我不认为有这样的事情,因为我想我现在已经找到了它,但唯一可以确定的方法就是给出一个直接的答案,因此我必须在放弃之前先问一下。我需要一个每次尝试访问对象方法时都会调用的方法。 JavaScript中有这样的东西吗?
基本上我需要在每个对象的方法之前和之后运行几行。对它们进行硬编码实际上不是一种选择。我想到的另一件事就是有一个像
这样的主要方法Mainmethod(ActualMethod, Parameters)
但这对我来说真的不好看,我真的不想这样做。
答案 0 :(得分:2)
如果这只是针对特定对象或特定类型的对象,您可以使用自己的存根来动态替换所有方法,这些存根执行前期工作,调用原始方法然后进行后期工作。
这样的事情会起作用:
function overideMethods(obj) {
// can pass either an instantiated object (hooks existing methods on the object)
// or a function constructor (hooks methods in the prototype)
if (typeof obj === "function") {
obj = obj.prototype;
}
for (var prop in obj) {
if (typeof obj[prop] === "function") {
(function(origMethod) {
obj[prop] = function() {
var retVal, args;
// do your pre-work here
// make copy of args passed to this method
args = Array.prototype.slice.call(arguments, 0);
// call original method with proper args
retVal = origMethod.apply(this, args);
// do your post-work here
return retVal;
};
})(obj[prop]);
}
}
}
工作演示:http://jsfiddle.net/jfriend00/7LzQj/
现在可以将此函数传递给对象或构造函数。如果传递一个对象,它将挂钩该对象上的现有可枚举方法。如果你传递一个构造函数,它将挂钩构造函数原型上的方法。这允许您为整个构造函数(预先)创建的所有对象设置挂钩,或者只挂钩单个对象。
如果您的对象动态地添加方法,无论是在构造函数中还是在对象生命周期的后期,并且您希望这些方法被挂钩,那么您需要在添加这些方法之后在对象上调用overideMethods()
- 您将无法在构造函数上调用它。
答案 1 :(得分:1)
这是一个使用函数装饰器的可能解决方案。如果你有像Underscore这样的东西你可以修改一下代码,但我假设你没有。
装饰器是一个高阶函数,它返回另一个函数的修改版本。在某些情况下,装饰器是一种更安全的猴子修补方法,但这完全取决于您的需求。
以下是演示:http://jsbin.com/ApaLAVab/1/edit
function compose(f, g) {
return function() {
return f(g.apply(this, arguments));
};
}
function before(fn) {
return function() {
console.log('before'); // code before method
fn.apply(this, arguments);
};
}
function after(fn) {
return function() {
fn.apply(this, arguments);
console.log('after'); // code after method
};
}
var run = compose(before, after);
function A() {}
A.prototype = {
say: run(function(name) { // decorate method
console.log('Hello '+ name);
})
};
var a = new A();
a.say('Peter');
//^ before
// Hello Peter
// after
答案 2 :(得分:0)
您也可以将其添加到构造函数中,因此您不必手动运行它:
function SimpleClass(){
this.overideMethods();
}
SimpleClass.prototype.overideMethods = function() {
var obj = this;
for (var prop in obj) {
if (typeof obj[prop] === "function") {
console.log(prop);
(function(origMethod) {
obj[prop] = function() {
var retVal, args;
// do your pre-work here
alert("before function call");
// make copy of args passed to this method
args = Array.prototype.slice.call(arguments, 0);
// call original method with proper args
retVal = origMethod.apply(this, args);
// do your post-work here
alert("after function call");
return retVal;
};
})(obj[prop]);
}
}
}
SimpleClass.prototype.testFn = function(){
alert("In the function.");
};
var testObj = new SimpleClass();
testObj.testFn();
工作示例:http://jsfiddle.net/awesomepeter/wvxAd/1/ 归功于jfriend00,我想做同样的事情,因为他来得有点太晚了;)所以我只是复制了他的答案并改进了。