Javascript绑定到对象
我尝试了这个例子,当我这样做时,我得到了以下消息Javascript绑定到对象,javascript,Javascript,我尝试了这个例子,当我这样做时,我得到了以下消息未定义的岩石而不是红宝石。 你能解释一下原因吗。函数执行上下文和this关键字 JavaScript函数在调用时有一个执行上下文,使得this关键字绑定到调用它们的对象。如果调用john.says()函数的执行上下文将有一个this关键字指向john。如果将全局变量func指定给对象john上的方法表示,则已将执行上下文更改为全局对象。调用func函数时,此将取消对窗口的引用(或未定义的*),并且由于窗口.skill未定义,表示将强制将该值转换为字
未定义的岩石代码>而不是红宝石代码>。
你能解释一下原因吗。函数执行上下文和this
关键字
JavaScript函数在调用时有一个执行上下文,使得this
关键字绑定到调用它们的对象。如果调用john.says()
函数的执行上下文将有一个this
关键字指向john
。如果将全局变量func
指定给对象john
上的方法表示
,则已将执行上下文更改为全局对象。调用func
函数时,此将取消对窗口的引用(或未定义的*),并且由于窗口.skill
未定义,表示
将强制将该值转换为字符串,以将其与字符串“rocks!”连接起来
如何使用bind保证执行上下文
您可以将函数的副本绑定到对象(有效地锁定其上下文引用):
如何使用闭包保证执行上下文
或者,您可以通过在构造函数中使用闭包来关闭相关位:
var func = john.says.bind(john);
如何使用闭包保证值
您可以直接从方法中引用skill
值,因此根本不需要上下文:
function Developer(skill){
var _this = this; // we keep a reference here
this.skill = skill;
this.says = function(){
alert(_this.skill + ' rocks!');
// when invoked _this refers to the context at construction
}
return this;
}
如何使用call和apply在调用时保证执行上下文
最后一个选项是在调用时使用所需的上下文调用该方法:
function Developer(skill){
// because skill is defined in this context, says will refer to this context
// to get the value of the skill variable.
this.says = function(){
alert(skill + ' rocks!');
}
}
如何使用原型来允许动态执行上下文设置正确的
如果我们想在对象实例或类型之间重用方法,但在调用时具有正确的执行上下文,那么可以使用prototype属性
func.call(john /*, optional arguments... */);
func.apply(john /*, optional arguments as an array */);
更多阅读:
- 执行上下文规范:
- MDN文档关于此:
*“use strict”激活一个表示JavaScript未来的特殊strict模式。当未设置上下文时,此特殊的严格执行环境将不会解析为全局对象,而是将其解析为适当范围的值未定义,因为func()
仅具有该函数,而不具有任何其他相关信息。(This.skill)
上下文丢失了调用says()
时,此
引用了john
但是现在,当您调用func()
时,此
指的是窗口
。因此,this.skills
将返回undefined
,除非您有一个同名的全局变量。试试这个
function Developer(skill){
this.skill = skill;
this.says();
}
Developer.prototype.says = function(){
alert(this.skill + ' rocks!');
}
var john = new Developer("Ruby"); // alert("Ruby rocks!")
var tony = new Developer("JavaScript"); // alert("JavaScript rocks!")
工作演示
调用函数时,此
将引用调用函数的对象
当你说
function Developer(skill) {
this.skill = skill;
this.says = function() {
alert(this.skill + ' rocks!');
}
}
var john = new Developer('Ruby');
john.says();
您只是得到函数对象(它不记得定义它的对象)
当你调用函数时,就像这样
var func = john.says;
func();
没有调用func
的当前对象。因此,默认情况下,JavaScript将全局对象(window
浏览器中的对象)指定为this
。由于在全局对象中未定义skill
,因此返回undefined
注意:在严格模式下,如果没有当前对象,此将是未定义的
这就是为什么我们必须显式地将对象绑定到函数,如下所示
var func = john.says;
func();
Function.prototype.bind
将返回一个绑定到john
的新函数。因此,当您调用此时,此将引用john
让我们通过实际返回对象来说明发生了什么:
func.bind(john)();
好吧,那为什么我们没有定义呢?好吧,一旦我们删除了函数,它就不再有上下文-它不知道这是什么。如果我们要这样做:
function Developer(skill) {
this.skill = skill;
this.says = function() {
alert(this.skill + ' rocks!');
}
return this; //this is basically { skill: skill, says: function() {} }
}
var john = new Developer('Ruby');
var func = john.says; // all it knows is the function() part, has no knowledge of skill
func(); //undefined rocks!
然后我们传入John作为这个
参数。解决方法是,在创建函数时将值传递给函数:
func.apply(john);
函数开发人员(技能){
这个技能=技能;
this.says=function(skill){/保持上述模式的最快方法是将this
直接绑定到方法this.says=function(){…}.bind(this);
:
。它已经以“在大多数情况下,this
的值取决于函数的调用方式”开头。也许下面的答案可以帮助您理解JavaScript原型和构造函数。虽然这可能最终“解决”OP的问题,但它并没有回答他的问题。“this
不再指john
对象”是迂腐的,它从一开始就没有指john
,因为它在函数调用之前根本不存在。@FelixKling,我已经更新了我的答案。“迂腐”是什么意思“?哦,我的意思是,我在批评一件其他人可能根本没有注意到的小事;)当通过new
关键字创建对象时,调用意味着将返回新创建的上下文对象。因此,您不需要“需要”在开发人员方法的底部返回它(尽管这不会影响安全性)。
function Developer(skill) {
this.skill = skill;
this.says = function () {
alert(this.skill + ' rocks!');
}.bind(this);
}
var john = new Developer('Ruby');
var func = john.says;
func(); // Ruby rocks!