What is context in _.each(list, iterator, [context])?

前端 未结 5 618
生来不讨喜
生来不讨喜 2020-11-29 16:42

I am new to underscore.js. What is the purpose of [context] in _.each()? How should it be used?

5条回答
  •  鱼传尺愫
    2020-11-29 17:01

    Simple use of _.each

    _.each(['Hello', 'World!'], function(word){
        console.log(word);
    });

    Here's simple example that could use _.each:

    function basket() {
        this.items = [];
        this.addItem = function(item) {
            this.items.push(item);
        };
        this.show = function() {
            console.log('items: ', this.items);
        }
    }
    
    var x = new basket();
    x.addItem('banana');
    x.addItem('apple');
    x.addItem('kiwi');
    x.show();

    Output:

    items:  [ 'banana', 'apple', 'kiwi' ]
    

    Instead of calling addItem multiple times you could use underscore this way:

    _.each(['banana', 'apple', 'kiwi'], function(item) { x.addItem(item); });
    

    which is identical to calling addItem three times sequentially with these items. Basically it iterates your array and for each item calls your anonymous callback function that calls x.addItem(item). The anonymous callback function is similar to addItem member function (e.g. it takes an item) and is kind of pointless. So, instead of going through anonymous function it's better that _.each avoids this indirection and calls addItem directly:

    _.each(['banana', 'apple', 'kiwi'], x.addItem);
    

    but this won't work, as inside basket's addItem member function this won't refer to your x basket that you created. That's why you have an option to pass your basket x to be used as [context]:

    _.each(['banana', 'apple', 'kiwi'], x.addItem, x);
    

    Full example that uses _.each and context:

    function basket() {
        this.items = [];
        this.addItem = function(item) {
            this.items.push(item);
        };
        this.show = function() {
            console.log('items: ', this.items);
        }
    }
    var x = new basket();
    _.each(['banana', 'apple', 'kiwi'], x.addItem, x);
    x.show();

    In short, if callback function that you pass to _.each in any way uses this then you need to specify what this should be referring to inside your callback function. It may seem like x is redundant in my example, but x.addItem is just a function and could be totally unrelated to x or basket or any other object, for example:

    function basket() {
        this.items = [];
        this.show = function() {
            console.log('items: ', this.items);
        }
    }
    function addItem(item) {
        this.items.push(item);
    };
    
    var x = new basket();
    _.each(['banana', 'apple', 'kiwi'], addItem, x);
    x.show();

    In other words, you bind some value to this inside your callback, or you may as well use bind directly like this:

    _.each(['banana', 'apple', 'kiwi'], addItem.bind(x));
    

    how this feature can be useful with some different underscore methods?

    In general, if some underscorejs method takes a callback function and if you want that callback be called on some member function of some object (e.g. a function that uses this) then you may bind that function to some object or pass that object as the [context] parameter and that's the primary intention. And at the top of underscorejs documentation, that's exactly what they state: The iteratee is bound to the context object, if one is passed

提交回复
热议问题