jQuery闭包:如何从函数单击中获取值

时间:2013-06-14 14:04:54

标签: javascript jquery click closures

我不太了解JS闭包,我认为它可以解决我的问题。这是:

我有类似的东西:

$(document).ready(function () {
    $("#buttonConfirm").click(function () {
        popup_confirme();
    });
});
function popup_confirme() {
    var r = popup_modal();
}
function popup_modal() {
    var int_val = 0;
    $(".button").click(function () {
        int_val = ($(this).val() == 'yes' ? '1' : '0');
    });
    return int_val;
}

我想通过按钮单击事件返回我的int_val。我需要将'r'值设为0或1.我知道我应该使用闭包,但我不知道该怎么做。感谢您的专业知识!

3 个答案:

答案 0 :(得分:3)

由于与封闭无关的原因,你无法做到这一点,这是不可能的。

您的调用设置int_val的代码,您只是定义代码,并说“单击.buttons时,调用此代码”。代码将不会在您运行return int_val时执行,将在单击按钮时在将来的某个时间点执行。

这段代码无法在逻辑上起作用:

// First line run
var int_val = 0;

// Second line run
$(".button").click(function () {
    // This line runs in the future, or maybe never, if the button isn't clicked
    int_val = ($(this).val() == 'yes' ? '1' : '0');
});

// Third line run
return int_val;

如果要从异步函数中传回值,则应使用promises:

function popup_modal() {
    var dfd = $.Deferred();

    $(".button").click(function () {
        int_val = ($(this).val() == 'yes' ? '1' : '0');

        // Allow int_val to find its way back to the calling code's `done` handler
        dfd.resolve(int_val);
    });

    return dfd.promise()
}

调用代码将收到一个promise对象,它可以将回调添加到:

function popup_confirme() {
    var r;
    popup_modal().done(function (int_val) {
      r = int_val;
    }
}

除此之外,我不能直截了当地说出你在调用代码中int_val的意思。

答案 1 :(得分:1)

当内部函数引用在其外部定义的内容时,会发生闭包。举例说明:

function outer() {
    var foo = 1;
    element.click(function () {
        // this function creates a closure on foo.
        alert(foo);
    });
};

您似乎想要做的是,int_valpopup_modal可以访问popup_confirme变量。

根据你的例子,有许多方法可以做到这一点,但是这样简单的事情可以起作用:

(function () {

    var int_val = 0;

    var popup_modal = function () {
        int_val = $(this).val() === 'yes' ? 1 : 0;
    };

    var popup_confirme = function () {
        // your original code here doesn't really do anything
        alert(int_val);
    };

    $('.button').click(popup_modal);
    $('#buttonConfirm').click(popup_confirme);

}());

答案 2 :(得分:1)

从技术上讲,所有JavaScript函数都是闭包,因为它们是附加了作用域链的对象。 闭包只是函数对象和作用域(一组变量绑定)的组合。

范围实际上非常简单。 Javascript使用词法作用域,这意味着函数在定义它们时生效的变量作用域中执行。简单地说,外部函数不能从内部函数读取值,除非特别返回。内部函数可以读取外部函数中声明的所有值。

当大多数人谈论闭包时,他们实际上指的是将项目从内部嵌套函数返回到已定义闭包的外部函数的行为。

e.g

// I am the outer function.
function outer (){

var outerVariable = "I am available to inner functions.";

    // I am an inner function. I was declared in the scope of the outer 
    // function and as such all the variables declared in that scope are 
    // available to me.
    function inner (){

        // This will return => "I am available to inner functions." as we can 
        // read the outer declaration.
        var innerReadValue = outerVariable; 

        // This will be available only to the inner function as it is 
        // not returned.
        var privateVariable = "I am private";

        // This will be available to the outer function as we are returning it 
        // on the next line.
        var publicVariable = "I am available to outer functions";

        // Make publicVariable public. This is what most people refer to 
        // when talking about closures. 
        return publicVariable; 

    }

    // Read the inner functions publicVariable declaration.
    // Returns => "I am available to outer functions"
    var outerReadValue = inner();

}

在您的示例中,您尝试获取已声明但未在内部范围上返回的值。正如你现在应该理解的那样,这对外部函数是不可见的,因此无法工作。

这可以这样改写:

// This is called an Immediately Invoked Function Expression. IIFE, It 
// basically wraps your code in a function hiding all internal declarations
// from the global scope and then invokes it. You don't want to pollute the 
// global scope.
(function(){

    // Declare this outside so all functions can read it.
    var int_val = 0;

    // Declare this outside so all functions can read it.
    var popup_confirm = function(){
        // "int_val" is available here.
        return int_val;
    };

    // Although your function runs automatically, we delay binding until
    // the DOM is ready.
    $(document).ready(function(){

        $("#buttonConfirm").click(function(){
           // Provide feedback. "popup_confirm" is available here
           // since is declared in the outer scope.
           return popup_confirm();
         });

        $(".button").click(function(){
            // Set the value of int_val that has been declared in the outer 
            // scope.
            int_val = $(this).val() === "yes" ? 1 : 0;

        });    
    });

}());

希望这对你来说更加清晰。