为了账号安全,请及时绑定邮箱和手机立即绑定

如何使用ES6类扩展函数?

如何使用ES6类扩展函数?

慕婉清6462132 2019-08-31 16:28:19
ES6允许扩展特殊对象。所以可以从函数继承。这样的对象可以作为函数调用,但是如何实现这种调用的逻辑呢?class Smth extends Function {  constructor (x) {    // What should be done here    super();  }}(new Smth(256))() // to get 256 at this call?类的任何方法都可以通过引用类实例this。但是当它被称为函数时,this指的是window。当作为函数调用时,如何获取对类实例的引用?
查看完整描述

3 回答

?
慕标琳琳

TA贡献1830条经验 获得超9个赞

这是我创建可调用对象的方法,这些对象正确引用其对象成员,并保持正确的继承,而不会弄乱原型。


只是:

class ExFunc extends Function {

  constructor() {

    super('...args', 'return this.__call__(...args)');

    return this.bind(this);

  }


  // Example `__call__` method.

  __call__(a, b, c) {

    return [a, b, c];

  }

}

扩展此类并添加一个__call__方法,更多信息......


代码和注释中的解释:

// A Class that extends Function so we can create

// objects that also behave like functions, i.e. callable objects.

class ExFunc extends Function {

  constructor() {

    // Here we create a dynamic function with `super`,

    // which calls the constructor of the parent class, `Function`.

    // The dynamic function simply passes any calls onto

    // an overridable object method which I named `__call__`.

    // But there is a problem, the dynamic function created from

    // the strings sent to `super` doesn't have any reference to `this`;

    // our new object. There are in fact two `this` objects; the outer

    // one being created by our class inside `constructor` and an inner

    // one created by `super` for the dynamic function.

    // So the reference to this in the text: `return this.__call__(...args)`

    // does not refer to `this` inside `constructor`.

    // So attempting:

    // `obj = new ExFunc();` 

    // `obj();`

    // Will throw an Error because __call__ doesn't exist to the dynamic function.

    super('...args', 'return this.__call__(...args)');

    

    // `bind` is the simple remedy to this reference problem.

    // Because the outer `this` is also a function we can call `bind` on it

    // and set a new inner `this` reference. So we bind the inner `this`

    // of our dynamic function to point to the outer `this` of our object.

    // Now our dynamic function can access all the members of our new object.

    // So attempting:

    // `obj = new Exfunc();` 

    // `obj();`

    // Will work.

    // We return the value returned by `bind`, which is our `this` callable object,

    // wrapped in a transparent "exotic" function object with its `this` context

    // bound to our new instance (outer `this`).

    // The workings of `bind` are further explained elsewhere in this post.

    return this.bind(this);

  }

  

  // An example property to demonstrate member access.

  get venture() {

    return 'Hank';

  }

  

  // 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 {

  get venture() {

    return 'Dean';

  }

  

  __call__(ans) {

    return [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) );  // [ 'Dean', 42 ]

进一步说明bind:

function.bind()工作很像function.call(),他们共享一个类似的方法签名:


fn.call(this, arg1, arg2, arg3, ...);更多关于mdn


fn.bind(this, arg1, arg2, arg3, ...);更多关于mdn


在第一个参数中重新定义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']`


查看完整回答
反对 回复 2019-08-31
?
开满天机

TA贡献1786条经验 获得超13个赞

您可以使用(也许)陷阱将Smth实例包装在Proxy中:applyconstruct


class Smth extends Function {

  constructor (x) {

    super();

    return new Proxy(this, {

      apply: function(target, thisArg, argumentsList) {

        return x;

      }

    });

  }

}

new Smth(256)(); // 256


查看完整回答
反对 回复 2019-08-31
  • 3 回答
  • 0 关注
  • 581 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号