简体   繁体   English

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

[英]How to bind methods when destructuring an object in JavaScript?

How to bind methods when destructuring an object in JavaScript?在 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

I want c to log in the console its "parent" object {getName: [Function]} .我希望c在控制台中登录其“父”对象{getName: [Function]}

Is there any way to bind all methods when destructuring an object in one destructuring line?在一个解构行中解构一个对象时,有没有办法绑定所有方法?

No, there is no way.不,没有办法。 Functions detached from objects lose the original context.与对象分离的函数会丢失原始上下文。 And destructing in JavaScript has no syntax to do something with extracted values on the fly. JavaScript 中的析构没有语法来动态处理提取的值。

You can use a getter or a proxy to bind a method whenever you get it, even using destructuring.您可以使用一个getter或代理结合的方法,只要你get它,甚至用解构。

Both solutions check if method is already bound, by looking for bound at the start of the name using String.startsWith() .两种解决方案都通过使用String.startsWith()在名称的开头查找bound检查方法是否已经绑定。 If not bound, that method will be bound before returning it.如果未绑定,该方法将在返回之前绑定。

  1. Auto-bind the method to the object with a getter.使用 getter 将方法自动绑定到对象。 This will require a getter for each method.这将需要每个方法都有一个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. Auto-bind the method to the object with a proxy .使用代理将方法自动绑定到对象。 Define once for all methods.为所有方法定义一次。

 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

There is a simple workaround using ES6 classes.使用 ES6 类有一个简单的解决方法。 You can use bind in the class constructor to manually set the context of the function.您可以在类构造函数中使用bind手动设置函数的上下文。

In the example below, getName() will "survive" the destructuring :在下面的示例中, getName()将“幸存”解构:

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

Yes.是的。 We can do this with a single line of code, assuming I understood your question correctly.假设我正确理解了你的问题,我们可以用一行代码来做到这一点。

This certainly isn't the most readable approach, but it's a method that I use often in my personal projects:这当然不是最易读的方法,但它是我在个人项目中经常使用的方法:

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);

Now we call the destructured props:现在我们调用解构的 props:

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

What's happening here?这里发生了什么? If that line was confusing, read on...如果该行令人困惑,请继续阅读...

We are wrapping everything in an IIFE which accepts as input the person object;我们将所有东西都包装在一个 IIFE 中,它接受person对象作为输入; we pull the getName prop inline.我们内联拉取getName道具。 1 1

Finally, we are explicitly mapping each call to bind using the getName prop - as pulled from our sole argument, person - to correspond to a, b, c , which we are destructuring away from the resolved IIFE.最后,我们使用getName属性显式地将每个调用映射到bind - 从我们唯一的参数person提取 - 对应于a, b, c ,我们正在从解析的 IIFE 中解构它。

1 OK so I've arguably cheated here in that we have two destructuring "statements" but which are ultimately resolved in the same expression 1好的,所以我可以说我在这里作弊了,因为我们有两个解构“语句”,但最终在同一个表达式中解决

Just use an arrow method:只需使用箭头方法:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM