方法来在javascript延伸Array对象(Ways to extend Array objec

2019-06-26 01:21发布

我尝试在JavaScript扩展Array对象有一些用户友好的方法,如Array.Add()代替的Array.push()等等......

我实现了3种方式来做到这一点。 偏偏第三道不工作,我要问为什么? 而要做到如何工作。

//------------- 1st way
Array.prototype.Add=function(element){
     this.push(element);
};

var list1 = new Array();
list1.Add("Hello world");
alert(list1[0]);

//------------- 2nd way
function Array2 () {
    //some other properties and methods
};

Array2.prototype = new Array;
Array2.prototype.Add = function(element){
  this.push(element);  
};

var list2 = new Array2;
list2.Add(123);
alert(list2[0]);

//------------- 3rd way
function Array3 () {
    this.prototype = new Array;
    this.Add = function(element){
      this.push(element);  
    };
};

var list3 = new Array3;
list3.Add(456);  //push is not a function
alert(list3[0]); // undefined

在3日的方式,我想在内部扩展Array对象ARRAY3类。 如何做到这一点,这样不会让“推不是一个函数”和“不确定”?

在这里,我补充一个4路。

//------------- 4th way
function Array4 () {
    //some other properties and methods
    this.Add = function(element){
        this.push(element);
    };
 };
Array4.prototype = new Array();

var list4 = new Array4();
list4.Add(789);
alert(list4[0]);

这里我再一次不得不使用原型。 我希望避免使用额外的线路外类构造函数Array4.prototype。 我想与所有作品紧凑定义的类在同一个地方。 但我想我不能这样做,否则。

Answer 1:

方法名应该小写。 原型不应该在构造函数中进行修改。

function Array3() { };
Array3.prototype = new Array;
Array3.prototype.add = Array3.prototype.push

在CoffeeScript中

class Array3 extends Array
   add: (item)->
     @push(item) 

如果你不喜欢的语法,你必须把它从构造函数中延伸,你唯一的选择是:

// define this once somewhere
// you can also change this to accept multiple arguments 
function extend(x, y){
    for(var key in y) {
        if (y.hasOwnProperty(key)) {
            x[key] = y[key];
        }
    }
    return x;
}


function Array3() { 
   extend(this, Array.prototype);
   extend(this, {
      Add: function(item) {
        return this.push(item)
      }

   });
};

你也可以这样做

ArrayExtenstions = {
   Add: function() {

   }
}
extend(ArrayExtenstions, Array.prototype);



function Array3() { }
Array3.prototype = ArrayExtenstions;

昔日,“prototype.js中”曾经有一个Class.create方法。 你可以换这一切都是那样的方法

var Array3 = Class.create(Array, {
    construct: function() {

    },    
    Add: function() {

    }
});

有关此的详细信息以及如何实现,看在prototype.js中源代码



Answer 2:

ES6

class SubArray extends Array {
    constructor(...args) { 
        super(...args); 
    }
    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

使用__proto__

(老答案,不推荐使用,可能会导致性能问题 )

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

现在,您可以将您的方法来SubArray

SubArray.prototype.last = function() {
  return this[this.length - 1];
};

初始化像正常阵列

var sub = new SubArray(1, 2, 3);

行为像普通数组

sub instanceof SubArray; // true
sub instanceof Array; // true


Answer 3:

在你的第三个例子,你只是创建一个名为新属性prototype为对象Array3 。 当你new Array3这应该是new Array3()你实例化对象到变量list3 。 因此, Add方法是行不通的,因为this ,这是有问题的对象,没有一个有效的方法push 。 希望你能理解。

编辑:退房了解JavaScript的背景下 ,以更多地了解this



Answer 4:

前一段时间我读的书的JavaScript忍者John Resig的 ,jQuery的创作者写的。 他提出了一个方法来模仿使用纯JS对象数组的方法等。 基本上,只有length是必需的。

var obj = {
    length: 0, //only length is required to mimic an Array
    add: function(elem){
        Array.prototype.push.call(this, elem);
    },
    filter: function(callback) {
        return Array.prototype.filter.call(this, callback); //or provide your own implemetation
    }
};

obj.add('a');
obj.add('b');
console.log(obj.length); //2
console.log(obj[0], obj[1]); //'a', 'b'

我不是说这是好还是坏。 这是做的一个原始的方式Array操作。 好处是,你不延长Array prototype 。 请记住, obj是一个普通的object ,它不是一个Array 。 因此obj instanceof Array将返回false 。 想想obj作为幌子

如果代码是你的兴趣,阅读摘录4.10模拟阵列的方法等



Answer 5:

你试图做更复杂的东西,然后只需添加为“推”称为“添加”的别名?

如果不是,它很可能是最好避免这样做。 我之所以认为这是一个坏主意是,由于阵列是一种内置的JavaScript类型,修改会导致所有的脚本数组类型有你的新的“添加”方法。 名称冲突与其他第三方的可能性很高,可能会导致第三方脚本失去其方法有利于你的一个。

我的一般原则是使一个辅助功能,已经在阵列的,如果它不存在的地方工作,如果它极有必要仅延伸阵列。



Answer 6:

你不能在JavaScript的扩展Array对象。

相反,你可以做的是定义一个对象,将包含的是对阵列执行的功能列表,并注入这些功能成Array实例,并返回这个新的Array实例。 你不应该做的是改变Array.prototype包括在列表中选择您的自定义功能。

例:

function MyArray() {
  var tmp_array = Object.create(Array.prototype);
  tmp_array = (Array.apply(tmp_array, arguments) || tmp_array);
  //Now extend tmp_array
  for( var meth in MyArray.prototype )
    if(MyArray.prototype.hasOwnProperty(meth))
      tmp_array[meth] = MyArray.prototype[meth];
  return (tmp_array);
}
//Now define the prototype chain.
MyArray.prototype = {
  customFunction: function() { return "blah blah"; },
  customMetaData: "Blah Blah",
}

只是一个样本代码,你可以修改它,但是你想使用。 但基本概念,我建议你遵循保持不变。



Answer 7:

你也可以用这种方式在ES6:

Object.assign(Array.prototype, {
    unique() {
      return this.filter((value, index, array) => {
        return array.indexOf(value) === index;
      });
    }
});

结果:

let x = [0,1,2,3,2,3];
let y = x.unique();
console.log(y); // => [0,1,2,3]


Answer 8:

var SubArray = function() {                                           
    var arrInst = new Array(...arguments); // spread arguments object
    /* Object.getPrototypeOf(arrInst) === Array.prototype */
    Object.setPrototypeOf(arrInst, SubArray.prototype);     //redirectionA
    return arrInst; // now instanceof SubArray
};

SubArray.prototype = {
    // SubArray.prototype.constructor = SubArray;
    constructor: SubArray,

    // methods avilable for all instances of SubArray
    add: function(element){return this.push(element);},
    ...
};

Object.setPrototypeOf(SubArray.prototype, Array.prototype); //redirectionB

var subArr = new SubArray(1, 2);
subArr.add(3); subArr[2]; // 3

答案是一个紧凑的解决方法,因为打算在所有支持的浏览器,其工作原理。



文章来源: Ways to extend Array object in javascript