[英]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.如果未绑定,该方法将在返回之前绑定。
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
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.