Странный синтаксис числовых методов в JavaScript - PullRequest
6 голосов
/ 07 декабря 2009

Взгляните на следующий код:

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'

Почему, когда это переменная, код работает правильно, но когда он является числовым литералом, он не работает?


А также, как ни странно, почему работает следующая строка?

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

В приведенной выше строке я в основном заключил литерал в круглые скобки.

Ответы [ 5 ]

10 голосов
/ 07 декабря 2009

Это синтаксическая ошибка, потому что вы представляете число. Строки могут работать таким образом, но не числами, потому что точка, следующая сразу за числом, символизирует десятичное значение. Символ после . вызывает ошибку.

7 голосов
/ 07 декабря 2009

В большинстве ответов уже говорилось, что точка после числового литерала считается частью этого числа в качестве разделителя дроби. Но если вы все еще хотите использовать точку в качестве оператора, то быстрое и простое исправление оставит пустое пространство между числом и пробелом.

2 .isIn(1,2,3,4,5) // <- notice the space between 2 and .
2 голосов
/ 07 декабря 2009

Джош был прав, но вам не нужно использовать переменную, чтобы использовать метод числа, хотя обычно это удобнее сделать.

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 голосов
/ 07 декабря 2009

Хотя различие часто неочевидно из-за автоматического преобразования типов, JavaScript поддерживает ряд примитивных типов, а также объектов:

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"

и что-то, что действительно смущает проблему:

// 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"));

Хотя использование автоматического преобразования типов делает жизнь немного проще, в глубине души всегда нужно хорошо понимать, какие типы являются вашими примитивными значениями и объектами; неожиданно большое количество ошибок JS возникает из-за того, что люди не понимают, что, например, что-то, что выглядит как число, на самом деле является строкой, или что некоторая операция, которую они выполнили, привела к чему-то, что раньше содержало число, имеющее было присвоено новое значение, которое является строкой или объектом.

РЕДАКТИРОВАТЬ: для более подробного рассмотрения исходного вопроса, на который я теперь понимаю, что я не ответил явно: 10.foo() вызовет синтаксическую ошибку, поскольку . рассматривается как десятичная точка, а foo() isn ' • допустимая последовательность символов для анализа в виде числа. (10).foo() будет работать в качестве заключающих в скобки (10) превратить всю конструкцию до . в одно выражение. Это выражение вычисляется и возвращает значение простого числа 10. Тогда . рассматривается как обработка этого примитивного значения в контексте объекта, поэтому он автоматически переносится в объект типа Number (это автоматическое преобразование типа в действии). Затем ссылка на свойство foo этого объекта, найденного в его цепочке прототипов; и окончательное значение () приводит к тому, что это свойство обрабатывается как ссылка на функцию и вызывается в контексте this для объекта Number, который был обернут вокруг примитивного значения в точке обнаружения ..

.
0 голосов
/ 07 декабря 2009

Насколько я понимаю, числа являются литералами, а не объектами. Однако когда вы определяете переменную как число, она становится новым объектом Number ().

Так делаем следующее;

var x = 10;

То же самое, что и идти;

var x = new Number(10);

Что касается второго примера; Я могу только предположить, что заключение в скобки вокруг числа заставило компилятор JavaScript предположить, что значение является анонимным объектом Number (). Что имеет смысл, я думаю ...

...