2013-04-20 15 views
6

Próbuję dodać funkcję do tablicy obiektów, do której każdy obiekt ma dostęp, ale która nie musi być dodawana do każdego obiektu osobno.Udostępnianie funkcji javascript między wszystkimi obiektami w tablicy

Pozwól, że dam ci krótki przykład.

Powiedzmy mam tablicę zawierającą podobne obiekty, z których każdy posiada właściwości x i y nieruchomości:

var objects = [{x:1, y:2}, 
       {x:0, y:5}, 
       {x:3, y:14} 
       ]; 

Chciałbym obliczyć sumę x i y dla każdego z obiektów.

Pierwsze podejście:

Aby obliczyć sumę dla danego obiektu, można przekazać ten obiekt do predefiniowanych funkcji tak:

function xySum1(o) {return o.x + o.y;} 

objects[0].x  //--> returns 1 
objects[0].y  //--> returns 2 
xySum1(objects[0]) //--> returns 3 

Jest to dość brzydki i niezadowalające, ponieważ dostęp do właściwości x i y odbywa się inaczej. Ponadto mój kod znajduje się w różnych lokalizacjach, a funkcja xySum1 nie jest łatwo rozpoznawalna jako utworzona do działania na obiektach w tablicy.

Drugie podejście:

Można by pętli tablicy i dodać funkcję jako właściwość do każdego obiektu:

for (var i=0; i < objects.length; i++) { 
    objects[i].xySum2 = function() {return this.x + this.y;}; 
} 

Teraz suma jest uzyskiwana przez

objects[0].x  //--> returns 1 
objects[0].y  //--> returns 2 
objects[0].xySum2() //--> returns 3 

co jest znacznie lepsze.

Problemy

Istnieją jednak pewne problemy z tym podejściem. Po pierwsze, kiedy dodać nowy element do tablicy

objects.push({x:5,y:21}); 

czym suma nie mogą być obliczone przed funkcja została dodana do obiektu

objects[3].xySum2() //-->TypeError 

Innym problemem jest to, że wiele obiektów i wiele funkcji do dodania. Wydaje się, że marnowanie dobrej pamięci pozwala na dodanie każdej funkcji do każdego obiektu osobno.

Czy istnieje sposób, aby zrobić to bardziej efektywnie?

+6

Co z 'objects.xySum (0)'? – Bergi

+0

może zdefiniować konstruktora, a następnie funkcje będą w prototypie? – user2264587

+0

Możesz również zdefiniować metodę Object.prototype w następujący sposób: 'Object.prototype.xySum = function() {return typeof this.x! == 'undefined' && typeof this.y! == 'undefined'? this.x + this.y: undefined;} '. – dfsq

Odpowiedz

8

Zdefiniuj klasę:

function MyObject(x, y) { 
    this.x = x; 
    this.y = y; 
} 
MyObject.prototype = { 
    xySum2: function() { 
     return this.x + this.y; 
    }, x: 0, y: 0 
}; 

Następnie można zrobić:

var objects = [ 
    new MyObject(1, 2), 
    new MyObject(0, 5), 
    new MyObject(3, 14) 
]; 
objects[0].xySum2(); // 3 

objects.push(new MyObject(5, 21)); 
objects[3].xySum2(); // 26 

Alternatywnie, to co Bergi prawdopodobnie chciał powiedzieć w swoim komentarzu:

objects.xySum = function(index) { 
    return this[index].x + this[index].y; 
}; 

To podejście jest trochę "brudniejsza", ale także mniej zajmująca pamięć.

+1

Dzięki MaxArt za odpowiedź. Czy jest jakiś sposób, aby to zrobić, gdy już utworzono tablicę obiektów? Pytam, ponieważ jest on przekazywany z innej części programu, która jest poza moją kontrolą. – ElRudi

+0

@ ElRudi W takim przypadku proponuję użyć alternatywy: zdefiniuj funkcję tablicy 'objects' i gotowe. Pamiętaj, aby ponownie zdefiniować go w każdej kopii lub części, którą zamierzasz zrobić z "opcji". Lub zawsze możesz stworzyć własną tablicę 'MyObject's używając elementów' objects', jak w 'new MyObject (objects [i] .x, objects [i] .y)' – MaxArt

+0

Więc moje opcje: (1) zdefiniuj klasę, dodaj pożądaną funkcję do swojego prototypu - i przeprowadź pętlę przez wszystkie obiekty w otrzymanej tablicy, aby utworzyć dla każdej instancji klasy o tych samych właściwościach, (2) dodaj funkcję do prototypu obiektu "Object" zamiast tego, co może, ale nie musi być okropną praktyką kodowania, z przewagą mniejszej liczby linii kodu i mniejszej pętli przez tablice, lub (3) dodać funkcję do _array_ zamiast do pojedynczych obiektów - z tą wadą, że jest używana syntaktycznie różni się od innych właściwości i nie jest kopiowany wraz z danymi obiektu. Czy masz rację? – ElRudi

Powiązane problemy