在Factory函数中是对象名称和'this'关键字经常或总是可以互换?

时间:2018-04-21 02:56:15

标签: javascript this

以下代码不会引发错误,但我不完全确定原因。 在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());

3 个答案:

答案 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被假定为"这个",因为它是对象。