【總結】js結束循環(for,forEach,map,for in。。。)

話很少說,直接看代碼javascript

const arr = [1, 2, 3, 4, 5, 6];
複製代碼

for

  • break結束循環
for (let i = 0; i < arr.length; i++) {
  if (i === 3) {
    break;
  }
  console.log(arr[i]);  // 1 2 3
}
複製代碼
  • continue跳過當前循環
for (let i = 0; i < arr.length; i++) {
  if (i === 3) {
    continue;
  }
  console.log(arr[i]);  // 1 2 3 5 6
}
複製代碼

forEach

並無優雅的方法結束forEach循環,有的小夥伴可能會說,return不行咩。java

arr.forEach((item) => {
  if (item === 3) {
    // 此處return和return true,return false都同樣
    return;
  }
  console.log(item);  // 1 2 4 5 6
});
複製代碼

這裏我也有一樣的疑惑,forEach實質上是Array.prototype上的一個方法,既然是方法,那爲何retrun不能直接終止呢?🤔數組

帶着這樣的疑惑,在網上找了一下,實在找不到v8的源碼,借用mozilla的forEach源碼👀markdown

/* ES5 15.4.4.18. */
function ArrayForEach(callbackfn /*, thisArg*/) {
  var O = ToObject(this);
  var len = ToLength(O.length);
  if (arguments.length === 0)
    ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, "Array.prototype.forEach");
  if (!IsCallable(callbackfn))
    ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(0, callbackfn));
  var T = arguments.length > 1 ? arguments[1] : void 0;

  for (var k = 0; k < len; k++) {
    if (k in O) {
      callContentFunction(callbackfn, T, O[k], k, O);
    }
  }
  return void 0;
}
複製代碼

核心代碼咱們能夠看到原來是for循環對每一個元素都執行了一次fn,那這就不難理解爲何return終止不了forEach循環了。app

由於咱們傳入的方法,這裏爲if(item === 3) return,是在for循環內部執行的,return只結束了當item === 3所執行的fn,即return,可是for循環仍是會繼續執行。因此上面的代碼log的結果是1 2 4 5 6函數

tips: 這裏咱們也能夠看出來forEach的返回值是void 0,即undefined,那麼下次當咱們再聽到forEachmap的區別是forEach沒有返回值時,咱們就能夠很裝x的說:forEach也有返回值,只不過是undefined,沒有意義而已🌚oop

知道了怎麼回事,咱們本身擼一個forEachui

arr.forEach(callback(currentValue [, index [, array]])[, thisArg]) - MDNthis

Array.prototype.forEach = function (fn, thisArg) {
  if (typeof fn !== "function") {
    throw new TypeError(`${fn} is not a function`);
  }
  for (var i = 0; i < this.length; i++) {
    fn.apply(thisArg, [this[i], i, this]);
  }
};
複製代碼

那有的小夥伴可能要說了,我就要結束forEach循環,那固然也不是沒有辦法,拋出錯誤就好了spa

try {
  arr.forEach((item) => {
    if (item === 3) {
      throw new Error("exit foreach");
    }
    console.log(item);  // 1 2
  });
} catch (e) {}
複製代碼

這裏能夠看一下MDN上對forEach的說明: Array.prototype.forEach()

map

map與forEach相似,惟一的區別就是

map方法會給原數組中的每一個元素都按順序調用一次 callback函數。callback每次執行後的返回值(包括undefined)組合起來造成一個新數組。

這裏再貼一下MDN對map的使用說明

由於map生成一個新數組,當你不打算使用返回的新數組卻使用map是違背設計初衷的,請用forEach或者for-of替代。你不應使用map:

A)你不打算使用返回的新數組,
B)你沒有從回調函數中返回值。

Array.prototype.map()-MDN

for...in

break結束循環

const person = {
  name: "ming",
  age: 18,
  1: 1,
  job: "student",
};

for (const key in person) {
  if (key === "age") {
    break;
  }
  console.log(`${key}: ${person[key]}`);
  // 1: 1
  // name: ming
}
複製代碼

continue跳過當前循環

const person = {
  name: "ming",
  age: 18,
  1: 1,
  job: "student",
};

for (const key in person) {
  if (key === "age") {
    continue;
  }
  console.log(`${key}: ${person[key]}`);
  // 1: 1
  // name: ming
  // job: student
}
複製代碼

這裏能夠看到,key1的元素比keyname的元素先打印了出來,

for...in語句以任意順序遍歷一個對象的除Symbol之外的可枚舉屬性。

os: 原本for...in就是爲了遍歷對象的,然而對象原本就是無序的 🙄️

順手擼一個深拷貝

function deepClone(target) {
  if (typeof target !== "object" || target === null) return target;
  let result = Array.isArray(target) ? [] : {};
  for (const key in target) {
    if (target.hasOwnProperty(key)) {
      const element = target[key];
      if (typeof element === "object") {
        result[key] = deepClone(element);
      } else {
        result[key] = element;
      }
    }
  }
  return result;
}
複製代碼

注:當for...in用來遍歷數組時,遍歷的結果爲當前元素索引值的字符串形式

for...of

break結束循環

for (const val of arr) {
  if (val === 3) {
    break;
  }
  console.log(val); // 1 2
}
複製代碼

continue跳過當前循環

for (const val of arr) {
  if (val === 3) {
    continue;
  }
  console.log(val); // 1 2 4 5 6
}
複製代碼

咱們都知道for...of只能用來遍歷那些內置iterator(Array, Atring, ArrayLike, Set, Map...)或者實現了@@iterator方法的數據類型,而普通的Object並無內置iterator

這裏簡單說一下用for...of遍歷普通對象的兩種方法:

  1. 轉成array
for (const [key, value] of Object.entries(obj)) {
  console.log(`${key}: ${value}`);
}
複製代碼
  1. 實現iterator
person[Symbol.iterator] = function () {
  let nextIndex = 0;
  const arr = Object.entries(this);
  return {
    next: function () {
      return nextIndex < arr.length
        ? {
            value: arr[nextIndex++],
            done: false,
          }
        : {
            done: true,
          };
    },
  };
};
複製代碼
相關文章
相關標籤/搜索