luq techblog

o tworzeniu słów kilka…

JavaScript array_sum 18 kwietnia 2010

Filed under: JS — Łukasz @ 23:04
Tags: , ,

W ostatnim wpisie pisałem o stronie phpjs.org. Chciałbym na postawie tego, napisać dwa słowa o JavaScripcie i jego możliwościach, których większość ludzi nie wykorzystuje. Strona phpjs.org jak już poprzednio wspomniałem jest próbą przeportowania funkcji występujących w PHP na tak samo działające funkcje w JS, wszystko fajnie i pomysł bardzo mi się podoba, ale moim zdaniem nie pomyślano o wykorzystaniu tych funkcji w sposób obiektowy, bo JS jest w pełni obiektowy!

 

Okej przykład ten oprę o funkcję array_sum (http://phpjs.org/functions/array_sum:339). Wrzucę tutaj ten kod wycinając komentarze w celu zwiększenia czytelności, chyba nikt się nie obrazi.

function array_sum (array) {
    var key, sum = 0;

    if (typeof array !== 'object') {
        return null;
    }
    for (key in array) {
        sum += (array[key] * 1);
    }
     return sum;
}

Jeśli po tak zdefiniowanej funkcji napiszemy:

alert( 
    array_sum( [ 10, 20, 30 ] ) 
);

Wszystko gra i pokaże nam 60, ale, no właśnie, dlaczego z tej funkcji nie zrobić metody obiektu Array. Oczywiście jasne jest to, że portuje się funckcję i pozostaje ona funkcją o takiej samej nazwie. Natomiast moim zdaniem powinno się to potem zrobić bardziej z duchem obiektowym, czyli skorzystać z tego, że w JavaScript`cie mamy możliwość dodawania metod do standardowych klas.

Array.prototype.sum = function(){ 
    return array_sum( this )
};
var a = [ 10, 20, 30 ];
alert( a.sum() );

I w ten sposób to już nie działa. Dostajemy NaN. Dlaczego? Dlatego, że dodając metodę do standardowych klas (w taki sposób jak powyżej) tak naprawdę ta metoda jest dodawana do wszystkich obiektów stworzonych za pomocą definicji tej klasy. A, że w JavaScripcie metoda to tak naprawdę właściwość, która jest wskaźnikiem na funkcję, przelatując obiekt pętlą for-in mamy następujące pary właściwość : wartość.

0 : 10
1 : 20
2 : 30

// i uwaga!

sum : function(){ 
    return array_sum( this )
};

Dlatego, z ostatnim obiegiem pętli mamy coś takiego:

sum = 60 + ( function(){ return array_sum( this ) } * 1);

Mnożąc obiekt klasy Function przez liczbę (obiekt klasy Number) otrzymujemy NaN, a dodając do czegoś NaN otrzymujemy NaN. Oczywiście można to rozwiązać w bardzo prosty sposób, dodając warunek „jeśli właściwość nie jest obiektem klasy Function…”, kod prezentowałby się tak:

function array_sum (array) {
    var key, sum = 0;

    if (typeof array !== 'object') {
        return null;
    }
    for (key in array) {
        if( typeof array[key] !== 'function' ){ // <- taki if	
            sum += (array[key] * 1);
        }
    }
     return sum;
}

i wszystko by śmigało jak należy. Piszę o tym z dwóch powodów. Pierwszy to taki, że dla mnie jakoś naturalne było podpiąć tą funkcję pod obiekt, może to nikomu wcześniej nie przyszło do głowy. Drugim jest to, że administratorowie portalu phpjs.org najwidoczniej olali mój komentarz, który brzmiał tak:

Hi, sorry but my english is not so well…

 

Anyway, I think that in JavaScript must be possibility to create from this function – method of Array object. I known that You ported function in this same name and this is okej, but now can`t write this:

 

[CODE]
Array.prototype.sum = function(){
return array_sum( this )
};

var arr = [ 10, 20, 30 ];

alert( array_sum( arr ) );
alert( arr.sum() );
[/CODE]

 

@Kevin van Zonneveld write: „PHP does not differentiate between numerically indexed arrays and ‚associative arrays’ (in JavaScript, known as objects)” – this means that check:

 

[CODE]
if( key == parseInt( key ) ){
sum += (array[key] * 1);
}
[/CODE]

 
is bad, but check:

 

[CODE]
if( typeof array[key] !== ‚function’ ){
sum += (array[key] * 1);
}
[/CODE]

 

is ok and solves the problem.

Napisałem go ponad 2 tygodnie temu, do dziś nie został zaakceptowany…
Tyle na dziś.

Reklamy
 

2 Responses to “JavaScript array_sum”

  1. skowron-line Says:

    Sorki że odgrzewam kotleta no ale. Skoro chcesz sobie to podpiąć pod obiekt Array to lepiej całość wrzucić do anonimowej funkcji a nie dodawać jakieś głupie warunki które tylko katują parser.

    Array.prototype.sum = function(){
    // ciało funkcji
    }
    
  2. luq Says:

    @skowron-line nie bardzo rozumiem co masz na myśli… Oczywiście, że dodaje do klasy Array nową metodę, tak jak zresztą pisze w tym wpisie:

    Array.prototype.sum = function(){
        return array_sum( this )
    };
    

    Chodzi o to, że w postaci tej przeportowanej funkcji podanej na phpjs.org takie coś jest niemożliwe.


Skomentuj

Wprowadź swoje dane lub kliknij jedną z tych ikon, aby się zalogować:

Logo WordPress.com

Komentujesz korzystając z konta WordPress.com. Wyloguj / Zmień )

Zdjęcie z Twittera

Komentujesz korzystając z konta Twitter. Wyloguj / Zmień )

Zdjęcie na Facebooku

Komentujesz korzystając z konta Facebook. Wyloguj / Zmień )

Zdjęcie na Google+

Komentujesz korzystając z konta Google+. Wyloguj / Zmień )

Connecting to %s