在函数内部使对象的属性可用

时间:2014-01-13 15:30:14

标签: javascript

我想执行以下操作。我有一个这样的代码:

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()修改函数,因为浏览器以不同的方式实现它。

3 个答案:

答案 0 :(得分:2)

这是一个解决方案,使用evalMDN):

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!"