OK, oto sytuacja:

var vowels = ['a', 'i', 'y', 'e', 'o', 'u'];
String.prototype.isVowel = function () {
  return vowels.indexOf(this) !== -1;
};

alert('a'.isVowel());

Zostanie czujny "False" od this odniesienia nie 'a' ale jego prototyp. Aby to było działać, musimy zrobić trochę zmian.

String.prototype.isVowel = function () {
  return vowels.indexOf(this[0]) !== -1;
};

alert('a'.isVowel());

To będzie działać od String.prototype zawiera wszystkie znaki oryginalnego ciągu. To faktycznie hack i nie podoba mi się to.

Ale co musimy zrobić, aby ten kod działa?

Number.prototype.is5 = function () { return this === 5; }

alert((5).is5()); //will alert 'false'

Czy po prostu nie musisz dotykać prototypów?

3
franza 6 grudzień 2013, 23:28

2 odpowiedzi

Najlepsza odpowiedź

Problem polega na tym, co nazywa się boks . Jeśli masz prymitywną wartość, a następnie wywołaj metodę tej wartości, zostanie on owinięty jako obiekt typu String, Number, Boolean lub co ty. Jest to równoznaczne z wywołaniem new String('a'), na przykład. (Jest udokumentowany w Specyfikacja ECMASCREPT)

new String('a') nie jest taki sam jak 'a'. Dlatego nie znajduje się w tablicy.

Co musisz zrobić, jest zatem przekształcić wartość z powrotem do prymitywnej wartości. Zawsze możesz to osiągnąć za pomocą metody valueOf:

return vowels.indexOf(this.valueOf()) !== -1;

Twoja metoda jest zadzwonić this[0]. To działa, ponieważ otrzymuje pierwszy znak z ciągu jako prymitywnego, który jest następnie znaleziony w ciągu. Minusem jest to, że ab zostanie również uznany za samogłoskę według tej metody.


Podobnie z liczbami:

 Number.prototype.is5 = function () { return this.valueOf() === 5; };

Jeden inny punkt: jest to domyślne zachowanie JavaScript. Nie jest oczywiste lub intuicyjne, jak pokazałeś. W ECMASCREPT 5 stworzono "tryb ścisły", gdzie wszystkie rodzaje niepożądanych zachowań są wyłączone. Auto-boks jest jednym z nich. Jeśli więc użyjesz nowoczesnej przeglądarki, będzie to miało oczekiwane zachowanie:

Number.prototype.is5 = function () {
    "use strict";
    return this === 5;
};
9
Givi 6 grudzień 2013, 20:22

Spójrz na sposób, który zadeklarowałeś String.prototype.isVowel, który działał akceptowalnie. Teraz spójrz na Number.prototipe.is5(). Zobacz różnice?

  • Prototipe jest błędnie napisany i powinien być prototypem.

  • is5 () nie powinien mieć () po nim.

To cię z tym opuszcza:

Number.prototype.is5 = //...

Powinieneś otrzymać błąd podczas ustawienia numeru.Prototy.is5 (), więc może to wszystko tylko literówki

0
Scott Mermelstein 6 grudzień 2013, 19:37