直接修改函数有多危险

How dangerous is modifying a function directly?

本文关键字:危险 函数 修改      更新时间:2023-09-26

为了解决对我来说范围限制的问题(如这里所回答的),我编写了一段代码,在匿名函数中插入一行,这样编写函数的人就不必自己动手了。这有点古怪(实际上,感觉很古怪),我真的不知道自己在做什么,所以我很感激有一个专业的眼光来发现我可能错过的任何错误,或者指出我没有意识到的任何危险。这是代码:

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");
});

上面的函数按预期计算,我不需要强制编写匿名函数的人使用this.Foo访问Foo。不过,这种方法让人感觉不太确定。我所做的事情可以接受吗?如果不能,有什么方法可以绕过它吗?

此外,我没有在最初的问题中包括这一点的唯一原因是,这似乎偏离了问题的最初背景。

您试图破坏语言。不要那样做。它不是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!
});

没人料到会有这样的恶作剧。


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

  • CCD_ 4是用每一个新对象初始化的。这没有必要。更好地使用

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

  • 你的魔术太复杂了。怎么样

    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);
    };
};

自从我在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) // :(

不过,可以保存参数。