JavaScript中Number方法的奇怪语法

6

请看下面的代码:

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

这是一个语法错误,因为你正在表示一个数字。字符串可以这样工作,但数字不能,因为紧跟在数字后面的句点表示十进制值。.之后的字符导致了错误。


7

大多数答案已经说明在数字字面量后面加一个点被认为是这个数字的一部分,作为小数分隔符。但如果你仍然想将点用作操作符,那么快速而简单的解决方法就是在数字和点之间留下一个空格。

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

其实这很合乎逻辑 - 点号在 JavaScript 中是一个标准操作符,就像 +、= 或 - 一样。你可以写类似于 4 + 5 的表达式,所以也可以使用 4 . isIn()。 - Andris
@Andris,非常好的答案。但是请注意,在可读性方面,添加括号更好(2).isIn(1,2,3,4,5,6)。 - shabunc

2

Josh是正确的,但你不必使用一个变量来使用数字的方法,尽管这样做通常更方便。

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)

5..isIn5 .isIn 都需要消除 [parsing] 歧义。 - Crescent Fresh

0

尽管由于自动类型转换,区分通常不明显,但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()不是可以解析为数字的有效字符序列。 (10).foo()将起作用,因为封闭括号(10)使.之前的整个结构成为单个表达式。该表达式将被计算并返回原始数字值10。然后.被视为在对象上下文中处理该原始值,因此它会自动包装在类型为Number的对象中(这是自动类型转换的作用)。然后,在该对象的原型链中找到该对象的foo属性;最后的()使该属性被视为函数引用,并在包装原始值时遇到.的点的this上下文中调用。


10Number(10) 是相同的。bar = Number(10) 并不会使 bar 成为“Number 类型的对象”。也许你想比较的是 10new Number(10)?或者是 '10'Number('10') - Crescent Fresh
糟糕,真是发现得好 - 缺少了 new 关键字。我应该从我进行测试的控制台中复制这些代码,而不是重新输入它们 :-) - NickFitz

-1

我的理解是数字是字面量,而不是对象。但是,当您将变量定义为数字时,它就成为了一个新的Number()对象。

因此,执行以下操作:

var x = 10;

这与前往相同;

var x = new Number(10);

关于第二个例子,我只能假设将括号放在数字周围使得JavaScript编译器认为该值是一个匿名的Number()对象。我想这也说得通...

3
x = 10x = new Number(10) 不是等价的。 - Crescent Fresh
正确的写法是:alert(typeof 10);,而不是 alert(typeof new Number(10)); - Josh Stodola

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接