5

うーん、タイトルだけではわかりにくい。ここに例があります。関数が自動的に「注入」される変数を参照するようにします。つまり、次のようになります。

function abc() {
   console.log(myVariable);
}

私は試してみました:

with({myVariable: "value"}) { abc() } 

ただし、abc が wi​​th ブロック内で宣言されていない限り、これは機能しません。つまり、次のようになります。

with({myVariable: "value"}) { 

    function abc() {
       console.log(myVariable);
    }

    abc();  // This will work

}

最後の部分は機能しますが、 with ステートメントを偽造することは可能ですか? または、開発者に with ステートメントで関数呼び出しを宣言させる必要がありますか?

基本的に私がやりたい呼び出しは次のとおりです。

doSomething({myVariable: "value"}, function() {
    console.log(myVariable);
});

もちろん、これを 1 つのパラメーター オブジェクトとして渡すことができることは承知していますが、それは私がやろうとしていることではありません。

doSomething({myVariable: "value"}, function(M) {
    console.log(M.myVariable);
});

さらに、私はeval の使用を避けようとしています:

with({myVariable: "value"}) { 

    eval(abc.toString())(); // Will also work

}

これは Javascript の eval を超えてまったくサポートされていませんか?

4

8 に答える 8

4

JavaScript は、探している構文を実現する簡単な方法を提供しません。変数をレキシカル環境に注入する唯一の方法は、eval(または非常に類似しFunctionたコンストラクター) を使用することです。この質問に対する回答のいくつかは、これを示唆しています。他のいくつかの回答は、回避策としてグローバル変数を使用することを提案しています。ただし、これらのソリューションにはそれぞれ独自の注意事項があります。

それ以外の唯一のオプションは、別の構文を使用することです。元の構文に最も近いのは、Aadit M Shah が提案したように、doSomething からコールバックにパラメーターを渡すことです。はい、あなたがそれをしたくないと言ったのは承知していますが、それはそれか醜いハックのどちらかです...


元の回答(質問を完全に理解していないときに書かれました)

多分あなたが探しているのはクロージャーですか?このようなもの:

var myVariable = "value";
function doSomething() {
    console.log(myVariable);
};
doSomething(); // logs "value"

それともこれ?

function createClosure(myVariable) {
    return function() {
        console.log(myVariable);
    };
}
var closure = createClosure("value");
closure(); // logs "value"

あるいは:

var closure = function(myVariable) {
    return function() {
        console.log(myVariable);
    };
}("value");
closure(); // logs "value"
于 2013-07-17T00:21:41.100 に答える
2

警告: 不快なコードが先にあります

function callWithContext(func, context, args) {
    var oldProperties = {};

    for(var n in context) {
        if(context.hasOwnProperty(n)) {
            var oldProperty = Object.getOwnPropertyDescriptor(self, n);
            oldProperties[n] = oldProperty;

            (function(n) {
                Object.defineProperty(self, n, {
                    get: function() {
                        if(arguments.callee.caller === func) {
                            return context[n];
                        }

                        if(!oldProperty) {
                            return;
                        }

                        if(oldProperty.get) {
                            return oldProperty.get.apply(this, arguments);
                        }

                        return oldProperty.value;
                    },
                    set: function(value) {
                        if(arguments.callee.caller === func) {
                            context[n] = value;
                        }

                        if(!oldProperty) {
                            return;
                        }

                        if(oldProperty.set) {
                            return oldProperty.get.apply(this, arguments);
                        } else if(!oldProperty.writable) {
                            var fakeObject = {};
                            Object.defineProperty(fakeObject, n, {value: null, writable: false});
                            fakeObject[n] = value; // Kind of stupid, but…
                            return;
                        }

                        oldProperty.value = value;
                    }
                });
            })(n);
        }
    }

    func.apply(this, args);

    for(var n in context) {
        if(context.hasOwnProperty(n)) {
            if(oldProperties[n]) {
                Object.defineProperty(self, n, oldProperties[n]);
            } else {
                delete self[n];
            }
        }
    }
}

ちなみに、これは吐き気がするほど恐ろしいです。使用しないでください。しかし、ええと、それは実際に機能します。

于 2013-07-17T00:35:00.477 に答える
0

goog.partialを見て、少し上にスクロールして、その機能の説明を確認します。

これがその実装です:

var b = goog.partial(alert, 'Hello world!');
b();//alerts "Hello world!"

この例では、パラメーター "Hello world!" を使用して関数 alert を渡します。ただし、複数のパラメーターを使用して独自の関数を渡すことができます。

これにより、常に特定のパラメーターで呼び出される関数を指す変数を作成できます。名前のない関数でパラメーターを使用するには、引数を使用できます。

function test(){
  console.log(arguments);//["hello","world"]
}

test("hello","world");
于 2013-07-17T07:35:54.060 に答える