直接修改函数有多危险?

时间:2012-07-09 03:23:32

标签: javascript

为了解决已证明对我有限制的范围(如here所述),我编写了一段代码,在匿名函数中插入一行,这样无论谁编写函数都没有必须自己做。它有点hacky(实际上,它感觉相当多hacky),我真的不知道我在做什么,所以我很欣赏专家的眼睛来捕捉我可能错过的任何错误或指出任何危险我我没有意识到。这是代码:

function myObj(testFunc) {
    this.testFunc = testFunc;


    this.Foo = function Foo(test) {
        this.test = test;

        this.saySomething = function(text) {
            alert(text);
        };
    };

    var Foo = this.Foo;
    var funcSep = this.testFunc.toString().split("{");
    funcSep.splice(0, 1);
    funcSep = funcSep.join("{");
    var compFunc =  "    var Foo = this.Foo;" + funcSep;
    compFunc = compFunc.split("}");
    compFunc.splice(compFunc.length - 1, 1);
    compFunc.join("}");
    var otherTestFunc = new Function(compFunc);
    otherTestFunc.apply(this);
}

var test = new myObj(function() {
    var test = new Foo();
    test.saySomething("Hello world");
});

上面的函数按预期进行评估,我不需要强制编写匿名函数的人使用Foo来获取对this.Foo的访问权限。不过,这种方法感觉不确定。我正在接受什么,如果没有,有没有办法绕过它?

此外,我在原始问题中没有包含此内容的唯一原因是,这似乎与问题的原始背景有所不同。

2 个答案:

答案 0 :(得分:2)

你正试图打破这种语言。不要那样做。这不是Java。

开发人员对变量的行为和范围有一定的期望,而你的方法宁愿混淆它们。想想以下内容:

var Foo = SomeWonderfulClass;    
var test = new myObj(function() {
    var test = new Foo();
    // ...
});

现在,开发人员想要实例化SomeWonderfulClass,但是你的魔法会与之混淆。

另一方面,即使你的诡计,这也可以正常工作:

var test = new myObj(function() {
    var Foo = SomeWonderfulClass;    
    var test = new Foo();
    // ...
});

但更大的问题是实际范围丢失了:

var Bananas = SomeWonderfulClass;
var test = new myObj(function() {
    var test = new Bananas(); // Error: Bananas is undefined!
});

没有人期望这样的恶作剧。


话虽如此,您的代码还有一些需要改进的地方:

  • this.Foo初始化为每个新对象。这不是必要的。更好地使用

    myObj.prototype.Foo = function () {...}
    
  • var Foo = this.Foo;中不需要myObj行。

  • 你的魔法过于复杂。 <怎么样

    var otherTestFunc = new Function(testFunc.toString()
            .replace(/^[^{]+{/, '{var Foo=this.Foo;'));
    

    无需移除大括号。

  • testFunc不接受任何论据,但我想你知道。)

归结为

function myObj(testFunc) {
    this.testFunc = testFunc;
    var otherTestFunc = new Function(testFunc.toString()
            .replace(/^[^{]+{/, '{var Foo=this.Foo;'));
    otherTestFunc.apply(this);
}

myObj.prototype.Foo = function Foo(test) {
    this.test = test;

    this.saySomething = function(text) {
        alert(text);
    };
};

答案 1 :(得分:0)

自从我在asp.net验证码(!)中看到它以来,我一直被这种方法困扰。任意函数都不安全:

var f = (function () {
   var closure = 1
   return function (argument) {
      alert(argument)
      alert(closure)
   }
})()

var f2 = new Function(f.toString().replace(/^function.*?{([\s\S]*)}$/, 'alert(1);$1'))
f2(1) // :(

虽然可以保存参数。