Javascript - 范围

时间:2013-10-15 22:13:58

标签: javascript oop methods event-handling

<script type="text/javascript">
function BigComputer(answer) {
   this.the_answer = answer;
   this.ask_question = function () {
   alert(this.the_answer);
   }
}

 function addhandler() {
   var deep_thought = new BigComputer(42),
   the_button = document.getElementById('thebutton');

   the_button.onclick = deep_thought.ask_question;
}

window.onload = addhandler;
 </script> 

为什么这个脚本会返回undefined而不是42? 这就是我如何理解:
1)在网页加载时,我们运行'addhandler'方法 2)在此方法中,我们为deep_thought变量创建BipComputer实例。我们在答案中设置了42(BipComputer类中的公共变量)
3)然后我们设置按钮的参考(在html文件内)
4)点击按钮激活,这里有魔力:
在我看来应该打印出数字42,因为我们刚刚在第2步中设置了这个,但不是变量是“未定义”吗?。

另一个问题是,运行没有()的方法(当没有传递参数时)和with()之间的区别是什么。 [像addhandler方法]。

也许这个问题很简单,但我过去常常在java和php中编程,现在我在面向javascript的编程思维方式对我来说很奇怪。函数看起来像类,类看起来像函数,没有真正的构造函数和东西。
但没关系,让我们回到问题:) 我真的很感激任何帮助。




@Edit

感谢@lbstr我找到了有用的链接,对于那些问我同样问题的人。 http://web.archive.org/web/20080209105120/http://blog.morrisjohns.com/javascript_closures_for_dummies

3 个答案:

答案 0 :(得分:6)

触发点击处理程序时,this是按钮。这是你想要做的:

function BigComputer(answer) {
    this.the_answer = answer;
    var self = this;
    this.ask_question = function() {
        alert(self.the_answer);
    };
}

封闭的精彩使这一切成为可能。许多js粉丝都认为这是该语言的最佳部分。 Read all about 'em

将范围与this区分开来很重要。虽然变量是按函数确定的,但this在给定的范围链中不一定相同。一个简单的例子是,我可以使用我想要的任何this值来调用我想要的任何函数:

someFunc.call(someThis); // call someFunc, using someThis for this

对于事件处理程序,this通常是事件发起的元素。这很好,因为您可能在页面上有几个按钮,并且您想要对单击的按钮执行某些操作。

答案 1 :(得分:4)

问题在于分配后

the_button.onclick = deep_thought.ask_question;

单击该按钮时,将调用分配给onclick属性的函数,并将this绑定到该按钮。您可以(至少)以三种方式解决问题:

  • 通过重写函数(如the answer by lbstr

  • 使用bind创建一个使用所需ask_question执行this的新函数:

    the_button.onclick = deep_thought.ask_question.bind(deep_thought);
    

    请注意bind是JS 1.8.5的新功能;上面的链接有一个旧的JS引擎垫片。

  • 编写一个闭包来获取this内的正确ask_question

    the_button.onclick = function() { deep_thought.ask_question(); };
    
    编辑:正如RobG在评论中指出的那样,这段代码会在某些浏览器(特别是许多版本的MSIE)中造成内存泄漏。修复方法是完全消除变量the_button

    document.getElementById('thebutton').onclick = function() {
        deep_thought.ask_question();
    };
    

    有关其他方法,请参阅this tutorial

答案 2 :(得分:0)

当您从按钮单击指定要执行的ask_question()时,“this”将是按钮的上下文,而不是基于构造函数的deep_thought变量的上下文。如果从this.the_answer删除“this”并将其设为var,则会收到42的警告。