以下代码不会引发错误,但我不完全确定原因。
在doubleIt
方法中,我使用对象的名称returnObject
而不是this
。
实例化newInstance
后,我希望将术语returnObject
复制到新的doubleIt
方法中。因为returObject
仅存在于工厂函数中,如果从doubleIt
调用newInstance
,则会混淆JS引擎并引发错误。但它没有,它工作正常。为什么这仍然有效?
"use strict"
function factoryFunction(x) {
let returnObject = {
oneParameter: x,
doubleIt: () => returnObject.oneParameter * 2
// doubleIt: () => this.oneParameter * 2
// Why don't I have to use the 'this' version?
}
return returnObject;
}
let newInstance = factoryFunction(10);
console.log(newInstance.doubleIt());
答案 0 :(得分:5)
javascript处理此类情况的方式在this等文档中详细描述。
对于大多数人来说,这并不容易解析,但要点是首先处理作业的左侧。因此,在您的示例中,returnObject
获取对该对象的引用。之后,评估对象的值。因此,它看到您正在使用它已经具有引用的returnObject
,并且能够在运行时查找oneParameter
属性。所有这些都在closure中捕获,这意味着返回的对象可以访问名称returnObject
。
为了表明它实际上是在运行时进行评估,您可以更改oneParameter
然后调用该函数。它按预期工作:
"use strict"
function factoryFunction(x) {
let returnObject = {
oneParameter: x,
doubleIt: () => returnObject.oneParameter * 2
// doubleIt: () => this.oneParameter * 2
// Why don't I have to use the 'this' version?
}
return returnObject;
}
let newInstance = factoryFunction(10);
newInstance.oneParameter = 100
console.log(newInstance.doubleIt());

此外,returnObject
未复制到新doubleIt
- doubleIt
,只有一个指向returnObject
的引用。
答案 1 :(得分:2)
闭包捕获其环境变量。由于returnObject被定义为闭包之外的变量,因此它将被闭包捕获。
在这种情况下会发生的是,将创建一个循环引用,其中闭包doubleIt()将引用returnObject,而returnObject将引用doubleIt()。
关于"这个",在你的例子中,它引用了窗口对象,因为没有使用" new"调用工厂函数。如果使用" new"调用它,那么它将引用factoryFunction。但是,它永远不会引用returnObject,因为从不使用" new"调用returnObject本身。为了得到这个"这个"指向doubleIt()中的returnObject,您需要为将使用new调用的returnObject定义一个函数。如果您使用或不使用" new"调用factoryFunction,则以下代码段将起作用:
function factoryFunction(x) {
let returnObject = function(x) {
this.oneParameter = x;
this.doubleIt = () => this.oneParameter * 2;
};
return new returnObject(x);
}
let newInstance = factoryFunction(10);
let anotherNewInstance = new factoryFunction(10);
console.log(newInstance.doubleIt());
console.log(anotherNewInstance.doubleIt());

答案 2 :(得分:1)
JavaScript对象方向与" classic"不同。面向对象。当你创建新对象时,returnObject被假定为"这个",因为它是对象。