我是JavaScript的新手,目前正在研究动态范围的工作原理。现在,我了解了this
是如何获得其价值的。我已经阅读了所有规则并了解了大多数规则,但是我很难理解这段代码,这些代码解释了在装饰器中使用箭头函数和函数之间的区别。
这是代码https://javascript.info/arrow-functions的链接。
带有箭头功能的代码
function defer(f, ms) {
return function() {
//What is this? Why use apply?
setTimeout(() => f.apply(this, arguments), ms)
};
}
function sayHi(who) {
alert('Hello, ' + who);
}
let sayHiDeferred = defer(sayHi, 2000);
sayHiDeferred("John"); // Hello, John after 2 seconds
具有正常功能
function defer(f, ms) {
return function(...args) {
// What's the purpose of this line?
let ctx = this;
setTimeout(function() {
// Again why apply?
return f.apply(ctx, args);
}, ms);
};
}
这就是我难以理解的地方。
apply
?没有申请我们就不能做到吗? f
而不使用f.apply
会发生什么?apply
而使用setTimeOut
? 任何解释将不胜感激。
答案 0 :(得分:2)
实实在在的问题-您正在思考的好兆头。
为什么在两种情况下我们都使用Apply?我们不能在没有申请的情况下这样做吗?
值得一提的是,.apply
(及其同级.bind
)是从我们没有自动绑定到“ this”上下文的箭头功能开始的。所以,只要知道-他们来自更古老的时代。
现在,它们是做什么用的(申请/绑定)?当您要分配“ this”时,您实际上只需要它们。在您介绍的情况下,您没有引用this
-这意味着如果您简单地正常调用这些函数,您将得到相同的结果。这也解决了您的问题:
如果我简单地调用f而不是使用f.apply会发生什么?
什么都没有。您会有相同的结果。
由于setTimeOut,我们是否使用apply?
您似乎正在举一些在互联网上看到的示例-但简短的答案是:是的,您会使用。 .apply
或.bind
因为setTimeOut 而出现。但是您提供的示例隐藏了实际的课程。
这是尝试。
function iReferenceThisForStuff() {
console.log(this.foo)
}
setTimeout(iReferenceThisForStuff, 10)
// ...10ms pass
// "undefined" is logged because "this" references the global window object
在上面的示例中,我们向超时传递了一个非绑定函数,并记录了window.foo
,因为-在未明确设置的情况下-this
是对全局范围的引用。这是一种后备行为,非常奇怪-但这是它的工作方式。
使用.bind
和.apply
示例:
function iReferenceThisForStuff() {
console.log(this.foo)
}
setTimeout(iReferenceThisForStuff.bind({ foo: "bar" }), 10)
// ...10ms pass
// "bar" is logged because "this" references the object reference passed to `.bind`
// You could have also done...
setTimeout(function () {
return iReferenceThisForStuff.apply({ foo: "bar" }, /* maybe some additional args */)
}, 10)
// and you would have the same outcome.
关于箭头功能的最后注释。它们将this
绑定为this
,就像实例化它们的闭包中的(function () {
setTimeOut(() => { // This arrow function is instantiated in a closure where `this` is a reference to { foo: "bar" } and is automatically bound.
console.log(this.foo) // Will eventually log "bar"
})
}.bind({ foo: "bar" }))
一样。
Analytics.enabled = false; Analytics.initializeOnStartup = false;