让数字值像5这样的数值“可链接”的一种方法是在适当的原型对象上定义一个方法,例如Number.prototype
。例如:
Number.prototype.add = function (n) {
return this + n
}
(5).add(2)
5.0.add(2)
5..add(2)
((5).add(2) + 1).add(34)
以上语法很有趣,因为
5.add(2)
是无效的:JavaScript在
5.
后面期望一个数字(或“nothing”)。由于
这是全局副作用(它将
影响所有数字),应该注意避免意外的交互。
使“5”可链式化的
唯一另一种方法是创建一个新的
Number
对象(5不是真正的Number实例,即使它使用了Number.prototype!)然后复制所需的方法。(我曾经认为这是唯一的另一种方法,但请参见KooiInc的答案-但我不确定从
toString
返回非字符串是否定义良好。)
function ops(a) {
return {
add: function(b) {
var res = new Number(a + b)
var op = ops(res)
res.add = op.add
return res
}
}
}
function number(a) {
return ops(a)
}
number(5).add(2) + 1
(number(5).add(2) + 1).add(34)
然而,需要记住这会引入一些微妙的问题:
typeof 5 // number
typeof new Number(5) // object
5 instanceof Number // false
new Number(5) instanceof Number // true
这就是为什么我们需要一个Number
(在JavaScript中搜索SO的“primitives”):
x = 5
x.foo = "bar"
x.foo // undefined
此外,结合cwolves的回答,考虑以下内容:
function number (n) {
if (this === window) {
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
愉快地编码。
res.add = op.add
这一行是不是把ops(number)
中的 add 方法复制到了res.add
中并返回它?如果是这样,那么如果你有多个方法需要链式调用怎么办?[x] - xx3004res.add = op.add; res.subtract = op.subtract
等很繁琐 :-) 然而,在该示例中,请注意每次调用op
时,都会创建一组新的函数。虽然可能不是问题,但这会创建更多的垃圾和数据绑定在闭包中,而不是使用原型的方法。 - user166390