underscore template first examples debounce javascript functional-programming underscore.js this

javascript - template - underscore js examples



¿Qué es el contexto en_.each(list, iterator,[context])? (5)

Soy nuevo en underscore.js. ¿Cuál es el propósito de [context] en _.each() ? ¿Cómo debe usarse?


Uso simple de _ cada uno

_.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>

Aquí hay un ejemplo simple que podría usar _.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();

Salida:

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

En lugar de llamar a addItem varias veces , puede usar el guión bajo de esta manera:

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

que es idéntico a invocar addItem tres veces de forma secuencial con estos elementos. Básicamente itera su matriz y para cada elemento llama a su función de devolución de llamada anónima que llama a x.addItem(item) . La función de devolución de llamada anónima es similar a la función de miembro addItem (por ejemplo, toma un elemento) y es algo sin sentido. Entonces, en lugar de pasar por una función anónima, es mejor que cada _.each evite esta indirección y llame a addItem directamente:

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

pero esto no funcionará, ya que dentro de la función de miembro addItem la canasta this no se referirá a su canasta x que usted creó. Es por eso que tiene una opción para pasar su cesta x para ser utilizada como [context] :

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

Ejemplo completo que utiliza _each y el contexto:

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>

En resumen, si la función de devolución de llamada que pasas a _.each de alguna manera usa this entonces necesitas especificar a qué se debe hacer referencia dentro de tu función de devolución de llamada. Puede parecer que x es redundante en mi ejemplo, pero x.addItem es solo una función y podría no estar relacionado con x basket o cualquier otro objeto, por ejemplo :

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>

En otras palabras, vincula algún valor a this dentro de su devolución de llamada, o bien puede usar bind directamente como este:

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

¿Cómo esta característica puede ser útil con algunos métodos de subrayado diferentes?

En general, si algún método underscorejs toma una función de devolución de llamada y si desea que se llame a una devolución de llamada en alguna función miembro de algún objeto (por ejemplo, una función que usa this ), entonces puede vincular esa función a algún objeto o pasar ese objeto como [context] y esa es la intención principal. Y en la parte superior de la documentación de underscorejs, eso es exactamente lo que dicen: el iteratee está vinculado al objeto de contexto, si se pasa uno


Como se explica en otras respuestas, el context es el contexto que se utilizará dentro de la devolución de llamada pasada a each .

Explicaré esto con la ayuda del código fuente de los métodos relevantes del código fuente de guión bajo

La definición de _.each o _.forEach es la siguiente:

_.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; };

La segunda declaración es importante notar aquí

iteratee = optimizeCb(iteratee, context);

Aquí, el context se pasa a otro método optimizeCb y la función devuelta se asigna a iteratee que se llama más tarde.

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); }; };

Como se puede ver en la definición del método anterior de optimizeCb , si no se pasa el context , func se devuelve tal como está. Si se pasa el context , se llama a la función de devolución de llamada como

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

func se llama con call() que se utiliza para invocar un método estableciendo this contexto. Entonces, cuando this se usa dentro de func , se referirá al 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>

Puede considerar el context como el último parámetro opcional de forEach en JavaScript.


El contexto le permite proporcionar argumentos en el tiempo de llamada, lo que permite una fácil personalización de las funciones auxiliares genéricas preconstruidas.

algunos ejemplos:

// 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);

Incluso a partir de los ejemplos limitados, puede ver cuán poderoso puede ser un "argumento extra" para crear código reutilizable. En lugar de hacer una función de devolución de llamada diferente para cada situación, generalmente puede adaptar un ayudante de bajo nivel. El objetivo es tener su lógica personalizada agrupando un verbo y dos sustantivos, con un mínimo estándar.

Es cierto que las funciones de flecha han eliminado muchas de las ventajas del "código de golf" de las funciones genéricas puras, pero las ventajas semánticas y de consistencia permanecen.

Siempre agrego "use strict" a los ayudantes para proporcionar compatibilidad nativa [].map() al pasar primitivas. De lo contrario, se les coacciona en objetos, lo que normalmente funciona, pero es más rápido y más seguro ser específico del tipo.


El parámetro de contexto simplemente establece el valor de this en la función del iterador.

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);

Ejemplo de trabajo: http://jsfiddle.net/a6Rx4/

Utiliza el número de cada miembro de la matriz que se itera para obtener el elemento en ese índice de someOtherArray , que está representada por this ya que lo pasamos como el parámetro de contexto.

Si no configura el contexto, this se referirá al objeto window .


context es a donde se refiere this en su función de iterador. Por ejemplo:

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);