我正在使用_.mixin()
为Underscore.js中的某些功能添加其他功能。我想要做的是重载调用,以便在使用原始签名时调用原始的Underscore函数。然而,保持对原始函数的引用是非常困难的。我已经尝试了多种方法来保持原始引用只有在_.mixin()
将参考点应用于新函数后才能找到。
(function() {
//Just using the base underscore pattern
var root = this;
//Save a object reference to the old function
var _oldCall = root._.oldCall;
root._.mixin({
oldCall: function (list, funk) {
//Call old function when we detect we should
if(/*detect old signature*/) return _oldCall(list, funk);
//Otherwise do something else
return 'something else';
}
});
}).call(this)
最终发生的事情是,当调用进入无限循环时抛出异常,并在堆栈不再推送函数调用时结束。如何替换旧函数的引用?
根据提交的答案,我为@Simon Boudrias建立了一个概念验证。一个只有一个克隆。另一个我试图用克隆替换_的值。第一个例子按预期工作,第二个例子让我大吃一惊,但是当我试图保留一个未经修改的参考时,我正在看到它。
var c = _.clone(_);
c.max(); //-Infinity
_.max()) //-Infinity
_.mixin({'max': function () {return 'whole bunches';}});
c.max(); //-Infinity
_.max(); //'whole bunches'
_ = c;
c.max(); //-Infinity
_.max(); //-Infinity
var backup = _;
var c = _.clone(_);
_ = c;
backup.max(); // -Infinity
_.max(); // -Infinity
_.mixin({'max': function () {return 'whole bunches';}};
backup.max(); // 'whole bunches'
_.max(); // -Infinity
_ = backup;
backup.max(); // 'whole bunches'
_.max(); // 'whole bunches'
答案 0 :(得分:1)
从我看到的,代码似乎没问题。唯一的问题是你应该确保在调用旧方法时保留上下文:_oldCall.call(root._, list, funk)
。
但是,如果方法是递归的(这似乎就是这种情况),这可能会带来奇怪的行为。
这就是为什么修改和不拥有对象通常是个坏主意的原因之一。
为了达到类似的效果,我相信你应该提供一个外观。要么是完整的下划线API,要么只是你要修改的方法。
var raw_ = root._;
var my_ = _.clone(root._); // Consider this pseudo code, I don't think _ clone deeply
my_.myOverride = function() {
// call the raw_ methods when necessary here
};
// Then export your underscore with your usual module system or global
export._ = my_;
// root.my_ = my_
或者只需制作自己的方法并在必要时导入:
exports = function() {
// my functions with call to _
}
答案 1 :(得分:1)
我测试了您的代码http://jsfiddle.net/WLCcd/
,并显示原始引用已保留,因此在其他位置查找错误
(function() {
//Just using the base underscore pattern
var root = this;
root._.mixin({
oldCall: function () {
console.log('old');
}
});
//Save a object reference to the old function
var _oldCall = root._.oldCall;
//delete root._.oldCall;
root._.mixin({
oldCall: function (list, funk) {
if(arguments.length == 0) return _oldCall();
console.log('new');
//Otherwise do something else
return 'something else';
}
});
console.dir(_oldCall);
_.oldCall();
_.oldCall(1);
}).call(this)