为了解决对我来说范围限制的问题(如这里所回答的),我编写了一段代码,在匿名函数中插入一行,这样编写函数的人就不必自己动手了。这有点古怪(实际上,感觉很古怪),我真的不知道自己在做什么,所以我很感激有一个专业的眼光来发现我可能错过的任何错误,或者指出我没有意识到的任何危险。这是代码:
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.*?{([sS]*)}$/, 'alert(1);$1'))
f2(1) // :(
不过,可以保存参数。