3

私にとってスコープの制限であることが証明されていることを回避するために(ここで回答)、無名関数に行を挿入するコードを作成しました。これにより、関数を作成する人は誰でも自分でそれを行う必要がなくなります。それは少しハッキーです(実際には、かなりハッキーな感じがします)、そして私は本当に自分が何をしているのかわからないので、私が見逃したかもしれないエラーを見つけたり、危険を指摘したりするために専門家の目で感謝します気づいていません。コードは次のとおりです。

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 に答える