我想执行以下操作。我有一个这样的代码:
var obj = {
method : function() {}
};
var func = function() {
return method(); //method is undefined here
};
func(); // What to do here?
是否可以以一种方式调用func,它将从obj中看到方法,例如它作为参数给出。我想在func中使用obj.method,而无需编写' obj。'在修改func本身之前和之后。是否有任何黑客可以实现这一目标? 换句话说,是否有可能强制obj作为func的闭包? 我试过了:
with(obj) {
func();
}
但它不起作用。任何人,任何想法?或者它是唯一的选项,将函数的主体作为字符串,放置'与(obj)'在它里面,然后从中创建一个新功能?
澄清: 因为这段代码将在帮助类中“eval'没关系我不想要的是通过.toString()修改函数,因为浏览器以不同的方式实现它。
答案 0 :(得分:2)
这是一个解决方案,使用eval
(MDN):
var obj = {
method : function() {console.log("it workes!");}
};
var func = function() {
return method(); //method is undefined here
};
var newfunc = (function (obj, func) {
var method = obj.method;
eval("var f = " + func.toString());
return f;
}(obj, func));
newfunc(); //it workes
基本上,您只是使用名为method
的局部变量创建一个新范围,并重新评估此范围内的函数体。所以你基本上是在创建一个具有相同主体的新功能。我不太喜欢这种方法,我不推荐它,但考虑到你的限制,它可能是唯一的解决方案。
是的,它仍然要求你写obj.method
,但不要写func
。所以我想,应该没问题。
修改强>
所以这是一个版本,您不必手动指定属性名称:
var newfunc = (function (__obj__, __func__) {
for (var __key__ in __obj__) {
if (__obj__.hasOwnProperty(__key__)) {
eval("var " + __key__ + " = " + __obj__[__key__]);
}
}
eval("var __f__ = " + func.toString());
return __f__;
}(obj, func));
这也是通过使用eval()
。
请注意,我将所有剩余的局部变量更改为包含下划线的名称,以最小化名称与obj
内的属性冲突的可能性。
另请注意,并非所有有效的属性名称都是有效的变量名称。你可以有这样一个对象:
var obj = {
"my func": function () {}
}
但是如果您使用此对象,您将使用上述方法生成语法错误,因为它会尝试评估:
var my func = ...
正如apsillers在评论部分所说,如果你无法控制obj
的属性,那就更糟了。在这种情况下,您根本不应该使用eval
,因为您可以非常轻松地进行跨站点脚本攻击(例如来自apsillers):
var obj = {
"a; alert('xss'); var b": function () {}
}
会评估3个不同的陈述:
var a;
alert('xss');
var b = function () {};
答案 1 :(得分:1)
除非您单独定义method
,否则无法进行此操作:
var obj = {
method : function() {}
},
method = obj.method;
// rest of code
这是因为method
内的func()
引用假定window.
命名空间;因此,如果不修改func()
本身,就无法做到理智。
答案 2 :(得分:0)
更多基于basilikum答案的澄清版本,我发现了'with'的简化:
var obj = {
method : function() { return "it workes!"; }
};
var func = function() {
return method(); //method is undefined here
};
(function (obj, func) {
with(obj) {
eval("var __res__ = (" + func.toString() + ")()");
}
return __res__;
}(obj, func));
>> "It workes!"