简体   繁体   English

为什么我必须在闭包中声明一个函数,访问闭包中定义的变量?

[英]Why do I have to declare a function within a closure access variables defined in the closure?

Why do I have to declare a function within a closure to be able to access the variables in the closure? 为什么我必须在闭包中声明一个函数才能访问闭包中的变量? I expected that I would be able to define the function outside of the closure, but close around it, providing the variables it needed, but the variables are not available unless the function is actually defined within the closure. 我希望我能够在闭包之外定义函数,但可以在闭包周围进行定义,并提供所需的变量,但是除非函数实际上是在闭包内定义的,否则变量不可用。

http://jsfiddle.net/c5oba93a/1/ http://jsfiddle.net/c5oba93a/1/

//reusable function defined outside of closure, I want to swap out myMethod within this function.
var reusableFunction = function () {
    //common code
    try {
        console.log(myVar);
        myMethod.call(this);
    } catch (e) {
        console.log(e);
    }
    //common code
};


var functOneForClosure = function () {
    console.log('functOne');
};
var functTwoForClosure = function () {
    console.log('functTwo');
};

//myMethod and myVar are undefined in reusableFunction
(function () {
    var myMethod = functOneForClosure;
    var myVar = 'variable in closure with functOne';
    return reusableFunction;
})()();
(function (myMethodIn) {
    var myMethod = myMethodIn;
    var myVar = 'variable in closure with functTwo';
    return reusableFunction;
})(functOneForClosure)();

//if the function is defined within the closure it behaves as expected.
var getReusableVersion =(function (myMethod) {
    var myVar = 'defining function within closure makes the difference';
    return function () {
        //common code
        try {
            console.log(myVar);
            myMethod.call(this);
        } catch (e) {
            console.log(e);
        }
        //common code
    };
});

getReusableVersion(functOneForClosure)();

@pherris According to your beforelast comment: That won't help. @pherris根据您之前的评论:这无济于事。 The this inside the IIFEs refers to the window object and now you spam it with additional properties. this的IIFEs内指的是window对象,现在你有附加属性的垃圾邮件了。 But myVar and myMethod inside reusableFunction still are undefined, you have to use this.myVar and this.myMethod instead. 但是reusableFunction myVar and myMethod仍未定义,您必须改用this.myVarthis.myMethod Better than spamming the window is to pass the vars as arguments: 比向窗口发送垃圾更好的是将vars作为参数传递:

var reusableFunction = function (myVar, myMethod) {
    // no try/catch needed anymore
    console.log(myVar);
    if (typeof myMethod == 'function') myMethod.call(this);
    else console.log(myMethod);
};

Now there are two ways to invoke it with your IIFE. 现在,有两种方法可以用IIFE调用它。

The first returns the function from IIFE with arguments bound to it and executes it afterwards: 第一个从IIFE返回带有绑定参数的函数,然后执行该函数:

(function () {
    var myMethod = functOneForClosure;
    var myVar = 'variable in closure with functOne';

    // first argument of .bind() appears in the function as 'this',
    // the others appear as fixed arguments of the function
    return reusableFunction.bind(window, myVar, myMethod);
})()();

The second way invokes it inside the IIFE, so the invocation afterwards is removed: 第二种方法在IIFE中调用它,因此之后的调用被删除:

(function () {
    var myMethod = functOneForClosure;
    var myVar = 'variable in closure with functOne';

    return reusableFunction(myVar, myMethod);

    // of course its possible to call on 'this', but that doesn't change anything:
    /* return reusableFunction.call(this, myVar, myMethod); */

})();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM