Javascript _.each(list, iterator, [context]) 中的上下文是什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4946456/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 14:55:03  来源:igfitidea点击:

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

javascriptfunctional-programmingunderscore.jsthis

提问by ram

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

我是 underscore.js 的新手。[context]in的目的是_.each()什么?应该如何使用?

回答by user113716

The context parameter just sets the value of thisin the iterator function.

上下文参数只是设置this迭代器函数中的值。

var someOtherArray = ["name","patrick","d","w"];

_.each([1, 2, 3], function(num) { 
    // In here, "this" refers to the same Array as "someOtherArray"

    alert( this[num] ); // num is the value from the array being iterated
                        //    so this[num] gets the item at the "num" index of
                        //    someOtherArray.
}, someOtherArray);

Working Example:http://jsfiddle.net/a6Rx4/

工作示例:http : //jsfiddle.net/a6Rx4/

It uses the number from each member of the Array being iterated to get the item at that index of someOtherArray, which is represented by thissince we passed it as the context parameter.

它使用来自正在迭代的 Array 的每个成员的数字来获取 的索引处的项目,由于我们将其作为上下文参数传递,因此someOtherArray由 表示this

If you do not set the context, then thiswill refer to the windowobject.

如果不设置上下文,this则将引用该window对象。

回答by Harmen

contextis where thisrefers to in your iterator function. For example:

contextthis在您的迭代器函数中引用的地方。例如:

var person = {};
person.friends = {
  name1: true,
  name2: false,
  name3: true,
  name4: true
};

_.each(['name4', 'name2'], function(name){
  // this refers to the friends property of the person object
  alert(this[name]);
}, person.friends);

回答by dandavis

The context lets you provide arguments at call-time, allowing easy customization of generic pre-built helper functions.

上下文允许您在调用时提供参数,允许轻松定制通用的预构建帮助函数。

some examples:

一些例子:

// stock footage:
function addTo(x){ "use strict"; return x + this; }
function pluck(x){ "use strict"; return x[this]; }
function lt(x){ "use strict"; return x < this; }

// production:
var r = [1,2,3,4,5,6,7,8,9];
var words = "a man a plan a canal panama".split(" ");

// filtering numbers:
_.filter(r, lt, 5); // elements less than 5
_.filter(r, lt, 3); // elements less than 3

// add 100 to the elements:
_.map(r, addTo, 100);

// encode eggy peggy:
_.map(words, addTo, "egg").join(" ");

// get length of words:
_.map(words, pluck, "length"); 

// find words starting with "e" or sooner:
_.filter(words, lt, "e"); 

// find all words with 3 or more chars:
_.filter(words, pluck, 2); 

Even from the limited examples, you can see how powerful an "extra argument" can be for creating re-usable code. Instead of making a different callback function for each situation, you can usually adapt a low-level helper. The goal is to have your custom logic bundling a verb and two nouns, with minimal boilerplate.

即使从有限的示例中,您也可以看到“额外参数”对于创建可重用代码的强大功能。您通常可以调整低级助手,而不是为每种情况制作不同的回调函数。目标是让您的自定义逻辑以最少的样板文件捆绑一个动词和两个名词。

Admittedly, arrow functions have eliminated a lot of the "code golf" advantages of generic pure functions, but the semantic and consistency advantages remain.

诚然,箭头函数消除了泛型纯函数的很多“代码高尔夫”优势,但语义和一致性优势仍然存在。

I always add "use strict"to helpers to provide native [].map()compatibility when passing primitives. Otherwise, they are coerced into objects, which usually still works, but it's faster and safer to be type-specific.

在传递原语时,我总是添加"use strict"助手以提供本机[].map()兼容性。否则,它们将被强制转换为对象,这通常仍然有效,但特定于类型更快更安全。

回答by Pavel P

Simple use of _.each

_.each 的简单使用

_.each(['Hello', 'World!'], function(word){
    console.log(word);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>

Here's simple examplethat could use _.each:

这是可以使用的简单示例_.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 addItemmultiple times you could use underscorethis way:

您可以这样使用下划线,而不是addItem多次调用:

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

which is identical to calling addItemthree 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 addItemmember function (e.g. it takes an item) and is kind of pointless. So, instead of going through anonymous function it's better that _.eachavoids this indirection and calls addItemdirectly:

这与addItem使用这些项目按顺序调用3 次相同。基本上它会迭代您的数组,并为每个项目调用您的匿名回调函数,该函数调用x.addItem(item). 匿名回调函数类似于addItem成员函数(例如,它需要一个项目)并且是毫无意义的。因此,与其通过匿名函数,不如_.each避免这种间接调用并addItem直接调用:

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

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

但这行不通,因为在 bag 的addItem成员函数this内不会引用x您创建的篮子。这就是为什么您可以选择传递您的篮子x以用作[context]

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

Full example that uses _.each and context:

使用 _.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();
_.each(['banana', 'apple', 'kiwi'], x.addItem, x);
x.show();
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>

In short, if callback function that you pass to _.eachin any way uses thisthen you need to specify what thisshould be referring to inside your callback function. It may seem like xis redundant in my example, but x.addItemis just a function and could be totally unrelated to xor basketor any other object, for example:

简而言之,如果您以_.each任何方式传递给回调函数使用,this那么您需要this在回调函数中指定应该引用的内容。x在我的示例中,它似乎是多余的,但x.addItem它只是一个函数,可能与xbasket或任何其他对象完全无关,例如

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();
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>

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

换句话说,您将一些值绑定到this回调内部,或者您也可以像这样直接使用bind

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

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

此功能如何与一些不同的下划线方法一起使用?

In general, if some underscorejsmethod 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

通常,如果某个underscorejs方法采用回调函数,并且您希望在某个对象的某个成员函数(例如,使用 的函数this)上调用该回调,那么您可以将该函数绑定到某个对象或将该对象作为[context]参数传递,那就是主要意图。在 underscorejs 文档的顶部,这正是他们所说的:迭代对象绑定到上下文对象,如果传递了一个

回答by Tushar

As explained in other answers, contextis the thiscontext to be used inside callback passed to each.

正如在其他答案中所解释的,contextthis在回调中使用的上下文传递给each.

I'll explain this with the help of source code of relevant methods from underscore source code

我将在下划线源代码中相关方法的源代码的帮助下解释这一点

The definition of _.eachor _.forEachis as follows:

_.each或的定义_.forEach如下:

_.each = _.forEach = function(obj, iteratee, context) {
  iteratee = optimizeCb(iteratee, context);

  var i, length;
  if (isArrayLike(obj)) {
    for (i = 0, length = obj.length; i < length; i++) {
      iteratee(obj[i], i, obj);
    }
  } else {
    var keys = _.keys(obj);
    for (i = 0, length = keys.length; i < length; i++) {
      iteratee(obj[keys[i]], keys[i], obj);
    }
  }
  return obj;
};

Second statement is important to note here

第二个声明很重要,请注意这里

iteratee = optimizeCb(iteratee, context);

Here, contextis passed to another method optimizeCband the returned function from it is then assigned to iterateewhich is called later.

在这里,context传递给另一个方法,optimizeCb然后将返回的函数分配给iteratee稍后调用的函数。

var optimizeCb = function(func, context, argCount) {
  if (context === void 0) return func;
  switch (argCount == null ? 3 : argCount) {
    case 1:
      return function(value) {
        return func.call(context, value);
      };
    case 2:
      return function(value, other) {
        return func.call(context, value, other);
      };
    case 3:
      return function(value, index, collection) {
        return func.call(context, value, index, collection);
      };
    case 4:
      return function(accumulator, value, index, collection) {
        return func.call(context, accumulator, value, index, collection);
      };
  }
  return function() {
    return func.apply(context, arguments);
  };
};

As can be seen from the above method definition of optimizeCb, if contextis not passed then funcis returned as it is. If contextis passed, callback function is called as

从上面的方法定义可以看出optimizeCb,如果context没有通过,则func原样返回。如果context传递,回调函数被调用为

func.call(context, other_parameters);
          ^^^^^^^

funcis called with call()which is used to invoke a method by setting thiscontext of it. So, when thisis used inside func, it'll refer to context.

func被调用 with call()which 用于通过设置this它的上下文来调用方法。所以,当this在 inside 中使用时func,它会引用context.

// Without `context`
_.each([1], function() {
  console.log(this instanceof Window);
});


// With `context` as `arr`
var arr = [1, 2, 3];
_.each([1], function() {
  console.log(this);
}, arr);
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>

You can consider contextas the last optional parameter to forEachin JavaScript.

您可以将contextto视为forEachJavaScript 中的最后一个可选参数。