How can one de-reference JavaScript variables when enclosing an outer scope

后端 未结 4 1603
隐瞒了意图╮
隐瞒了意图╮ 2020-12-16 22:07

Ok, here\'s a problem script.

var links = [ \'one\', \'two\', \'three\' ];

for( var i = 0; i < links.length; i++ ) {
    var a = document.createElement(          


        
相关标签:
4条回答
  • 2020-12-16 22:46

    I recommend Christophs way with one function since it uses less resources.

    Below is another way that stores the value on the function (that is possible because a function is an object) and users argument.callee to get a reference to the function inside the function. In this case it doesn't make much sense, but I show the technique since it can be useful in other ways:

    var links = [ 'one', 'two', 'three' ];
    
    for( var i = 0; i < links.length; i++ ) {
        var a = document.createElement( 'div' );
        a.innerHTML = links[i];
        a.onclick = function() { alert( arguments.callee.i ) }
        a.onclick.i = i;
        document.body.appendChild( a );
    }
    

    The technique is useful when your function needs to store persistent information between calls. Replace the part above with this:

    a.id="div"+i;
    a.onclick = function() {
        var me = arguments.callee;
        me.count=(me.count|0) + 1;
        alert( me.i );
    }
    

    and you can later retrieve how many times it was called:

    for( var i = 0; i < links.length; i++ ){
        alert(document.getElementById("div"+i).onclick.count);
    }
    

    It can also be used to cache information between calls.

    0 讨论(0)
  • 2020-12-16 22:49

    You need to use this little closure trick - create and execute a function that returns your event handler function.

    var links = [ 'one', 'two', 'three' ];
    
    for( var i = 0; i < links.length; i++ ) {
        var a = document.createElement( 'div' );
        a.innerHTML = links[i];
        a.onclick = (function(i) { return function() { alert( i ) } })(i);
        document.body.appendChild( a );
    }
    
    0 讨论(0)
  • 2020-12-16 22:49

    I'd stay with your own solution, but modify it in the following way:

    var links = [ 'one', 'two', 'three' ];
    
    function handler() {
        alert( this.i );
    }
    
    for( var i = 0; i < links.length; i++ ) {
        var a = document.createElement( 'div' );
        a.innerHTML = links[i];
        a.i = i; //set a property of the current element with the current value of i
        a.onclick = handler;
        document.body.appendChild( a );
    }
    

    This way, only one function object gets created - otherwise, the function literal will be evaluated on every iteration step!

    A solution via closure is even worse performance-wise than your original code.

    0 讨论(0)
  • 2020-12-16 22:51

    RoBorg's method is definitely the way to go, but I like a slightly different syntax. Both accomplish the same thing of creating a closure that preserves 'i', this syntax is just clearer to me and requires less modification of your existing code:

    var links = [ 'one', 'two', 'three' ];

    for( var i = 0; i < links.length; i++ ) (function(i) {
        var a = document.createElement( 'div' );
        a.innerHTML = links[i];
        a.onclick = function() { alert( i ) }
        document.body.appendChild( a );
    })(i);
    
    0 讨论(0)
提交回复
热议问题