在下面的函数cat
中,您可以直接调用eat
和play
函数,而无需实例化新的cat
对象,这可以通过传入来自函数cat.eat
进入cat.play
函数以获取状态。
var cat = function(obj){
// if (obj instanceof cat) return obj;
// if (!(this instanceof cat)) return new cat(obj);
// this.catwrapped = obj;
}
cat.eat = function(food){
if(food == "tuna") return 95
if(food == "milk") return 35
return 0
}
cat.play = function(energy){
if(energy < 50) return 0
return 100
}
var energy = cat.eat("tuna")
var status = cat.play(energy)
console.log(status) // 100
我正在尝试保留此功能并添加下划线样式链。所以你可以做到以下几点。这是怎么回事?
cat.day = function(obj){
var instance = cat(obj);
// instance._chain = true;
return instance;
}
var status = cat.day()
.eat("tuna")
.play()
.status()
console.log(status) // should log 100
我需要在cat
和cat.day
中使用此代码的最低代码是什么?
答案 0 :(得分:0)
您需要返回对象的指针才能执行链式调用:
cat.play = function(energy){
// do something with energy
return cat
}
cat.eat = function(food){
// do something with food
return cat
}
var status = cat.day()
.eat("tuna")
.play()
.status()
由于您将return用于不同的目的(之后忽略它),您需要重新考虑您的程序算法
更新。您可以根据参数创建将执行任务或返回数据的函数:
var energy = 0;
cat.eat = function(v) {
// return something on empty call
if (!arguments.length) return energy
// process passed data
energy += v
// return cat object to allow chaincals
return cat
}
在这种情况下,cat.eat(10)将允许您执行链式调用,而cat.eat()将返回值,存储在能量中
Update2:您的函数不会改变任何内部变量,因此任何数据都将在标准链式调用中丢失。你做什么,你需要一个管道,并将一个功能直接输出到另一个输入。有很多方法可以做到:
您可以尝试使用下划线缩减功能:
var status = _.reduce([cat.play, cat.eat], function(status, f){ return f(status); }, "tuna");
或者你可以直接打电话给他们:
cat.status(cat.play(cat.eat("tuna")))
如果您创建内部变量来存储能量,您甚至可以调用下划线链:
var cat = function() {
this.energy = 0;
}
cat.eat = function(food){
if (food == "tuna") cat.energy = 95
else if(food == "milk") cat.energy = 35
else cat.energy = 0
}
cat.play = function(){
if(cat.energy < 50) cat.energy = 0
else cat.energy = 100
}
var status = _.chain(cat)
.eat("tuna")
.play()
.value()
.energy
但似乎有点多余
答案 1 :(得分:0)
我复制了所有使其可链接的下划线功能,并将其添加到对象的末尾。
这个想法是你可以创建像普通函数一样的函数,执行某种输入/输出操作。然后,您可以循环遍历所有这些函数,并构建原型,这些原型涉及使对象可以链接,例如存储数据和传输参数。
var _ = require("underscore")
var cat = function(obj) {
if (obj instanceof cat) return obj;
if (!(this instanceof cat)) return new cat(obj);
this._wrapped = obj;
};
cat.eat = function(food){
if(food == "tuna") return 95
if(food == "milk") return 35
return 0
}
cat.play = function(energy){
if(energy < 50) return 0
return 100
}
// Add a "chain" function. Start chaining a wrapped Underscore object.
cat.chain = function(obj) {
var instance = cat(obj);
instance._chain = true;
return instance;
};
// Helper function to continue chaining intermediate results.
var chainResult = function(instance, obj) {
return instance._chain ? cat(obj).chain() : obj;
};
var ArrayProto = Array.prototype
var push = ArrayProto.push
cat.mixin = function(obj) {
_.each(_.functions(obj), function(name) {
var func = cat[name] = obj[name];
cat.prototype[name] = function() {
var args = [this._wrapped];
push.apply(args, arguments);
return chainResult(this, func.apply(cat, args));
};
});
};
// Add all of the Underscore functions to the wrapper object.
cat.mixin(cat);
// Extracts the result from a wrapped and chained object.
cat.prototype.value = function() {
return this._wrapped;
};
// var energy = cat.eat("tuna")
// var status = cat.play(energy)
//
// console.log(status) // 100
var status = cat.chain("tuna")
.eat()
.play()
.value()
console.log(status) // 100
更新:
我使函数使任何对象成为可链式对象的下划线mixin。
这里是mixin:
var _ = require("underscore")
_.mixin({
prototypeChain: function(thObj){
return function(obj) {
var instance = thObj(obj);
instance._chain = true;
return instance;
}
},
prototypeExtend: function(theObj){
var chainResult = function(instance, obj) {
return instance._chain ? theObj(obj).chain() : obj;
}
var prototypes = _.map(_.functions(theObj), function(name) {
var func = theObj[name];
theObj.prototype[name] = function() {
var args = [this._wrapped];
Array.prototype.push.apply(args, arguments);
return chainResult(this, func.apply(theObj, args));
};
});
_.extend(theObj, prototypes)
},
prototypeValue: function(){
return function(){
return this._wrapped;
}
}
})
以下是它的工作原理:
var cat = function(obj) {
if (obj instanceof cat) return obj;
if (!(this instanceof cat)) return new cat(obj);
this._wrapped = obj;
};
cat.eat = function(food){
if(food == "tuna") return 95
if(food == "milk") return 35
return 0
}
cat.play = function(energy){
if(energy < 50) return 0
return 100
}
cat.chain = _.prototypeChain(cat)
_.prototypeExtend(cat)
cat.prototype.value = _.prototypeValue()
var energy = cat.eat("tuna")
var status = cat.play(energy)
console.log(status) // 100
var status = cat.chain("tuna")
.eat()
.play()
.value()
console.log(status) // 100
答案 2 :(得分:0)
我创建了一个npm模块underscore-chainable
来做这件事。
npm install underscore-chainable
然后
var _ = require("underscore")
_.mixin(require("underscore-chainable"))
var cat = _.makeChainable() // make the `cat` object chainable
cat.eat = function(food){
if(food == "tuna") return 95
if(food == "milk") return 35
return 0
}
cat.play = function(energy){
if(energy < 50) return 0
return 100
}
_.extendChainable(cat) // extend the chainablity
// adds `.chain` and `.value`
var energy = cat.eat("tuna")
var status = cat.play(energy)
console.log(status) // 100
var status = cat
.chain("tuna")
.eat()
.play()
.value()
console.log(status) // 100