首页 > 解决方案 > 在创建 ._each 函数(underscore.js)时如何编写“上下文”变量

问题描述

我正在尝试从 underscore.js 重新创建 _.each() 函数,但是无法正确获取“上下文”变量。我理解它的含义,但似乎在试图实现它。我已经用注释标记了下面的代码区域。任何提示表示赞赏,谢谢!

_.each = function (collection, iteratee, context) {
  //-----context--------
  if (context) {
    if (Array.isArray(collection)) {
      for (let i = 0; i < collection.length; i++) {
        iteratee.call(context, collection[i], collection);
      }
    } else {
    for (const key in collection) {
      iteratee.call(context, collection[key], collection);
    }
  }
    return collection;
  }
  //-----end of context----
  //check if array or object
  if (Array.isArray(collection)) {
    for (let i = 0; i < collection.length; i++) {
      iteratee(collection[i], i, collection);
    }
  } else {
    for (const key in collection) {
      iteratee(collection[key], key, collection);
    }
  }
  return collection;
};

标签: javascriptunderscore.js

解决方案


你根本不需要if (context) {。从根本上说,无论是否提供上下文,您都需要进行相同的操作,因此您可以将代码留在此之外if并始终执行.call(context, /* other arguments */Function#call将始终执行该函数,第一个参数将是该this调用的值。如果undefined提供了值,那么这不是错误 - 在非严格模式下,值this将分配给全局对象,但在strict模式下,“this”关键字如何工作?

因此,如果没有提供上下文,那么您通常不需要做任何特别的事情。

const _ = {};

_.each = function (collection, iteratee, context) {
  //check if array or object
  if (Array.isArray(collection)) {
    for (let i = 0; i < collection.length; i++) {
      iteratee.call(context, collection[i], collection);;
    }
  } else {
    for (const key in collection) {
      iteratee.call(context, collection[key], collection);
    }
  }
  return collection;
};


const arr = [1, 2, 3];
const obj = {
  foo: "hello",
  bar: "world"
};

function print(value) {
  console.log(value);
}

console.log("--- basic foreach ---");

_.each(arr, print);
_.each(obj, print);

console.log("--- foreach with context ---");

function contextPrint(value) {
  console.log(this[value]);
}

_.each(arr, contextPrint, { 1: "one", 2: "two", 3: "three" });
_.each(obj, contextPrint, { hello: "this", world: "works" });

console.log("--- no context provided ---");

_.each(arr, contextPrint);
_.each(obj, contextPrint);

与下划线比较,行为是一样的:

const arr = [1, 2, 3];
const obj = {
  foo: "hello",
  bar: "world"
};

function print(value) {
  console.log(value);
}

console.log("--- basic foreach ---");

_.each(arr, print);
_.each(obj, print);

console.log("--- foreach with context ---");

function contextPrint(value) {
  console.log(this[value]);
}

_.each(arr, contextPrint, { 1: "one", 2: "two", 3: "three" });
_.each(obj, contextPrint, { hello: "this", world: "works" });

console.log("--- no context provided ---");

_.each(arr, contextPrint);
_.each(obj, contextPrint);
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.11.0/underscore-min.js" integrity="sha512-wBiNJt1JXeA/ra9F8K2jyO4Bnxr0dRPsy7JaMqSlxqTjUGHe1Z+Fm5HMjCWqkIYvp/oCbdJEivZ5pLvAtK0csQ==" crossorigin="anonymous"></script>


推荐阅读