Javascript链规则,返回特定值而不是[Object][x]
问题在标题处,但首先请看以下代码:Javascript链规则,返回特定值而不是[Object][x],javascript,return-value,simulation,chain,Javascript,Return Value,Simulation,Chain,问题在标题处,但首先请看以下代码: function number(a) { return { add: function(b) { result = a + b; return this; }, substract(b) { result = a - b; return this; } } 上面这些代码是链式规则的简单示例。我重新运行一个对象
function number(a) {
return {
add: function(b) {
result = a + b;
return this;
}, substract(b) {
result = a - b;
return this;
}
}
上面这些代码是链式规则的简单示例。我重新运行一个对象,以便可以连续执行该操作:
number(2).add(5).add(3 * 12).substract(Math.random());
我的问题是,我必须重新运行一个对象以保持函数的可链接性。我想输入链式规则,但要返回特定的值。例如number(2)。add(3)
将返回5
非常感谢您的任何建议
提前感谢大家。
[x] 您有两个选择。您可以返回新对象:
function number(a){
return this instanceof number ? (this.value = a, this) : new number(a);
}
number.prototype = {
valueOf : function(){
return this.value;
},
add : function(b){
return new number(this.val + b);
},
subtract : function(b){
return new number(this.val - b);
}
};
或者您可以修改现有的代码(大部分代码与上面相同,这是不同的):
区别在于它们的行为方式:
var x = new number(5),
y = x.add(10);
// with first example
// x == 5, y == 15
// with 2nd example
// x == 15, y == 15, x === y
使数字值如5“可链接”的一种方法是在适当的原型对象上定义一个方法,例如
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.
之后需要一个数字(或“nothing”)。因为这是一个全球性的副作用(它会影响所有的数字),所以应该注意避免意外的互动
使“5”链能够运行的另一种方法是创建一个新的Number
对象(5不是实数实例,即使它使用Number.prototype!),然后复制所需的方法。(我过去认为这是唯一的另一种方法,但请看KooiInc的答案——然而,我不确定从返回非字符串到字符串的定义有多明确。)
但是,请记住,这会带来一些微妙的问题:
typeof 5 // number
typeof new Number(5) // object
5 instanceof Number // false
new Number(5) instanceof Number // true
这就是为什么我们需要一个数字(在JavaScript中搜索“原语”):
此外,结合cwolves的回答,考虑:
function number (n) {
if (this === window) { // or perhaps !(this instanceof number)
return new number(n)
} else {
this.value = n
}
}
然后,新编号(2)
和编号(2)
都将计算为新编号对象
number(2).value // 2
new number(2).value // 2
number(2) instanceof number // true
new number(2) instanceof number // true
快乐编码。如果将值定义为属性(this.a
),并在返回的对象中使用toString
,则可以链接方法:
function number(a) {
return {
a: Number(a) || 0, //if not a, or a===NaN, default = 0
add: function(b) {
this.a += b;
return this;
},
subtract: function(b){
this.a -= b;
return this;
},
valueOf: function(){
return Number(this.a);
},
toString: this.valueOf
}
}
var n = number(5);
alert(number.add(5).add(2).subtract(2)); //=> 10
alert(number.add(0.5)); //=> 10.5
alert(number(2).add(5).add(3 * 12).subtract(Math.random());
//=> 42.36072297706966
嗨,克沃尔夫斯。现在可以了。但是我想知道是否有其他方法可以链接函数(比如jQuery)并返回特定值而不创建新对象?我的意思是x=数字(2)。添加(2)。添加(3)
而不是x=新数字(2);x、 添加(2)。添加(3)
?[x] @xx3004-从构造函数中做出返回语句:返回这个instanceof number?本:新编号(a)代码>。将样本修改为reflect@cwolves我会将检查移到函数的顶部,以避免在“非新”情况下重复工作(即使在本例中它非常简单)。它还避免了在单个尾随三元条件中“隐藏”意图:)@cwolves Ahh正在查看注释,而不是更新的代码。我只是觉得更新后的代码“太聪明了”:@pst-以前有人批评我使用逗号:)不管怎样,我的观点是正确的。如果构造函数实际上很复杂,那么将If(!this instanceof number){return new number(a);}
放在构造函数的顶部+1(上面应该显示的number(5)+3
,结果是8——至少在Firefox4中是这样)。您知道从toString
返回非字符串是否/在何处定义良好吗?根据我的示例,应该使用valueOf而不是toString:)@all:实际上,仅仅valueOf
不起作用,但您可以强制toString
使用valueOf
-请参阅我的编辑。这是一篇关于对象到原语转换的好文章:这篇文章正如我所期望的那样完美,但我仍然不明白为什么toString:This.valueOf这行太重要了?我甚至没看到你叫它,那它是干什么的?[x] @xx3004链接文章很好。出于某种原因,我认为那些(转换函数)只是内部定义的。。。我真傻。这一个工作正常,但有点复杂。我认为这是一个方便的方法,我从这个例子中学到了很多。我这里有点混乱,行res.add=op.add
是否将add方法从ops(number)复制到res.add,然后返回?如果你这样做了,如果你有不止一种方法来链接会发生什么?[x] @xx3004许多框架都提供了一种方法,可以同时复制一组属性。(因为执行res.add=op.add;res.subtract=op.subtract
等操作非常繁琐:-)但是,在该示例中,请注意,每次调用op
时,都会创建一组新的函数。虽然这可能不是一个问题,但与使用原型的方法相比,这会在闭包中创建更多的垃圾和数据绑定。
function number (n) {
if (this === window) { // or perhaps !(this instanceof number)
return new number(n)
} else {
this.value = n
}
}
number(2).value // 2
new number(2).value // 2
number(2) instanceof number // true
new number(2) instanceof number // true
function number(a) {
return {
a: Number(a) || 0, //if not a, or a===NaN, default = 0
add: function(b) {
this.a += b;
return this;
},
subtract: function(b){
this.a -= b;
return this;
},
valueOf: function(){
return Number(this.a);
},
toString: this.valueOf
}
}
var n = number(5);
alert(number.add(5).add(2).subtract(2)); //=> 10
alert(number.add(0.5)); //=> 10.5
alert(number(2).add(5).add(3 * 12).subtract(Math.random());
//=> 42.36072297706966