gpt4 book ai didi

javascript - 如何在不同的上下文中使用 es6 构造函数指令

转载 作者:数据小太阳 更新时间:2023-10-29 05:24:23 25 4
gpt4 key购买 nike

是否可以通过更改“this”上下文(调用、应用或其他)在另一个实例上使用 es6 构造函数指令?这可以使用 es5“类”。这是我的意思的一个小例子:

function ES5() {
this.foo = 'foo';
}

class ES6 {
constructor() {
this.bar = 'bar';
}
}

var a = new ES6();
ES5.call(a);
console.log(a.foo + a.bar); //foobar



var b = new ES5();
//Reflect.construct(ES6); ??
ES6.call(b); //TypeError: Class constructor ES6 cannot be invoked without 'new'

console.log(b.foo + b.bar); //how to get foobar here too?


编辑:
我的问题与 new 关键字无关。我正在寻找的答案是如何使用另一个“this”上下文(带或不带 new 关键字)运行放置在 es6 构造函数中的指令。

最佳答案

正如评论和您自己所指出的,尝试使用自定义 this 调用类构造函数如果有任何解决方法,上下文真的不是你想要尝试的东西。这是故意变硬的!

如果由于某些原因这是不可避免的,足以证明棘手的解决方法是合理的,您可以在下面找到两个部分解决方案。它们都以自己的方式不完美 - 根据您的具体情况,其中之一可能仍然适合您的需求。

解决方法 1

虽然无法设置 this直接在构造函数调用中,可以设置this的原型(prototype)到您选择的对象 .

为此,您可以使用 Reflect.construct()调用内部[[Construct]]自定义方法new.target值(value)。 this然后将初始化为继承自 new.target.prototype 的对象.

以您的示例为基础:

function ES5() {
this.foo = 'foo';
}

class ES6 {
constructor() {
this.bar = 'bar';
}
}

let b = new ES5();

function TemporaryHelperConstructor() {}
TemporaryHelperConstructor.prototype = b;

b = Reflect.construct( ES6, [], TemporaryHelperConstructor ); // The third argument corresponds to the value of new.target

console.log( b.foo + b.bar ); // foobar !


( Reflect.construct() 和内部 [[Construct]] 方法的确切工作原理在规范的 26.1.29.2.2 部分中进行了描述)

潜在问题
  • 类构造函数实际上并未使用 this 调用绑定(bind)到b , 它被称为 this绑定(bind)到直接继承自 b 的空对象.如果您或类构造函数依赖于 Object.getOwnPropertyNames() 之类的方法,这可能会导致问题。 , Object.getPrototypeOf()


  • 解决方法 2

    虽然不可能调用内部 [[Call]]类构造函数的方法而不会导致 TypeError , 可以提取附加到类构造函数的代码块并从中创建一个普通函数,然后您可以使用自定义 this 调用它捆绑。

    您可以使用 Function.prototype.toString()方法将类构造函数的代码块提取为字符串。 Function()然后构造函数可以从这个字符串中创建一个普通函数,您可以使用自定义 this 调用它通过 Function.prototype.apply()绑定(bind).

    以您的示例为基础:

    function ES5() {
    this.foo = 'foo';
    }

    class ES6 {
    constructor() {
    this.bar = 'bar';
    }
    }

    const b = new ES5();

    const constructorBody = ES6.toString().match( /(?<=constructor\(\) ){[^}]*}/ )[0]
    const ordinaryFunction = Function( constructorBody )

    ordinaryFunction.apply( b ); // No TypeError

    console.log( b.foo + b.bar ); // foobar !


    请注意,此代码段出于演示目的使用了一个极其简化的正则表达式。为了使事情变得健壮,您需要考虑字符串和注释中的嵌套花括号和花括号。如果需要,您还需要提取构造函数参数。

    (根据规范的 19.2.3.5 部分,您可以依赖 Function.prototype.toString() 的足够一致的输出,以使这种方法跨实现工作。)

    潜在问题
  • new.target将设置为 undefined在执行普通函数时(与 [[Call]] 调用一样),如果类构造函数使用它可能会导致问题。
  • 原始类构造函数的闭包将丢失给使用 Function() 创建的新函数( MDN ),这可能会导致 ReferenceErrors如果类构造函数依赖它们。
  • 这种方法将导致 SyntaxError如果使用 super() 应用于派生类,这在普通函数中是无效的语法。


  • 结论

    您的问题没有完美的解决方案。如果您的用例足够简单,那么您仍然可以实现您想要的。部分解决方法会带来它们自己的有害问题 - 小心行事!

    关于javascript - 如何在不同的上下文中使用 es6 构造函数指令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54622443/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com