以编程方式向 javascript 函数添加代码

我试图在不修改原始 JS 代码的情况下定制现有的 JS 库。这段代码加载了一些我可以访问的外部 JS 文件,我想要做的是修改原始文件中包含的一个函数,而不是将整个内容复制粘贴到第二个 JS 文件中。
例如,禁区 JS 可能有这样一个函数:

var someFunction = function(){
alert("done");
}

我希望能够以某种方式附加或预置一些 JS 代码到该函数中。原因主要是在原始的不可触摸的 JS 函数是相当庞大的,如果该 JS 曾经得到更新,我覆盖它的函数将过期。

我不确定这是否可行,但我觉得应该检查一下。

58515 次浏览

first store the actual function in a variable..

var oldFunction = someFunction;

然后定义你自己的:

someFunction = function(){
// do something before
oldFunction();
// do something after
};

您可以创建一个调用代码的函数,然后调用该函数。

var old_someFunction = someFunction;
someFunction = function(){
alert('Hello');
old_someFunction();
alert('Goodbye');
}

我不知道你是否可以更新这个函数,但是取决于它是如何被引用的,你可以在它的位置创建一个新的函数:

var the_old_function = someFunction;
someFunction = function () {
/* ..My new code... */
the_old_function();
/* ..More of my new code.. */
}

如果 someFunction是全局可用的,那么您可以缓存该函数,创建您自己的函数,并让您的函数调用它。

如果这是真品。

someFunction = function() {
alert("done");
}

你会这么做。

someFunction = (function() {
var cached_function = someFunction;


return function() {
// your code


var result = cached_function.apply(this, arguments); // use .apply() to call it


// more of your code


return result;
};
})();

这是小提琴


注意,我使用 .apply来调用缓存函数。这使我能够保留 this的预期值,并将传入的任何参数作为单独的参数传递,而不管传入的参数有多少。

如果你想改变局部上下文,你必须重新创建函数。例如:

var t = function() {
var a = 1;
};


var z = function() {
console.log(a);
};

现在

z() // => log: undefined

然后

var ts = t.toString(),
zs = z.toString();


ts = ts.slice(ts.indexOf("{") + 1, ts.lastIndexOf("}"));
zs = zs.slice(zs.indexOf("{") + 1, zs.lastIndexOf("}"));


var z = new Function(ts + "\n" + zs);

还有

z() // => log: 1

但这只是最简单的例子。要处理参数、注释和返回值还有很多工作要做。此外,还有许多陷阱。
ToString | 切片 | 索引 | 最后索引 | < a href = “ https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global _ Objects/Function”rel = “ noReferrer”> new Function

代理模式(user1106925使用的)可以放在函数中。下面我写的这个函数可以处理不在全局范围内的函数,甚至可以处理原型。你可以这样使用它:

extender(
objectContainingFunction,
nameOfFunctionToExtend,
parameterlessFunctionOfCodeToPrepend,
parameterlessFunctionOfCodeToAppend
)

在下面的代码片段中,您可以看到我使用该函数来扩展 test.Prototype.doIt ()。

// allows you to prepend or append code to an existing function
function extender (container, funcName, prepend, append) {


(function() {


let proxied = container[funcName];


container[funcName] = function() {
if (prepend) prepend.apply( this );
let result = proxied.apply( this, arguments );
if (append) append.apply( this );
return result;
};


})();


}


// class we're going to want to test our extender on
class test {
constructor() {
this.x = 'instance val';
}
doIt (message) {
console.log(`logged: ${message}`);
return `returned: ${message}`;
}
}


// extends test.prototype.doIt()
// (you could also just extend the instance below if desired)
extender(
test.prototype,
'doIt',
function () { console.log(`prepended: ${this.x}`) },
function () { console.log(`appended: ${this.x}`) }
);


// See if the prepended and appended code runs
let tval = new test().doIt('log this');
console.log(tval);