从另一个不起作用的方法调用对象方法

calling an object method from another method not working

假设我有以下编码场景:

export const test = () => {
    return (
        var1,
        var2,
        var3
    ) => {
        return Object.freeze({
            getVarOne: () => var1,
            getVarTwo: () => var2,
            getVarThree: () => var3,
            total: () => var1 + var2 + var3,
            squareTotal: () => Math.pow(total(), 2)
        })
    }
}

let obj1 = test();
let obj2 = obj1(1, 2, 3);
let obj3 = obj2.squareTotal();

我可以从 squareTotal 方法访问 total 方法的方法是什么?对于整个方法调用,我一直未定义。

当您在示例中调用时,从 squareTotal() 内部,您可以执行以下操作:

this.total()

this 将是 obj2,这是具有 total 方法的冻结对象。但是,您还需要停止对任何希望引用您自己的对象的方法使用箭头函数,因为箭头函数使用 this 的词法值,而不是 this.[=21= 的被调用对象值]

这将适用于两个更改 1) 更改为 this.total() 和 2) 将 squareTotal() 更改为常规函数 - 而不是箭头函数,因此它具有 this 的正确值:

const test = () => {
    return (
        var1,
        var2,
        var3
    ) => {
        return Object.freeze({
            getVarOne: () => var1,
            getVarTwo: () => var2,
            getVarThree: () => var3,
            total: () => var1 + var2 + var3,
            squareTotal: function() {
                return Math.pow(this.total(), 2);
            },
        })
    }
}

let fn = test();
let obj2 = fn(1, 2, 3);
let result = obj2.squareTotal();
console.log(result);

total 不是可以像 total() 那样调用的全局函数。如果要从要返回的 object 访问 total 方法,请调用 this.total()。但请确保不要使用箭头函数表达式。

您可以使用以下代码:

const test = () => {
    return (
        var1,
        var2,
        var3
    ) => {
        return Object.freeze({
            getVarOne: () => var1,
            getVarTwo: () => var2,
            getVarThree: () => var3,
            total: () => var1 + var2 + var3,
            squareTotal: function() {return Math.pow(this.total(), 2) }
        })
    }
}    

let obj1 = test();
let obj2 = obj1(1, 2, 3);
let obj3 = obj2.squareTotal();

console.log(obj3);

从箭头函数更改的原因是,箭头函数从其声明的词法范围中获取 this。在这里它应该属于 window object。对于任何其他方法,this 取决于它们的调用方式(此处它们由对象调用)。 Relevant SO answer

有一个未定义的 total 函数作为 Math.pow 的参数调用。如果您打算调用对象的 member,那么您需要指定它是一个 variable 引用,而不是 属性.

你可以使用 this,但是你必须使方法成为标准的 function 而不是箭头函数——你可以使用 ES6 对象方法符号(省略 function关键字):

const test = () => {
    return (
        var1,
        var2,
        var3
    ) => {
        return Object.freeze({
            getVarOne: () => var1,
            getVarTwo: () => var2,
            getVarThree: () => var3,
            total: () => var1 + var2 + var3,
            squareTotal() { return Math.pow(this.total(), 2) }   
        })
    }
}

let obj1 = test();
let obj2 = obj1(1, 2, 3);
let obj3 = obj2.squareTotal();

console.log(obj3);  

如果您想访问同一对象内的属性,请不要使用箭头函数:它们不能使用对象的 scope. Here is a simplification of you factory function, where total is a gettersquareTotal 实例的函数表达式。

const test = () => {
  return (var1, var2, var3) => {
    return Object.freeze({
      get total() {
        return var1 + var2 + var3;
        // ^ because the object is frozen
        //   var1 ... var3 don't have to be
        //   part of the object. Values are
        //   retrieved from closed over 
        //   parameter values
      },
      squareTotal() {
        return Math.pow(this.total, 2);
      },
    });
  };
}

const obj1 = test();
const obj2 = obj1(1, 2, 3);
console.log(`obj2.squareTotal(): ${obj2.squareTotal()}`);

// btw: because of the closure, the factory can 
// be simplified to a one liner too:
const test1a = () => (v1, v2, v3) => Object.freeze({
    squareTotal: () => Math.pow(v1 + v2 + v3, 2), });
const obj1a = test1a()(1, 2, 3);
console.log(`obj1a.squareTotal(): ${obj1a.squareTotal()}`);

// note: getter is not useful in a frozen object,
// but if the properties may change later it can be
// because in that case 'total' always gives the current
// total

const test2 = () => {
  return (var1, var2) => {
    return {
      var1,
      var2,
      get total() {
        return this.var1 + this.var2;
      },
      squareTotal() {
        return Math.pow(this.total, 2);
      },
    };
  };
};
const x = test2()(1, 2);
console.log(`x.sqareTotal(): ${x.squareTotal()}`);
x.var2 = 15;
console.log(`x.var2: ${x.var2}; x.squareTotal():  ${x.squareTotal()}`);