【问题标题】:How to bind methods when destructuring an object in JavaScript?在 JavaScript 中解构对象时如何绑定方法?
【发布时间】:2017-08-27 22:52:20
【问题描述】:

在 JavaScript 中解构对象时如何绑定方法?

const person = {
  getName: function() {
    console.log(this);
  }
};

var a = person.getName;
var b = person.getName.bind(person);
var {getName: c} = person;

person.getName(); //=> {getName: [Function]}
a();              //=> window or global
b();              //=> {getName: [Function]}
c();              //=> window or global

我希望c 登录控制台它的“父”对象{getName: [Function]}

在一行destructuring中解构对象时,有什么方法可以绑定所有方法吗?

【问题讨论】:

  • 上下文在调用时给出。 var {getName:c} = person;var c = person.getName; 相同。如果您想为c 提供您选择的上下文,请使用.call.apply.bind
  • 我想不出除了 var {…} = autobindAllMethods(person) 的辅助函数

标签: javascript node.js ecmascript-6 this destructuring


【解决方案1】:

不,没有办法。与对象分离的函数失去了原始上下文。并且 JavaScript 中的析构没有语法来动态处理提取的值。

【讨论】:

  • 这将是一个很棒的功能!
【解决方案2】:

您可以在 get 时使用 getter 或代理来绑定方法,甚至使用解构。

两种解决方案都检查方法是否已绑定,方法是使用 String.startsWith() 在名称开头查找 bound。如果未绑定,则该方法将在返回之前绑定。

  1. 使用 getter 将方法自动绑定到对象。这需要为每个方法提供一个getter

const person = {
  prop: 5,
  _getName: function() {
    console.log(this.prop);
  },
  
  get getName() {
    // if not bound, bind the method
    if(!this._getName.name.startsWith('bound ')) {
      this._getName = this._getName.bind(this);
    }
    
    return this._getName;
  }
};

var a = person.getName;
var b = person.getName.bind(person);
var {getName: c} = person;

person.getName(); //=> 5
a();              //=> 5
b();              //=> 5
c();              //=> 5
  1. 使用proxy 将方法自动绑定到对象。为所有方法定义一次。

var handler = {
  get: function(target, prop, receiver) {
    // if method, and not bound, bind the method
    if(typeof target[prop] === 'function' && !target[prop].name.startsWith('bound ')) {
      target[prop] = target[prop].bind(target);
    }
    
    return target[prop];
  }
};

const person = new Proxy({
  prop: 5,
  getName: function() {
    console.log(this.prop);
  }
}, handler);

var a = person.getName;
var b = person.getName.bind(person);
var {getName: c} = person;

person.getName(); //=> 5
a();              //=> 5
b();              //=> 5
c();              //=> 5

【讨论】:

    【解决方案3】:

    有一个使用 ES6 类的简单解决方法。您可以在类构造函数中使用bind手动设置函数的上下文。

    在下面的示例中,getName() 将“幸存”解构:

    class Person {
      constructor() {
        this.getName = this.getName.bind(this);
      }
    
      getName() {
        console.log(this);
      }
    }
    
    const {
      getName
    } = new Person();
    
    getName(); // Person { getName: [Function: bound getName] }

    【讨论】:

      【解决方案4】:

      是的。假设我正确理解了您的问题,我们可以用一行代码完成此操作。

      这当然不是最易读的方法,但它是我在个人项目中经常使用的方法:

      const person = {
          getName: function() {
            console.log(this);
          }
        };
      
      // IIFE for destructuring and applying changes inline
      const { a, b, c } = (({ getName }) => ({ a: getName.bind(person), b: getName.bind(person), c: getName.bind(person) }))(person);
      

      现在我们称之为解构道具:

      a(); // { getName: [Function: getName] }
      b(); // { getName: [Function: getName] }
      c(); // { getName: [Function: getName] }
      

      这里发生了什么?如果该行令人困惑,请继续阅读...

      我们将所有内容都包装在一个 IIFE 中,该 IIFE 接受 person 对象作为输入;我们将 getName 属性拉入内联。1

      最后,我们使用getName 属性显式地将每个调用映射到bind - 从我们唯一的参数person 中提取 - 对应于a, b, c,我们正在从解析的IIFE 中解构它。

      1好吧,我可以说在这里作弊了,因为我们有两个解构“语句”,但最终在同一个表达式中解决

      【讨论】:

        【解决方案5】:

        只需使用箭头方法:

        const person = {
          getName: () => console.log(this),
        };
        

        【讨论】:

        • 您的代码中有错字。 getName:。将“=”替换为“:”
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-10-22
        • 1970-01-01
        • 1970-01-01
        • 2020-06-14
        • 1970-01-01
        • 2021-05-16
        • 2019-06-15
        相关资源
        最近更新 更多