5のような数値を「連鎖可能」にする1つの方法は、などの適切なプロトタイプオブジェクトにメソッドを定義することNumber.prototype
です。例えば:
Number.prototype.add = function (n) {
return this + n
}
(5).add(2) // 7
5.0.add(2) // 7
5..add(2) // 7
((5).add(2) + 1).add(34) // okay! 42
上記の構文5.add(2)
は無効であるためおかしいです。JavaScriptは。の後に数字(または「何もない」)を期待しています5.
。これはグローバルな副作用であるため(すべての数値に影響します)、予期しない相互作用を回避するように注意する必要があります。
他の唯一の「5」をチェーン可能にする別の方法は、新しいNumber
オブジェクトを作成し(Number.prototypeを使用している場合でも5は実際のNumberインスタンスではありません!)、必要なメソッドをコピーすることです。(以前はこれが唯一の方法だと思っていましたが、KooiIncの回答を参照してください。ただし、から非文字列を返すことがどれほど明確に定義されているかはわかりませんtoString
。)
function ops(a) {
return {
add: function(b) {
var res = new Number(a + b) // important!
var op = ops(res)
res.add = op.add // copy over singletons
return res
}
}
}
function number(a) {
return ops(a)
}
number(5).add(2) + 1 // 8
(number(5).add(2) + 1).add(34) // error! add is not a function
ただし、これにより微妙な問題が発生することに注意してください。
typeof 5 // number
typeof new Number(5) // object
5 instanceof Number // false
new Number(5) instanceof Number // true
そして、これが私たちが必要とする理由ですNumber
(JavaScriptで「プリミティブ」をSOで検索してください):
x = 5
x.foo = "bar"
x.foo // undefined
さらに、cwolvesの回答と併せて、次のことを考慮してください。
function number (n) {
if (this === window) { // or perhaps !(this instanceof number)
return new number(n)
} else {
this.value = n
}
}
次に、両方new number(2)
と両方が新しい数値オブジェクトnumber(2)
に評価されます。
number(2).value // 2
new number(2).value // 2
number(2) instanceof number // true
new number(2) instanceof number // true
ハッピーコーディング。