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

问题描述

假设我有以下编码场景:

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 方法?对于整个方法调用,我一直未定义。

解决方法

有一个未定义的 total 函数被称为 Math.pow 的参数。如果你打算调用对象的成员,那么你需要指定,目前,它是一个变量引用,而不是一个属性.

您可以使用 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);  

,

squareTotal() 内部调用时,如您的示例所示,您可以:

this.total()

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

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

const test = () => {
    return (
        var1,squareTotal: function() {
                return Math.pow(this.total(),2);
            },})
    }
}

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

,

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

您可以使用以下代码:

const test = () => {
    return (
        var1,squareTotal: function() {return Math.pow(this.total(),2) }
        })
    }
}    

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

console.log(obj3);

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

,

如果您想访问同一对象内的属性,请不要使用箭头函数:它们不能使用对象的 scope。这是工厂函数的简化,其中 total 是一个 getter,而 squareTotal 是实例的函数表达式。

const test = () => {
  return (var1,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,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,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,get total() {
        return this.var1 + this.var2;
      },};
  };
};
const x = test2()(1,2);
console.log(`x.sqareTotal(): ${x.squareTotal()}`);
x.var2 = 15;
console.log(`x.var2: ${x.var2}; x.squareTotal():  ${x.squareTotal()}`);