我正在创建一个JavaScript库。我一直在尝试实施链接。
0:我刚开始提出的内容:
function V(p) {
return {
add : function(addend) { return V(p + addend); },
sub : function(subtra) { return V(p - subtra); },
};
}
使用这种方法我可以轻松链接:
V(3).add(7).sub(5) // V(5)
不幸的是,结果始终是包装的V()函数,我无法以这种方式提取结果值。所以我想了一下这个问题并提出了两个半解决方案。
1:将旗帜传递给最后一种方法
function V(p, flag) {
if(flag)
return p;
else
return {
add : function(addend, flag) { return V(p + addend, flag); },
sub : function(subtra, flag) { return V(p - subtra, flag); }
};
}
使用这种方法,我可以通过将标志传递给我使用的最后一个方法来结束链接:
V(3).add(7).sub(5, true) // 5
虽然这很好用,但它需要重复一些代码,使链接的可读性降低,而且代码不那么优雅。
2:使用start()和end()方法
_chain = false;
function V(p) {
function Wrap(w) {
return (_chain) ? V(w) : w;
}
return {
add : function(addend) { return Wrap(p + addend); },
sub : function(subtra) { return Wrap(p - subtra); },
start : function() { _chain = true; },
end : function() { _chain = false; return p; }
};
}
使用此方法,您可以执行单个操作,而无需更多代码:
V(3).add(7) // 10
但链接需要两种方法,使得可读性低得多:
V(3).start().add(7).sub(5).end() // 5
所以基本上我只是在寻找在我的库中实现链接的最佳方法。理想情况下,我正在寻找一些可以使用任何方法的东西,而不需要以不优雅的方式终止链。
V(3).add(7).sub(5) // 5, perfect chaining
答案 0 :(得分:10)
为什么不引入私有变量并对其进行处理?我想这更方便。另外,拥有一个最终返回计算值的纯“getter”可能是一个好主意。这看起来像是:
function V(p) {
var value = p;
return {
add : function(addend) { value += addend; return this; },
sub : function(subtra) { value -= subtra; return this; },
get : function() { return value; }
};
}
V(5).add(7).sub(5).get(); // 5
显然,您无法在 getter功能中返回Object
。所以你需要一些链接结束并返回值的方法。
答案 1 :(得分:5)
在某些情况下,它确实需要与end
类似的东西,但在您的简单算术示例中,它不需要。
function V(initial_val){
if(!(this instanceof V)){
return new V(initial_val);
}
var num = initial_val || 0;
this.set = function(val){
num = val;
return this;
}
this.add = function(val){
num += val;
return this;
}
this.sub = function(val){
num -= val;
return this;
}
this.valueOf = function(){
return num;
}
this.toString = function(){
return ""+num;
}
}
通过向对象添加valueOf
和toString
函数,您可以访问其原始值。也就是说,您可以执行以下操作:
var num = V(0).add(1).sub(2), another_num = 3 + num; // num = -1 and another_num = 2;
答案 2 :(得分:2)
我会将Haochi的优秀答案修改如下:
如果你有很多V对象,那么使用原型会更有效率 在toString函数中,我用任意方式调用通用数字toString 你要关心的论点。
function V (n) {
if (!(this instanceof V)) {
return new V (n);
}
this.num = +n || 0;
return this;
}
V.prototype = {
set: function (val) {
this.num = val;
return this;
},
add: function (val) {
this.num += val;
return this;
},
sub: function (val) {
this.num -= val;
return this;
},
valueOf: function () {
return this.num;
},
toString: function () {
return this.num.toString.apply (this.num, arguments);
}
}