2014-10-03 41 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

相關問題