2009-12-07 7 views
6

Spójrz na poniższy kod:Dziwny składnia metod numer w JavaScripcie

Number.prototype.isIn = function() { 
    for (var i = 0, j = arguments.length; i < j; ++i) { 
     if (parseInt(this, 10) === arguments[i]) { 
      return true; 
     } 
    } 
    return false; 
}; 

var x = 2; 
console.log(x.isIn(1,2,3,4,5)); // <= 'true' 
console.log(2.isIn(1,2,3,4,5)); // <= Error: 'missing) after argument list' 

Dlaczego jest tak, że gdy jest to zmienna, kod działa poprawnie ale gdy jest to numer dosłowny, to się nie powiedzie?


A także, o dziwo, dlaczego działa następująca linia?

console.log((2).isIn(1,2,3,4,5)); // <= 'true' 

W powyższej linijce zasadniczo umieściłem literał w nawiasie.

Odpowiedz

10

Jest to błąd składniowy, ponieważ reprezentujesz liczbę. Ciągi mogą działać w ten sposób, ale nie liczby, ponieważ kropka bezpośrednio po liczbie symbolizuje wartość dziesiętną. Posta po . powoduje błąd.

-1

Rozumiem, że liczby są literałami i , a nie obiektami. Jednak gdy definiujesz zmienną jako liczbę, staje się ona nowym obiektem Number().

Wykonując następujące czynności;

var x = 10; 

Czy to samo, co pójście;

var x = new Number(10); 

Jeśli chodzi o drugi przykład; Mogę tylko założyć, że umieszczenie nawiasów wokół numeru spowodowało, że kompilator JavaScript zakłada, że ​​wartość jest anonimowym obiektem Number(). Co ma sens chyba ...

+3

'x = 10' i' x = nowa liczba (10) 'nie są równoważne. –

+0

Prawidłowe: 'alert (typeof 10);' vs. 'alert (typeof new Number (10));' –

+0

Dzięki za poprawki facetów. – Cammy

0

Choć rozróżnienie jest często nie wynika z powodu automatycznej konwersji typu, JavaScript obsługuje wiele typów pierwotnych, jak również obiektów:

var foo = 10; 
var bar = new Number(10); 
alert(foo.toString(16)); // foo is automatically wrapped in an object of type Number 
         // and that object's toString method is invoked 
alert(bar.toString(16)); // bar is already an object of type Number, 
         // so no type conversion is necessary before 
         // invoking its toString method 
var foo2 = "foo"; 
var bar2 = new String("foo"); 
alert(typeof foo2);  // "string" - note the lowercase "s", not a String object 
alert(typeof bar2);  // "object" 

alert(typeof true)  // "boolean" 
alert(typeof new Boolean(true)) // "object" 

i coś, co naprawdę dezorientuje Emisja:

// the next line will alert "truthy" 
alert("Boolean object with value 'false'" + (new Boolean(false) ? " is truthy" : " is falsy")); 
// the next line will alert "falsy" 
alert("boolean primitive with value 'false'" + (false ? " is truthy" : " is falsy")); 

Mimo, powołując się na automatyczną konwersję typu sprawia, że ​​życie trochę łatwiejsze, należy zawsze mieć z tyłu czyjegoś umysłu dobre zrozumienie, jakiego rodzaju swoich pierwotnych wartości i obiekty w rzeczywistości; zaskakująco duża liczba błędów JS wynika z tego, że ludzie nie zdają sobie sprawy, że na przykład coś, co wygląda jak liczba, jest w rzeczywistości ciągiem znaków lub że niektóre operacje, które wykonali, spowodowały coś, co zawierało przypisano nową wartość, która jest łańcuchem lub obiektem.

EDIT: aby dokładniej rozwiązanie pierwotnego pytanie, co ja teraz sobie sprawę, że nie odpowiedział wprost: 10.foo() spowoduje błąd składni jak . jest postrzegana jako separator dziesiętny i foo() nie jest ważna kolejność znaki do przeanalizowania jako liczby. (10).foo() będzie działać jako zamykające nawiasy (10) przekształcić całą konstrukcję przed . w jedno wyrażenie. To wyrażenie jest obliczane i zwraca prymitywną wartość liczbową: 10. Wtedy . jest postrzegany jako traktujący tę prymitywną wartość w kontekście obiektu, więc jest automatycznie zawijany w obiekt typu Number (jest to automatyczna konwersja typu w działaniu).Następnie odwołuje się właściwość tego obiektu, znajdująca się w jego prototypowym łańcuchu; i końcowa () powoduje, że ta właściwość ma być traktowana jako odwołanie do funkcji i wywoływana w kontekście 'tego' obiektu Number, który był zawinięty wokół wartości pierwotnej w punkcie napotkania ..

+0

'10' i' Number (10) 'są identyczne. 'bar = Number (10)' nie powoduje, że 'bar' jest" obiektem typu Number ". Być może chciałeś porównać '10' z' new Number (10) '? LUB ''10'' vs' Number (' 10 ') '? –

+0

Ups, dobry połów - brakowało "nowego". Powinienem skopiować te rzeczy z konsoli, gdzie wykonuję moje testy, zamiast przepisać je :-) – NickFitz

2

Josh był poprawny, ale nie musisz używać zmiennej, aby użyć metody liczby, , chociaż zwykle wygodniej jest to zrobić.

5.isIn(1,2,3,4,5) returns an error 

5.0.isIn(1.2.3.4.5) returns true, as does 
(5).isIn(1,2,3,4,5) 
+0

'5..isIn' i' 5 .isIn' również usuwają niejednoznaczność [parsowania]. –

7

W większości odpowiedzi stwierdzono, że kropka po literałach numerycznych jest uważana za część tej liczby jako separator ułamków. Ale jeśli nadal chcesz używać kropki jako operatora, to szybka i łatwa poprawka pozostawiłaby pustą przestrzeń między liczbą a przestrzenią.

2 .isIn(1,2,3,4,5) // <- notice the space between 2 and . 
+0

+1 hmm, jest to interesujące wykorzystanie białych znaków! –

+0

w rzeczywistości jest to dość logiczne - kropka jest standardowym operatorem w JavaScript, podobnie jak + lub = lub -. Możesz napisać coś w stylu 4 + 5, dzięki czemu możesz użyć 4. isIn() również. – Andris

+0

@Andris, świetna odpowiedź. Jednak, aby zauważyć, dodanie nawiasów jest lepsze (2) .isIn (1,2,3,4,5,6) (w sensie czytelności) – shabunc