<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
答案 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的警告。