3

为了解决已被证明对我来说是范围限制的问题(如在此处回答),我编写了一段代码,该代码在匿名函数中插入了一行,这样编写函数的人就不必自己动手了。这有点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. 不过,这种方法感觉很可疑。我正在做的事情是否可以接受,如果没有,有什么方法可以规避它吗?

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

4

2 回答 2

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);
    };
};
于 2012-07-09T06:01:20.870 回答
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) // :(

不过可以保存参数。

于 2012-07-09T05:16:14.780 回答