SPOSOBY ROZSZERZENIA obiektu Array w javascript

Staram się rozszerzyć obiekt Array w javascript za pomocą kilku przyjaznych dla użytkownika metod, takich jak Array.Add () zamiast tablicy.push() itd...

Wdrażam 3 sposoby, aby to zrobić. niestety trzecia droga nie działa i chcę zapytać dlaczego? i jak to zrobić działa.

//------------- 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

W trzeci sposób chcę rozszerzyć obiekt Array wewnętrznie klasy Array3. Jak to zrobić, aby nie dostać "push is not a function" I "undefined"?

Tutaj dodaję czwarty sposób.

//------------- 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]);

Tutaj znowu muszę użyć prototyp. Miałem nadzieję uniknąć używania dodatkowych linii poza konstruktorem klasy jako Array4.prototyp. Chciałem mieć kompaktową, zdefiniowaną klasę ze wszystkimi elementami w jednym miejscu. Ale myślę, że nie mogę tego zrobić inaczej.

Author: demosthenes, 2012-07-05

8 answers

Nazwy metod powinny być pisane małymi literami. Prototyp nie powinien być modyfikowany w konstruktorze.

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

W CoffeeScript

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

Jeśli nie podoba Ci się ta składnia i musisz ją rozszerzyć z konstruktora, Twoja jedyna opcja to:

// 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)
      }

   });
};

Możesz też to zrobić

ArrayExtenstions = {
   Add: function() {

   }
}
extend(ArrayExtenstions, Array.prototype);



function Array3() { }
Array3.prototype = ArrayExtenstions;
W dawnych czasach " prototyp.js miał zajęcia.Utwórz metodę. Można to wszystko zawinąć jest to metoda taka
var Array3 = Class.create(Array, {
    construct: function() {

    },    
    Add: function() {

    }
});

Aby uzyskać więcej informacji na ten temat i jak wdrożyć, zajrzyj do prototyp.kod źródłowy js

 28
Author: SMathew,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-07-06 15:48:32

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

Za pomocą __proto__

(stara odpowiedź, niezalecana, może powodować problemy z wydajnością)

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

Teraz możesz dodać swoje metody do SubArray

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

Inicjalizacja jak normalne Tablice

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

Zachowuje się jak normalne Tablice

sub instanceof SubArray; // true
sub instanceof Array; // true
 11
Author: laggingreflex,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-24 03:16:42

W trzecim przykładzie tworzysz nową właściwość o nazwie prototype dla obiektu Array3. Kiedy wykonujesz new Array3, które powinno być new Array3(), tworzysz instancję tego obiektu do zmiennej list3. Dlatego metoda Add nie będzie działać, ponieważ this, który jest danym obiektem, nie ma poprawnej metody push. Mam nadzieję, że rozumiesz.

Edit: Sprawdź zrozumienie kontekstu JavaScript aby dowiedzieć się więcej o this.

 2
Author: elclanrs,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-21 14:15:40

Jakiś czas temu przeczytałem książkę Javascript Ninja napisaną przez Johna Resiga , twórcę jQuery . Zaproponował sposób naśladowania metod typu array za pomocą zwykłego obiektu JS. Zasadniczo wymagane jest tylko 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'
Nie chodzi mi o to, że to dobre czy złe. To oryginalny sposób wykonywania Array operacji. Korzyść polega na tym, że nie przedłużasz Array prototype. Należy pamiętać, że obj jest zwykłym object, nie jest Array. Dlatego obj instanceof Array zwróci false. Think obj jako fasada .

Jeśli ten kod Cię interesuje, przeczytaj fragment Listing 4.10 Simulating array-like methods .

 2
Author: roland,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-03 13:35:51

Czy próbujesz zrobić coś bardziej skomplikowanego, a następnie dodać alias dla " push "o nazwie "Add"?

Jeśli nie, prawdopodobnie najlepiej byłoby tego uniknąć. Powodem, dla którego sugeruję, że jest to zły pomysł, jest to, że ponieważ tablica jest wbudowanym typem javascript, jego modyfikacja spowoduje, że wszystkie typy tablicy skryptów będą miały nową metodę "Add". Potencjał kolizji nazw z inną stroną trzecią jest wysoki i może spowodować, że skrypt strony trzeciej straci swoją metodę na rzecz Twojej.

My ogólną zasadą jest, aby funkcja pomocnicza działała na tablicy, jeśli już gdzieś nie istnieje i rozszerza tablicę tylko wtedy, gdy jest bardzo potrzebna.

 0
Author: duyker,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-07-05 04:53:16

Nie można rozszerzyć obiektu Array w JavaScript.

Zamiast tego, możesz zdefiniować obiekt, który będzie zawierał listę funkcji, które wykonują się w tablicy, i wstrzyknąć te funkcje do tej instancji tablicy i zwrócić tę nową instancję tablicy. Nie powinieneś zmieniać Array.prototype, aby włączyć swoje niestandardowe funkcje na liście.

Przykład:

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",
}

Tylko przykładowy kod, możesz go modyfikować i używać jak chcesz. Ale podstawowa koncepcja I polecam do naśladowania pozostaje taka sama.

 0
Author: Boopathi Rajaa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-07 20:42:20

Możesz również użyć tego sposobu w ES6:

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

Wynik:

let x = [0,1,2,3,2,3];
let y = x.unique();
console.log(y); // => [0,1,2,3]
 0
Author: selahattinunlu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-08 15:41:14
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

Odpowiedzią jest kompaktowe obejście, które działa zgodnie z przeznaczeniem we wszystkich obsługiwanych przeglądarkach.

 0
Author: Neni,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-31 18:49:31