gpt4 book ai didi

javascript - 使用 setPrototypeOf 进行数组子类化

转载 作者:行者123 更新时间:2023-11-28 19:25:24 25 4
gpt4 key购买 nike

所以我读了一些关于 subclassing Array in JavaScript 的博客文章、SO 线程和其他讲座。关于该主题的普遍观点是,没有办法创建具有某种缺点的子类。

在尝试一些事情时,我自己想出了这个解决方案:

// This is the constructor of the new class.
function CustomArray() {

// The "use strict" statement changes the way the "magic" variable
// "arguments" works and makes code generally safer.
"use strict";

// Create an actual array. This way the object will treat numeric
// properties in the special way it is supposed to.
var arr = [],
i;

// Overwrite the object's prototype, so that CustomArray.prototype is
// in the prototype chain and the object inherits its methods. This does
// not break the special behaviour of arrays.
Object.setPrototypeOf(arr, CustomArray.prototype);

// Take all arguments and push them to the array.
for (i = 0; i < arguments.length; i++) {
arr.push(arguments[i]);
}

// Return the array with the modified prototype chain. This overwrites
// the return value of the constructor so that CustomArray() really
// returns the modified array and not "this".
return arr;
}

// Make CustomArray inherit from Array.
CustomArray.prototype = Object.create(Array.prototype);

// Define a method for the CustomArray class.
CustomArray.prototype.last = function () {
return this[this.length - 1];
};

var myArray = new CustomArray("A", "B", 3);
// [ "A", "B", 3 ]

myArray.length;
// 3

myArray.push("C");
// [ "A", "B", 3, "C" ]

myArray.length;
// 4

myArray.last();
// "C"

我的问题是:这段代码有什么问题吗?我很难相信在这么多人在我之前搜索之后,我竟然想出了“唯一的解决方案”。

最佳答案

本文讨论了如何创建数组“子类”。也就是说,我们要创建一个具有 Array.prototype 的对象。在其原型(prototype)链中,但其直接原型(prototype)父级不是 Array.prototype (即,原型(prototype)父级可以提供数组原型(prototype)之外的其他方法)。

那篇文章说,创建数组“子类”的一个根本困难是数组从两者获取其行为

  1. 他们的原型(prototype),
  2. 只是数组实例。

如果数组继承了 Array.prototype 的所有行为,我们的工作会很快。我们只需创建一个原型(prototype)链包含 Array.prototype 的对象。 。该对象将为我们的数组子类实例创建一个理想的原型(prototype)。

但是,数组具有特殊的自动行为,这些行为对于数组实例来说是唯一的,并且不是从原型(prototype)继承的。 (特别是,我的意思是当数组更改时 length 属性周围的行为会自动更改,反之亦然。)这些是由 Array 创建每个数组实例时提供给每个数组实例的行为。构造函数,并且在 ECMAScript 5 中无法忠实地模仿它们。因此,数组子类 的实例必须最初由 Array 创建。构造函数。。如果我们想要合适的length,这是没有商量余地的。行为。

此要求与我们的其他要求相冲突,即实例必须具有不是 Array.prototype 的原型(prototype)。 (我们不想向 Array.prototype 添加方法;我们想要向使用 Array.prototype 作为其自己的原型(prototype)的对象添加方法。)在 ECMAScript 5 中,使用 Array 创建的任何对象。构造函数必须具有 Array.prototype 的原型(prototype)父级。 ECMAScript 5 规范没有提供在创建对象后更改其原型(prototype)的机制。

相比之下,ECMAScript 6 确实提供了这样的机制。您的方法与 __proto__ 非常相似文章中“Wrappers. Prototype chain injection.”部分中描述的基于方法,除非您使用 ECMAScript 6 的 Object.setPrototypeOf而不是__proto__ .

您的解决方案正确满足以下所有要求:

  1. 每个实例实际上都是一个数组(即由 Array 构造函数构建)。这确保 [[Class]]内部属性正确,且 length行为正确。
  2. 每个实例都有一个不是 Array.prototype 的直接原型(prototype),但仍包括Array.prototype在其原型(prototype)链中。

这些要求以前在 ES5 中是不可能满足的,但 ES6 使之变得相当容易。在 ES5 中,您可能有一个无法满足要求 #2 的数组实例,或者一个无法满足要求 #1 的普通对象。

关于javascript - 使用 setPrototypeOf 进行数组子类化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27985546/

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