2014-10-03 33 views
1

假设我想让所有Numbers在制作完成后都拥有属性foo,例如包含类似其值的两倍的东西。我想要做如何扩展像Object或Number之类的内建构造函数?

// extend Number constructor here. 
console.log(5.foo); // outputs 10 

你是怎么做到的?

+0

数字是原始的。你可以做到这一点,如果你创建一个对象,但为什么? – elclanrs 2014-10-03 21:56:22

+0

我不知道这是否可能,但它可能是一个非常糟糕的主意。想象一下,有人在阅读你的代码,并在某处使用了一个'number.foo'变量,这实际上是数字值的两倍。如果你写了一个像'valueTwice(num)'这样的方法,它会不会更具可读性? – 2014-10-03 22:00:46

+0

不要扩展原始对象,这是一个非常糟糕的主意。 – 2014-10-03 22:15:18

回答

2

你不延长构造,而是原型,通过defining a new property就可以了,用“吸”:

Object.defineProperty(Number.prototype, 'foo', { 
    get: function() { return this * 2; } 
}); 

> 1.foo 
    SyntaxError   // parser expected decimal part of number after dot 
> (1).foo 
    2 
> 1..foo 
    2 
> 1.0.foo 
    2 
> Number(1).foo 
    2 
> new Number(1).foo 
    2 
> 1['foo'] 
    2 
> 1e0.foo    // exponential notation 
    2 
> parseInt('1px').foo 
    2 
> 0x1.foo    // hex 
    2 
> 01.foo    // octal, disallowed in strict mode 
    2 
> Math.PI.foo 
    6.283185307179586 
> Infinity.foo 
    Infinity 
> NaN.foo 
    NaN 

为什么第一个例子1.foo失败? JS解析器一旦看到点,就会有小数部分。这是没有办法的。所以你必须满足于说1.0.foo

但是1.0是一个原始的不是对象,对吧?那么,1.0.foo怎么可能工作?因为JavaScript会在必要时将基元强制转换(转换或转换)为对象。在这种情况下,数值强制转换为数字对象,只需足够长的时间以计算foo的值,然后丢弃该对象(通过垃圾回收)。

有人可能会受到诱惑,也能实现一个二传手,在

set: function(v) { this = v/2; } 

,但当然,这是无效的;我们不能设置this!并且无法访问Number对象下的[[PrimitiveValue]]来设置它。

我不推荐以上内容,以这种方式扩展内置类型并不被认为是最佳实践。这最好放在异域的领域。

+0

但是不可以做5.px? – trusktr 2014-10-04 16:34:00

+0

你也可以做'1..foo',但是看起来就算很奇怪 – david 2014-10-05 04:04:01

1

你需要扩展原型:

Number.prototype.foo = function(){ 
return this*2; 
} 

芹苴这是一个方法不是成员。 num = 2; num.foo(); //返回4