[英]Best way to implement Javascript chaining in a library
I'm creating a JavaScript library. 我正在创建一个JavaScript库。 I've been trying to implement chaining. 我一直在尝试实施链接。
0: What I first came up with: 0:我第一次提出的:
function V(p) {
return {
add : function(addend) { return V(p + addend); },
sub : function(subtra) { return V(p - subtra); },
};
}
Using this method I can chain easily: 使用这种方法我可以很容易地链接:
V(3).add(7).sub(5) // V(5)
Unfortunately the result is always a wrapped V() function, I am unable to extract the resulting value this way. 不幸的是,结果始终是一个包装的V()函数,我无法以这种方式提取结果值。 So I thought about this problem a bit and came up with two semi-solutions. 所以我想了一下这个问题并提出了两个半解决方案。
1: Passing flag to last method 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); }
};
}
Using this method I can end the chain by passing a flag to the last method I use: 使用这种方法,我可以通过将标志传递给我使用的最后一个方法来结束链:
V(3).add(7).sub(5, true) // 5
While this works just fine, it requires some code repetition and makes chaining less readable and my code less elegant. 虽然这很好用,但它需要重复一些代码,并且链接的可读性会降低,而且代码也不那么优雅。
2: Using start() and end() methods 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; }
};
}
Using this method you can do single operations with no more code: 使用此方法,您可以执行单个操作,而无需更多代码:
V(3).add(7) // 10
But chaining requires two more methods, making things a lot less readable: 但链接需要两种方法,使得可读性低得多:
V(3).start().add(7).sub(5).end() // 5
So basically I'm just searching for the best way to implement chaining into my library. 所以基本上我只是在寻找实现链接到我的库的最佳方法。 Ideally I'm looking for something where I can use any number of methods and don't need to terminate the chain in inelegant ways. 理想情况下,我正在寻找一些我可以使用任何方法的东西,而不需要以不优雅的方式终止链。
V(3).add(7).sub(5) // 5, perfect chaining
Why not introducing a private variable and working on that ? 为什么不引入一个私有变量并进行处理呢? I guess that is even more convinient. 我想这更方便。 Plus it's probably a good idea to have a pure "getter" which finally returns the computed value. 另外,拥有一个最终返回计算值的纯“getter”可能是一个好主意。 This could look like: 这可能看起来像:
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
You cannot return the Object
in a getter function obviously. 您显然无法在getter函数中返回Object
。 So you need some method where the chaining ends and returns a value. 所以你需要一些链接结束并返回值的方法。
In some cases it does need to have something similar to end
, but in your simple arithmetic example, it does not. 在某些情况下,它确实需要具有类似于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;
}
}
By adding valueOf
and toString
functions to the object, you can access its primitive value. 通过将valueOf
和toString
函数添加到对象,您可以访问其原始值。 That is, you can do something like: 也就是说,你可以这样做:
var num = V(0).add(1).sub(2), another_num = 3 + num; // num = -1 and another_num = 2;
I would amend Haochi's excellent answer as follows : 我会将Haochi的优秀答案修改如下:
Using the prototype will be more efficient if you have many V objects and in the toString function I invoke the generic number toString with whatever arguments you care to give it. 如果你有很多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);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.