【问题标题】:calling an object method from another method not working从另一个方法调用对象方法不起作用
【发布时间】:2021-09-25 18:56:48
【问题描述】:

假设我有以下编码场景:

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 方法?我一直不确定整个方法调用。

【问题讨论】:

  • 您在Math.pow 中使用的total 是什么?你没有定义它?

标签: javascript node.js object-initializers


【解决方案1】:

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

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

【讨论】:

  • 使用相同语法使用 await/async 需要什么 squareTotal 还是必须使用 function 关键字?这将如何改变语法?
  • 你可以在async前加上前缀,比如async squareTotal() { return Math.pow(this.total(), 2) }
【解决方案2】:

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

this.total()

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

这将适用于两个更改 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);

【讨论】:

    【解决方案3】:

    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

    【讨论】:

      【解决方案4】:

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

      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()}`);

      【讨论】:

        猜你喜欢
        • 2012-10-04
        • 1970-01-01
        • 2014-07-19
        • 2016-04-25
        • 2013-05-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-12-09
        相关资源
        最近更新 更多