2

更多地了解 Javascript 和 OO 编程,但我不明白为什么我的 ojbect 的这种行为(myUser 无法访问属性 this.first_name 作为 'jon' 而是未定义(在底部的屏幕截图中以红色突出显示) .这是有问题的代码片段:

function User(first_name, last_name){
    this.first_name=first_name;
    this.last_name=last_name;
}

// left in for completeness
User.prototype = {
    constructor: User,
    sayName: function(){
        console.log("My Name: " + this.first_name + " and " + this.last_name);
    }

}

User.prototype.whoWhat = function(){
    console.log(this.first_name + " I want to tell you now " + Math.random());
}

var myUser=new User('jon', 'johnson');
myUser.sayName();
myUser.whoWhat();
setInterval(myUser.whoWhat, 3000);

这是控制台输出:

在此处输入图像描述

4

3 回答 3

6

问题是您的setInterval()回调失去了与您构建的对象的关联。函数与作为属性值的对象的关联影响this何时使用该属性值进行函数调用。在这里,您只是在引用值(即获取对函数的引用)。当系统调用函数时,this将是undefined(或window对象,取决于“严格”模态)。

this您可以使用包装函数确保这是正确的值:

  setInterval(function() { myUser.whoWhat(); }, 3000);

在较新的浏览器中,您可以使用 Function 原型中的方法bind()

  setInterval(myUser.whoWhat.bind(myUser), 3000);

这具有(出于您的目的)相同的效果,尽管bind()也可以做其他事情。

要记住的关键是,在 JavaScript 中,函数和对象之间没有长期的关系。对函数的引用只是普通值,不会因为函数恰好被定义为原型对象或对象字面量的属性而发生任何特殊情况。唯一重要的是如何实际调用函数。

于 2013-08-17T16:58:00.280 回答
3

这种行为在 MDN 文档中被称为“this”问题:

由 setInterval() 执行的代码在与调用它的函数不同的执行上下文中运行。因此,被调用函数的 this 关键字将被设置为窗口(或全局)对象,它不会与调用 setTimeout 的函数的 this 值相同。

https://developer.mozilla.org/en-US/docs/Web/API/window.setInterval

于 2013-08-17T17:02:08.050 回答
2

当您访问一个作为函数的属性时,如果您直接调用它,或者您保留引用并稍后调用它,则会有所不同。

当你直接调用它时,对象被用作上下文,但如果你保留引用以供以后它不再与对象关联,并且当你调用它时,它将与全局对象(窗口)一起调用语境。

解决方案是在 setTimeout 调用中使用的函数中调用方法:

setInterval(function(){ myUser.whoWhat(); }, 3000);
于 2013-08-17T17:08:08.140 回答