話很少說,直接看代碼javascript
const arr = [1, 2, 3, 4, 5, 6];
複製代碼
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循環,有的小夥伴可能會說,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
,那麼下次當咱們再聽到forEach
和map
的區別是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的說明:
map與forEach相似,惟一的區別就是
map
方法會給原數組中的每一個元素都按順序調用一次callback
函數。callback
每次執行後的返回值(包括undefined
)組合起來造成一個新數組。
這裏再貼一下MDN對map的使用說明
由於map生成一個新數組,當你不打算使用返回的新數組卻使用map是違背設計初衷的,請用forEach或者for-of替代。你不應使用map:
A)你不打算使用返回的新數組,
B)你沒有從回調函數中返回值。
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
}
複製代碼
這裏能夠看到,key
爲1
的元素比key
爲name
的元素先打印了出來,
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
用來遍歷數組時,遍歷的結果爲當前元素索引值的字符串形式
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
遍歷普通對象的兩種方法:
for (const [key, value] of Object.entries(obj)) {
console.log(`${key}: ${value}`);
}
複製代碼
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,
};
},
};
};
複製代碼