Bag*_*onè 5 javascript internet-explorer external
我在IE8上使用javascript扩展(AKA window.external)(可能是任何IE版本)来暴露某些功能.
我试图在window.external对象的函数上调用apply函数,它本身嵌入在每个JS函数中(应该是,根据这里),但浏览器不断抛出apply函数不存在的异常对于那个功能.
例如,此代码有效:
function onDataReceived(url, success, status, data, errorMessage) {
alert(onDataReceived);
}
function innerTest() {
alert(arguments[0] + ", " + arguments[1]);
}
function outerTest() {
innerTest.apply(null, arguments);
}
outerTest("hello", "world");
// alerts "hello, world"
Run Code Online (Sandbox Code Playgroud)
但是此代码抛出异常:
function outerTest() {
window.external.innerTest.apply(null, arguments); // <-- exception
}
outerTest("hello", "world");
Run Code Online (Sandbox Code Playgroud)
底线是 - 我需要将未知数量的参数传递给外部函数,到目前为止我已达到死胡同......
有任何想法吗?
编辑:
我接受了Mike Samuel的回答,因为(据我所知)apply
该window.external
对象中不存在该函数,因为它不是本机javascript对象.
迈克建议的"最坏情况"是我最终做的事情.
谢谢
Mik*_*uel 11
如果window.external
是宿主对象,或者是某些不希望其原型暴露给页面逻辑的扩展机制,那么它可能是一个函数,但可能没有通常call
和应用成员.幸运的是,您可以致电call
并申请apply
:
Function.prototype.apply.call(window.external, null, [argumentsToExtension])
Run Code Online (Sandbox Code Playgroud)
或者是真正的元,
Function.prototype.apply.apply(window.external, [null, [argumentsToExtension]])
Run Code Online (Sandbox Code Playgroud)
这里null
是什么,是作为价值传递this
,应被理解为window
用通常的呼叫/应用规则.
编辑:
如果这不起作用,你总是可以回到hackery的三角形.
function triangleOfHackery(obj, methodName, args) {
switch (args.length) {
case 0: return obj[methodName]();
case 1: return obj[methodName](args[0]);
case 2: return obj[methodName](args[0], args[1]);
case 3: return obj[methodName](args[0], args[1], args[2]);
...
}
}
Run Code Online (Sandbox Code Playgroud)
其实有一个通用的解决方案。一个简单的例子如下:
function invoke (funcName, ...args) {
var argStr = '';
for (let i in args) {
argStr += ', this.args[' + i + ']';
}
return (new Function('return window.external[\'' + funcName + '\'](' + argStr.substring(2) + ')')).bind({args})();
}
// define a circular structure which cannot be stringified:
const a = {}; a.a = a;
// make a call:
invoke('foo', 10, 'abc', new Date(), function(){}, a);
// equivalent to:
window.external.foo(10, 'abc', new Date(), function(){}, a);
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,没有必要保持参数可序列化。
主要思想是正确指定上下文,并将所有参数安装到该上下文上。
我这里使用ES6语法只是为了让代码更容易理解。当然,为了使其在 IE8 中工作,您可以将其转换为 ES5 兼容语法,并且您可能首先将 ES5 shim 包含在 polyfill 中Function.prototype.bind
。或者,你根本不需要bind
:
编辑:ES5 兼容版本:
function invoke (funcName) {
var argStr = '';
for (var i=1; i<arguments.length; i++) {
argStr += ', this.args[' + i + ']';
}
return {
args: arguments,
func: new Function('return window.external[\'' + funcName + '\'](' + argStr.substring(2) + ')')
}.func();
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
4571 次 |
最近记录: |