创建具有不同范围的ES6 / ESNext原型函数(不是内联函数) [英] Create ES6/ESNext prototype function with different scope (not an inline function)

查看:62
本文介绍了创建具有不同范围的ES6 / ESNext原型函数(不是内联函数)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好的说我们有这个:

class Car {
    constructor(name) {
        this.kind = 'Car';
        this.name = name;
    }

    printName() {
        console.log('this.name');
    }
}

我想要做的是定义printName,类似于这个:

what I want to do is define printName, something like this:

class Car {
    constructor(name) {
        this.kind = 'Car';
        this.name = name;
    }

    // we want to define printName using a different scope
    // this syntax is close, but is *not* quite correct
    printName: makePrintName(foo, bar, baz) 
}

其中makePrintName是一个仿函数,如下所示:

where makePrintName is a functor, something like this:

exports.makePrintName = function(foo, bar, baz){
   return function(){ ... }
};

ES6可以实现吗?我的编辑器和TypeScript不喜欢这个

is this possible with ES6? My editor and TypeScript is not liking this

注意:使用ES5,这很容易做到,看起来像这样:

var Car = function(){...};

Car.prototype.printName = makePrintName(foo, bar, baz);

使用类语法,目前最适合我的是:

Using class syntax, currently the best thing that is working for me, is this:

const printName = makePrintName(foo,bar,baz);

class Car {
  constructor(){...}
  printName(){
    return printName.apply(this,arguments);
  }
}

但这并不理想。 如果您尝试使用类语法来执行ES5语法可以执行的操作,您将看到问题。因此,ES6类包装器是一个漏洞抽象。

要查看真实用例,请参阅:

To see the real-life use case, see:

https://github.com/sumanjs/suman/blob/master/lib/test-suite-helpers/make-test-suite.ts#L171

使用 TestBlock.prototype.startSuite = ... 的问题是,在这种情况下,我不能简单地在线返回该类:

the problem with using TestBlock.prototype.startSuite = ..., is that in that case, I cannot simply return the class on line:

https://github.com/sumanjs/suman/blob/master/lib/test-suite-helpers/make-test-suite.ts#L67

推荐答案

我还没有提到的另一个想法是使用方法装饰器。以下装饰器采用方法实现并根据需要将其放在原型上:

Another idea I haven't seen mentioned yet is to use a method decorator. The following decorator takes a method implementation and puts it on the prototype, as desired:

function setMethod<T extends Function>(value: T) {
    return function (target: any, propertyKey: string, descriptor: TypedPropertyDescriptor<T>): void {
      descriptor.value = value;
      delete descriptor.get;
      delete descriptor.set;
    };
}

将它放在某个库中。以下是你如何使用它:

Put it in a library somewhere. Here's how you'd use it:

class Car {
    constructor(name) {
        this.kind = 'Car';
        this.name = name;
    }

    @setMethod(makePrintName(foo, bar, baz))
    printName() {} // dummy implementation
}

唯一的缺点是你必须在类中使用正确的签名放置方法的虚拟实现,因为装饰器需要一些东西装饰。但它在运行时的行为与您想要的完全相同(它不是为每个实例花费新函数定义的实例方法,或者是在每次使用时花费额外函数调用的访问器)。

The only downside is that you have to put a dummy implementation of the method with the right signature in the class, since the decorator needs something to decorate. But it behaves exactly as you want at runtime (it isn't an instance method which costs a new function definition for each instance, or an accessor which costs an extra function call at each use).

这有帮助吗?

这篇关于创建具有不同范围的ES6 / ESNext原型函数(不是内联函数)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆