我正在学习Javascript,我对“this”关键字感到有些困惑。我理解它指的是一个对象的特定实例,如果它被调用(即如果fido = new Dog(“Fido”),那么this.method将引用它被调用的特定对象。)
但是,我在Javascript.info上遇到了问题,他们有以下解决方案来实现函数原型的延迟包装器:
Function.prototype.defer = function(ms) {
let f = this; //*****
return function(...args) {
setTimeout(() => f.apply(this, args), ms); //****
}
};
// check it
function f(a, b) {
alert(a + b);
}
f.defer(1000)(1, 2); // shows 3 after 1 sec
我对解决方案中使用“this”感到困惑。在第一次调用中,(让f = this),它将f设置为函数的特定调用。但是,之后的2行,他们调用f.apply(this,args)。我很困惑他们为什么同时使用变量f以及实际的“this”关键字......他们所指的是什么区别?
谢谢!
编辑:练习说改变原型并不是一个好习惯,但它只是为了测试你的理解
Edit2:我也尝试过使用console.log(这个),它显示未定义。我很好奇为什么我需要它(输入“”而不是“this”实际上产生相同的结果,这就是为什么我感到困惑)
答案 0 :(得分:1)
正如其他评论和答案所指出的那样,有几篇好文章可以更详细地解释“this”关键字。但回答你的问题,第一个“this”(let f = this
)是指向函数f的指针,而第二个“this”(f.apply(this, args)
)是指向窗口对象的指针,因为setTimeout是一个函数窗口对象。
答案 1 :(得分:1)
我将在下面注释代码:
Function.prototype.defer = function(ms) {
// The function was called via a reference to a function, so the "this"
// pointer being captured in "f" will refer to the function that was to be
// deferred;
let f = this;
return function(...args) {
// The "this" pointer here refers to the global window object, since
// the anonymous function returned above didn't explicitly specify
// a this pointer via bind or other means
console.log(this);
setTimeout(() => {
// Because of the use of an arrow function, the "this" pointer here
// refers to whatever is the "this" pointer in the containing block
// Remember, f refers to the original function, so we're invoking it
// here
f.apply(this, args)
}, ms);
}
};
答案 2 :(得分:0)
基本上,这是因为'this'变化非常快。在setTimeout内部,它将与外部不同。你使用f(尽管大多数人会使用'self'或类似的东西)来锁定执行时特定点的'this'。
答案 3 :(得分:-1)
当defer
返回function
时,this
中的f.apply(this, args), ms)
将引用返回的function
所调用的范围。
示例:
function First () {
this.name = 'First';
}
First.prototype.defer = function(ms) {
const f = this;
return function() {
setTimeout(() => {
console.log('Names => ', f.name, this.name);
}, ms);
}
}
const first = new First();
function Second() {
this.name = 'Second';
}
const second = new Second();
second.deferby1000 = first.defer(1000);
second.deferby1000();
//姓名=> “第一”“第二”