2010-07-10 9 views
5

Próbowałem sprawdzić, czy mogę zbudować moje obiekty JavaScript tak intuicyjnie, jak to możliwe, upewniając się, że jest to "poprawne", jak to możliwe. Prowadziłem kilka różnych scenariuszy na stronie JSLint.com Crockforda i nie miałem szczęścia. Wydaje mi się, że naprawiłem jeden błąd, a następnie pojawia się inny z powodu zmiany. Poniżej jest tak dobrze, jak mogę. Czy ktoś ma inne podejście do tego?Jaki jest najlepszy sposób na zbudowanie obiektu JavaScript, aby działał ORAZ przekazywał JSLint?

Jest to typowy sposób wyglądać struktura obiektu:

function gizmo(id) { 

    /* private variables */ 

    var myId = id; 

    /* private methods */ 

    var init = function() { 
    if (myId < 1) { 
     setId(1); 
    } 
    }; 

    var setId = function (newId) { 
    myId = newId; 
    }; 

    // run 'constructor' 
    init(); 

    /* public methods */ 

    return { 
    getId: function() { 
     return myId; 
    }, 
    setId: function (newId) { 
     setId(newId); 
    }, 
    incrementId: function (inc) { 
     setId(myId + inc); 
    } 
    }; 
} 

// creating an instance of gizmo 

var myGizmo = gizmo(-2); 
console.log(myGizmo.getId()); // outputs 1 

myGizmo.setId(5); 
console.log(myGizmo.getId()); // outputs 5 

myGizmo.incrementId(2); 
console.log(myGizmo.getId()); /// outputs 7 

To wydaje się działać dobrze. Jednakże, kiedy uruchamiam to przez JSLint, daje mi to błąd, że moje dwie prywatne funkcje to "Domniemane globale".

Najlepszym mogę wymyślić jest zadeklarować swoje funkcje na górze ze zmiennych, takich jak ten:

function gizmo(id) { 

    /* private variables */ 

    var myId = id, 
     init, 
     setId; 

    /* private methods */ 

    init = function() { 
    if (myId < 1) { 
     setId(1); 
    } 
    }; 

    setId = function (newId) { 
    myId = newId; 
    }; 

    // run 'constructor' 
    init(); 

    /* public methods */ 

    return { 
    getId: function() { 
     return myId; 
    }, 
    setId: function (newId) { 
     setId(newId); 
    }, 
    incrementId: function (inc) { 
     setId(myId + inc); 
    } 
    }; 
} 
+2

To nie jest tak wiele odpowiedzi jak porady. Nie martw się zbytnio o jsLint. Często uważam to za zbyt ostre. Zamiast tego skoncentruj się na programowaniu. Powiedział, że pozwolę innym omówić najlepszą praktykę. – TNi

+0

Uzgodnione. Nie podkreślam tego zbyt wiele. Po prostu mam sposób konstruowania mojego kodu na podstawie tego, czego nauczyłem się tu i tam w interwebs. W ciągu ostatnich kilku dni bawiłem się z JSLintem i byłem zainteresowany tym, aby inni zrozumieli to wszystko. –

+0

problemem jest init i kolejność twoich funkcji. Przenieś init tuż przed zwróceniem obiektu, który przejdzie. Poza tym nie potrzebuję funkcji init. Może jako samobójczy i anonimowy fn tylko po to, by rozdzielić rzeczy. – galambalazs

Odpowiedz

1

Jestem prawie pewien, że to błąd w JSLint. Nie widział jeszcze setId, więc zakłada, że ​​jest globalny. Ale w rzeczywistości nie ma to znaczenia, ponieważ wszystkie modele var są podnoszone, zgodnie z ECMAScript 5 10.5. Oznacza to, że twój pierwszy przykład, a drugi to ta sama semantyka. Deklaracja zmiennej lokalnej w dowolnym miejscu w funkcji jest przetwarzana natychmiast, a wiązanie jest początkowo ustawione na wartość undefined. Ale do czasu, gdy funkcja (na przykład init) faktycznie działa, zamknięta wartość nie jest już undefined.

Aby zobaczyć, że setId jest wstępnie zdefiniowana, ale nie odnosi się do globalnego, wykonaj test:

function setId() 
{ 
    alert("Global setId"); 
} 
function f() 
{ 
    var init = function() 
    { 
    setId(); 
    } 
    alert(typeof(setId)); 
    init(); 
    var setId = function() 
    { 

    } 
} 

będzie ostrzegać niezdefiniowana, a następnie wyrzucić błąd TypeError.

+0

+1, nie wiedziałem o podnoszeniu. Zawsze zakładałem, że musisz zadeklarować rzeczy w porządku. – gradbot

+0

Musisz zadeklarować je w kolejności, jeśli chcesz, aby działały w różnych przeglądarkach. – lawnsea

+0

@lawnsea, jaka przeglądarka zachowuje się inaczej i jak? –

0

nie wiem o JSlint, ale po przeczytaniu „Javascript dobre części” Zawsze deklaruję obiekty jako literały.

np

Mogwai={ 
    has_crazy_thoughts:True, 
    reacts_to_water:True, 
    name: 'Gizmo', 
    eat:function(food){ 
    // code 
    }, 
    become_gremlin:function(){ 
    // code 
    }, 
    cause_havoc:function(){ 
    // code 
    } 
} 

Nie jesteś faktycznie deklarując żadnych przedmiotów powyżej. Tylko funkcja. Wewnętrzne funkcje w rzeczywistości nie istnieją w JavaScript - w ogóle nie przypominają one Javy.

EDYCJA: Gorąco polecam wspomnianą wyżej książkę (bez afiliacji): http://oreilly.com/catalog/9780596517748 ... została napisana przez Douglasa Crockforda, który przyniósł nam JSlint.

+1

Jestem właścicielem książki. I tak, to jest dobre. Mój powyższy przykład tworzy prywatne zmienne i funkcjonuje przy użyciu zamknięć, co jest również czymś, co przechodzi Crockford w tej książce. Na przykład, używając literałów obiektowych, nie mam możliwości tworzenia prywatnych zmiennych lub funkcji. –

+0

W rzeczywistości deklarujesz obiekt. Deklarujesz obiekt, a także trzy funkcje, dwa bajty i ciąg znaków, wszystkie wypchane właściwościami obiektu. – icktoofay

+0

Również "True" i "False" są małe w JavaScript. – icktoofay

3

JSLint oczekuje, że setId zostanie zdefiniowany przed odwołaniem do init.

To przekazuje JSLint.

function gizmo(id) { 

    /* private variables */ 

    var myId = id; 

    /* private methods */ 

    var setId = function (newId) { 
    myId = newId; 
    }; 

    var init = function() { 
    if (myId < 1) { 
     setId(1); 
    } 
    }; 

    // run 'constructor' 
    init(); 

    /* public methods */ 

    return { 
    getId: function() { 
     return myId; 
    }, 
    setId: function (newId) { 
     setId(newId); 
    }, 
    incrementId: function (inc) { 
     setId(myId + inc); 
    } 
    }; 
} 
+0

nie ma znaczenia, czy zdefiniuję moją funkcję za pomocą funkcji setId() Otrzymuję ten sam błąd Implied Global w JSLint. –

+0

Po prostu przebiegłem to przez JSLint i minęło. Wypróbuj go na swojej stronie internetowej. http://www.jslint.com/ – gradbot

+1

'setId' nigdy nie odnosi się do globalnego. Dzięki podnoszeniu zawsze odnosi się do zmiennej lokalnej. To prawda, że ​​wartość tej zmiennej lokalnej jest początkowo niezdefiniowana, ale nie ma to znaczenia, ponieważ jest ona zdefiniowana po wywołaniu 'init'. –

0

Minęło dużo czasu (kilka lat) odkąd zaprogramowane JavaScript poważnie, więc moja pamięć o szczegółach najlepszą praktyką jest zupełnie nie ma. To, co zrobiłem, cofa się i wykopuje kilka zasobów, które mogą pomóc w podjęciu świadomej decyzji.

Po pierwsze, sposób tworzenia obiektów wydaje się bardzo podobny do Module Pattern. O ile dobrze pamiętam, artykuł, do którego się przyłączyłem, jest całkiem niezły. Po drugie, może wolisz inny sposób na instantiate your objects. Ten artykuł daje nieco inne podejście.

+0

Cool. Teraz czytam post Resiga na ten temat. Dzięki. –

Powiązane problemy