进一步了解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);
这是控制台输出:
答案 0 :(得分:6)
问题是你的setInterval()
回调失去了与你构建的对象的关联。当使用属性值进行函数调用时,函数与对象的关联作为属性值仅会影响this
。在这里,您只是引用该值(即获取对该函数的引用)。当系统调用该函数时,this
将是undefined
(或window
对象,具体取决于“严格”模式。
您可以使用包装函数确保this
是正确的值:
setInterval(function() { myUser.whoWhat(); }, 3000);
在较新的浏览器中,您可以使用名为bind()
的函数原型中的方法:
setInterval(myUser.whoWhat.bind(myUser), 3000);
虽然bind()
可以做其他事情,但是(为了你的目的)也有同样的效果。
要记住的关键是,在JavaScript中,函数和对象之间没有长期关系。对函数的引用只是普通的值,没有什么特别的事情发生,因为函数碰巧被定义为原型对象或对象文字的属性。唯一重要的是如何实际调用函数。
答案 1 :(得分:3)
此行为在MDN文档中称为“this”问题:
setInterval()执行的代码在单独的执行上下文中运行 到它被调用的函数。结果,这个 被调用函数的关键字将被设置为窗口(或全局) 对象,它不会与函数的this值相同 这叫做setTimeout。
https://developer.mozilla.org/en-US/docs/Web/API/window.setInterval
答案 2 :(得分:2)
当您访问属于某个函数的属性时,如果您直接调用它,或者如果您保留该引用并稍后调用它,则会有所不同。
当你直接调用它时,该对象被用作上下文,但如果你保留引用以供日后使用它不再与该对象相关联,并且当你调用它时,它将被调用全局对象(窗口)作为上下文。
解决方法是在函数中调用方法,以便在setTimeout调用中使用:
setInterval(function(){ myUser.whoWhat(); }, 3000);