Internet Explorer - javascript “apply” 函数在 window.external e
internet explorer - The Javascript "apply" function doesn't exist in window.external extension object
我在IE8上使用javascript扩展(AKA window.external(来公开某些功能。
我正在尝试调用 apply 函数,该函数(根据这里应该(本机嵌入到每个 JS 函数中,在 window.external 对象的函数上,但浏览器不断抛出异常,指出该函数不存在应用函数。
例如,此代码工作:
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"
但是此代码会引发异常:
function outerTest() {
window.external.innerTest.apply(null, arguments); // <-- exception
}
outerTest("hello", "world");
底线是 - 我需要将未知数量的参数传递给外部函数,到目前为止我已经走到了死胡同......
有什么想法吗?
编辑:
我接受了Mike Samuel的回答,因为(据我所知(apply
函数在window.external
对象中不存在,因为它不是本机javascript对象。
迈克建议的"最坏情况"是我目前最终所做的。
谢谢
如果window.external
是一个主机对象,或者来自某个不希望其原型公开给页面逻辑的扩展机制,那么它可能是一个函数,但可能没有通常的call
和应用成员。 幸运的是,您可以致电call
并申请apply
:
Function.prototype.apply.call(window.external, null, [argumentsToExtension])
还是真的元,
Function.prototype.apply.apply(window.external, [null, [argumentsToExtension]])
其中null
是作为this
的值传递的内容,应通过通常的调用/应用规则解释为window
。
编辑:
如果这不起作用,您可以随时退回到黑客三角形。
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]);
...
}
}
实际上有一个通用的解决方案。一个简单的例子如下:
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);
如您所见,没有必要保持参数可序列化。
主要思想是正确指定上下文,并将所有参数挂载到该上下文中。
我在这里使用了 ES6 语法,只是为了让代码更容易理解。当然,要使其在IE8中工作,您可以将其转换为与ES5兼容的语法,并且您可能首先包含ES5填充码以填充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();
}
- 未捕获的类型错误:topFrame.window.changeSelectedBarStyle不是函数,原因是什么
- 如何在javascript中添加带有回调函数的按钮点击事件作为window.conf
- 你能停止window.onload函数吗
- 使用window[variablename]()调用函数;在文档中.准备
- 确定window.load函数的优先级
- 成员函数中的Javascript“this”object==“window”
- 如何只使用一次window.onload函数
- 如何在 window.setInterval 中每分钟运行一次 getJSON 函数
- 如果我在 window.onbeforeunload 事件上确认是,我如何调用另一个 Java 脚本函数
- 为什么不'当用户输入空格或字符太多/不够时,此函数会发出window.alert
- 如何删除/重置window.onfocus函数
- 将Window Onload函数转换为非阻塞
- 为什么window.onload函数未定义
- window.load上单独的javascript文件中的引用函数
- 如何在javascript window.print()函数中打印MathML
- jquery window.load()函数赢得't在ios5上触发
- 函数后延迟window.open()
- window.opener调用函数给了我一个文档.getElementById(..)为null
- 函数 Window.focus 在 IE 中不起作用(8, 9, 10, 11)
- 使用 js 函数 window.history.back() 添加一个参数