Javascript closure?

后端 未结 2 1567
不知归路
不知归路 2020-12-11 11:35

Method # 1

function transform(ar) {
    var alStr = [];
    for(var i=0; i

        
相关标签:
2条回答
  • 2020-12-11 11:59

    Peter Olson is correct. However, the more modern (correct?) way of doing this is by using function.bind(obj, val). Introduced somewhat recently, function.bind allows you to pass variables by value and in certain contexts. Read more here.

    So, you could write something like this:

    function transform(ar) {
        var alStr = [];
        var O = function(x) { return x }
        for(var a in ar) {
            alStr.push(O.bind(null, ar[a]));
        }
        return alStr; 
    }
    
    var a = ["a", 24, 12345];
    var b = transform(a);
    console.log(a[2]);
    b[2]();
    

    This is a more correct paradigm due to the fact that initiating closures has very clear implications. Using bind, however, tends to be a functional approach to be used specifically when function calling (in particular contexts or with particular stipulations).

    Using a with block also has some downsides (there are plenty of questions about it).

    Bonus: If you wanted b to also represent subsequent changes to the a array, this solution solves that problem:

    function transform(ar) {
        var alStr = [];
        var O = function(x) { return ar[x] }
        for(var a in ar) {
            alStr.push(O.bind(null, a));
        }
        return alStr; 
    }
    
    var a = ["a", 24, 12345];
    var b = transform(a);
    console.log(a[2]);
    console.log(b[2]());
    console.log("*********");
    a[2] = "new value!";
    console.log(a[2]);
    console.log(b[2]());
    
    0 讨论(0)
  • 2020-12-11 12:02

    In Method #2 there are two problems:

    1. You are returning the key name, a, rather than the array value, ar[a]. That is, rather than return a; you want return ar[a];.

    2. The function will always refer to the last value looped through because it references the same scope object. To create a new scope object you will need a closure, a with block, or a bound function.

    With a closure:

    for(var a in ar) { 
      var O = (function(val) { 
        return function() { 
          return val; 
         }
      })(ar[a]);
      alStr.push(O); 
    }
    

    With a with block:

    for(var a in ar) { 
      with({val: ar[a]}) {
        alStr.push(function() { 
          return val; 
         });
      }
    } 
    

    With a bound function:

    for(var a in ar) { 
      var O = function(x) { return x; };
      alStr.push(O.bind(null, arr[a]));
    } 
    
    0 讨论(0)
提交回复
热议问题