子类化Javascript数组.TypeError:Array.prototype.toString不是通用的

Tau*_*ren 34 javascript inheritance

是否可以从javascript数组继承和继承?

我想拥有自己的自定义Array对象,它具有Array的所有功能,但包含其他属性.myobj instanceof CustomArray如果实例是我的CustomArray,我将用于执行特定操作.

在尝试子类化并遇到一些问题后,我发现Dean Edwards的这篇文章指出使用Array对象执行此操作无法正常工作.事实证明,Internet Explorer无法正确处理它.但我也发现了其他问题(目前只在Chrome中测试过).

这是一些示例代码:

/** 
 *  Inherit the prototype methods from one constructor into another 
 *  Borrowed from Google Closure Library 
 */
function inherits(childCtor, parentCtor) {
    function tempCtor() {};
    tempCtor.prototype = parentCtor.prototype;
    childCtor.superClass_ = parentCtor.prototype;
    childCtor.prototype = new tempCtor();
    childCtor.prototype.constructor = childCtor;
},

// Custom class that extends Array class
function CustomArray() {
    Array.apply(this, arguments);
}
inherits(CustomArray,Array);

array = new Array(1,2,3);
custom = new CustomArray(1,2,3);
Run Code Online (Sandbox Code Playgroud)

在Chrome的控制台中输入以下内容即可输出以下内容:

> custom
[]
> array
[1, 2, 3]
> custom.toString()
TypeError: Array.prototype.toString is not generic
> array.toString()
"1,2,3"
> custom.slice(1)
[]
> array.slice(1)
[2, 3]
> custom.push(1)
1
> custom.toString()
TypeError: Array.prototype.toString is not generic
> custom
[1]
Run Code Online (Sandbox Code Playgroud)

显然,对象的行为不一样.我应该放弃这种方法,还是有办法实现我的目标myobj instanceof CustomArray

CMS*_*CMS 34

Juriy Zaytsev(@kangax)就在今天发表了一篇关于这个主题的非常好的文章.

他探索了各种替代方案,如Dean Edwards iframe借用技术,直接对象扩展,原型扩展和ECMAScript 5访问器属性的使用.

最后没有完美的实施,每个都有自己的优点和缺点.

绝对是一个非常好的阅读:


lag*_*lex 23

ES6

class SubArray extends Array {
    last() {
        return this[this.length - 1];
    }
}
var sub = new SubArray(1, 2, 3);
sub // [1, 2, 3]
sub instanceof SubArray; // true
sub instanceof Array; // true
Run Code Online (Sandbox Code Playgroud)

原答案:(不推荐,可能会导致性能问题)

从接受的答案中提到的文章复制粘贴,以获得更多可见性

运用 __proto__

function SubArray() {
  var arr = [ ];
  arr.push.apply(arr, arguments);
  arr.__proto__ = SubArray.prototype;
  return arr;
}
SubArray.prototype = new Array;
Run Code Online (Sandbox Code Playgroud)

现在您可以添加方法了 SubArray

SubArray.prototype.last = function() {
  return this[this.length - 1];
};
Run Code Online (Sandbox Code Playgroud)

像普通数组一样初始化

var sub = new SubArray(1, 2, 3);
Run Code Online (Sandbox Code Playgroud)

像普通阵列一样

sub instanceof SubArray; // true
sub instanceof Array; // true
Run Code Online (Sandbox Code Playgroud)