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

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

本文关键字:闭包 函数 一个 访问 变量 定义 声明 为什么      更新时间:2023-09-26

为什么我必须在闭包中声明一个函数才能访问闭包中的变量?我希望我能够在闭包之外定义函数,但在闭包周围闭合,提供所需的变量,但除非函数实际上在闭包中定义,否则这些变量是不可用的。

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根据你的beforelast评论:那没用。IIFE中的this引用了window对象,现在您可以使用其他属性对其进行垃圾邮件处理。但是reusableFunction中的myVar and myMethod仍然未定义,您必须使用this.myVarthis.myMethod。比垃圾邮件窗口更好的是将变量作为参数传递:

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

现在有两种方法可以用IIFE调用它。

第一个从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);
})()();

第二种方法在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); */
})();