在 ECMAScript 5 中模拟辅助构造函数

问题描述 投票:0回答:1

我正在阅读《JavaScript 权威指南》,遇到了这个辅助构造函数:

function SetFromArray(a) { 
    Set.apply( this, a ); 
}

SetFromArray.prototype = Set.prototype; 

//

var s = new SetFromArray( [1,2,3] ); 

console.assert( s instanceof Set ); // => true 

这是设置功能:

function Set() { 
    this.values = {}; 
    this.n = 0; 
    this.add.apply(this, arguments); 
} 

正文进一步说道:

在 ECMAScript 5 中,函数的 bind() 方法具有特殊的行为,允许它创建这种辅助构造函数。

这里指的是哪些特殊行为以及如何使用它来创建那种辅助构造函数?甚至可以在 JavaScript 中创建辅助构造函数吗?

我尝试使用bind()方法重新创建这个函数:

    function SetFromArray(a) {
         Set.bind(null).apply(this, a);
} 

但是后来,我意识到,为了利用 bind() 方法的行为(其中,boundFunction 在用作构造函数时继承原始原型),我必须在构造函数调用中使用boundfunction 作为构造函数,因此我定义的 SetFromArray 函数的工作方式可能与未绑定时定义的函数不同。

oop constructor ecmascript-5
1个回答
0
投票

这里指的是哪些特殊行为以及如何使用它来创建这种辅助构造函数?

从我们在该章末尾找到的单个短语来看,这一点并不明显,但我认为作者并不打算像您在尝试中那样使用

bind
,因为:

  • 这只会使
    SetFromArray
    更长的代码,同时仍然保留已经存在的相同代码。
  • 它立即调用
    bind
    返回的函数,这意味着您可以直接使用
    apply
    call
    来代替。
    bind
    用于以下场景:您立即调用它返回的函数,而是将其传递给其他代码段(如使用
    return
    ),然后该代码可能会调用它。

注意作者是如何写的 “...这允许它[即

bind
]创建这个...构造函数”,他们似乎建议您可以以某种方式调用
bind
来获取所需的构造函数作为返回值。所以他们暗示了类似的事情:

var SetFromArray = <something>.bind(<something>);

虽然乍一看这听起来很有希望——因为

bind
返回一个函数—— 有几个原因导致这是不可能的,包括:

  1. 当调用

    bind
    返回的函数时,数组参数不会像
    apply
    那样分散为单独的参数,但这种转换是首先拥有
    SetFromArray
    函数的全部意义。

  2. 如果我们想要解决上述问题,我们仍然需要调用

    apply
    ,结果如下:

    var SetFromArray = Function.apply.bind(<something>);
    

    但是

    apply
    不是构造函数,因此
    new SetFromArray([])
    会引发异常。即使它是一个构造函数,它也不会创建
    Set
    的实例。

  3. 在严格模式下(在现代开发中应该打开该模式),

    bind
    返回一个不是构造函数的函数,破坏了
    bind
    将为我们创建构造函数的整个想法。

老书,快速复习

这本书于 1996 年首次出版,而 ECMAScript 5 于 2009 年才出版。JavaScript: The Definitive Guide 的第 6 版于 2011 年出版,在其介绍中

第六版涵盖 HTML5 和 ECMAScript 5

您在第9章中引用的短语就是在这种情况下添加的。我怀疑作者/回归者是否在测试中添加了这一附加声明,只是想 “嘿,这里我们有另一个函数,它只是传递一些参数......让我们添加他们可以使用

bind
来给它一个现代的 ECMAScript 5味道!”

自 2011 年以来发生了很多变化:

  • Set
    现在是原生 ECMAScript 的一部分。不再需要引用的代码。我们可以使用
    new Set([1,2,3])
    创建一个新集合。
  • 参数可以使用 扩展语法 进行扩展,因此,如果我们有一个采用单独参数而不是数组的构造函数,我们就可以执行
    new MyConstructor(...myArray)
  • class
    extends
    ,减少了您仍然想修改
    prototype
    属性的原因。
  • 有私有字段和
    Symbol
    ,使得像
    prop = "|**objectid**|"
    这样的东西变得不必要

辅助构造函数

通过篡改原型链来提供辅助构造函数的想法看起来与良好的 OOP 设计背道而驰。如果我们看看 ECMAScript 本身是如何解决这个“问题”的,我们可以发现以下例子:

  • Array.from
    Array.of
    提供了创建
    Array
    实例的替代方法。
  • [
    Object.create
    ] 和 [
    Object.fromEntries
    ] 提供了创建普通对象的替代方法

这表明在 ECMAScript 中,static 函数是提供创建类实例的替代方法的标准方法。

© www.soinside.com 2019 - 2024. All rights reserved.