这是一种创建可调用对象的方法,这些对象可以正确引用其对象成员,并保持正确的继承,而不会弄乱原型。
只是:
class ExFunc extends Function {
constructor() {
super('...args', 'return this.__self__.__call__(...args)')
var self = this.bind(this)
this.__self__ = self
return self
}
// Example `__call__` method.
__call__(a, b, c) {
return [a, b, c];
}
}
扩展此类并添加一个方法,下面还有更多...__call__
代码和注释中的说明:
// This is an approach to creating callable objects
// that correctly reference their own object and object members,
// without messing with prototypes.
// A Class that extends Function so we can create
// objects that also behave like functions, i.e. callable objects.
class ExFunc extends Function {
constructor() {
super('...args', 'return this.__self__.__call__(...args)');
// Here we create a function dynamically using `super`, which calls
// the `Function` constructor which we are inheriting from. Our aim is to create
// a `Function` object that, when called, will pass the call along to an internal
// method `__call__`, to appear as though the object is callable. Our problem is
// that the code inside our function can't find the `__call__` method, because it
// has no reference to itself, the `this` object we just created.
// The `this` reference inside a function is called its context. We need to give
// our new `Function` object a `this` context of itself, so that it can access
// the `__call__` method and any other properties/methods attached to it.
// We can do this with `bind`:
var self = this.bind(this);
// We've wrapped our function object `this` in a bound function object, that
// provides a fixed context to the function, in this case itself.
this.__self__ = self;
// Now we have a new wrinkle, our function has a context of our `this` object but
// we are going to return the bound function from our constructor instead of the
// original `this`, so that it is callable. But the bound function is a wrapper
// around our original `this`, so anything we add to it won't be seen by the
// code running inside our function. An easy fix is to add a reference to the
// new `this` stored in `self` to the old `this` as `__self__`. Now our functions
// context can find the bound version of itself by following `this.__self__`.
self.person = 'Hank'
return self;
}
// An example property to demonstrate member access.
get venture() {
return this.person;
}
// Override this method in subclasses of ExFunc to take whatever arguments
// you want and perform whatever logic you like. It will be called whenever
// you use the obj as a function.
__call__(a, b, c) {
return [this.venture, a, b, c];
}
}
// A subclass of ExFunc with an overridden __call__ method.
class DaFunc extends ExFunc {
constructor() {
super()
this.a = 'a1'
this.b = 'b2'
this.person = 'Dean'
}
ab() {
return this.a + this.b
}
__call__(ans) {
return [this.ab(), this.venture, ans];
}
}
// Create objects from ExFunc and its subclass.
var callable1 = new ExFunc();
var callable2 = new DaFunc();
// Inheritance is correctly maintained.
console.log('\nInheritance maintained:');
console.log(callable2 instanceof Function); // true
console.log(callable2 instanceof ExFunc); // true
console.log(callable2 instanceof DaFunc); // true
// Test ExFunc and its subclass objects by calling them like functions.
console.log('\nCallable objects:');
console.log( callable1(1, 2, 3) ); // [ 'Hank', 1, 2, 3 ]
console.log( callable2(42) ); // [ 'a1b2', Dean', 42 ]
// Test property and method access
console.log(callable2.a, callable2.b, callable2.ab())
查看 repl.it
进一步说明:bind
function.bind()
工作原理与 非常相似,并且它们共享类似的方法签名:function.call()
fn.call(this, arg1, arg2, arg3, ...);
有关 mdn 的更多信息
fn.bind(this, arg1, arg2, arg3, ...);
有关 mdn 的更多信息
在这两种情况下,第一个参数都重新定义了函数内的上下文。其他参数也可以绑定到一个值。但是,如果立即调用具有绑定值的函数,则返回一个“exotic”函数对象,该对象透明地包装原始对象,并预设任何参数。this
call
bind
this
因此,当您定义一个函数时,它的一些参数:bind
var foo = function(a, b) {
console.log(this);
return a * b;
}
foo = foo.bind(['hello'], 2);
仅使用其余参数调用绑定函数,其上下文已预设,在本例中为 。['hello']
// We pass in arg `b` only because arg `a` is already set.
foo(2); // returns 4, logs `['hello']`