摘要:對于每個枚舉的屬性,部分都會被執行。被迭代枚舉的對象。三對數組的每個元素執行一次提供的函數。沒有辦法終止會跳出循環,除了拋出一個異常。當到達包含值的項時,整個數組的第一個項被移除了,這導致所有剩下的項前移了一個位置。
前言
初學JavaScript的時候,知道有各種for的時候,懵懵懂懂,也許是因為沒有系統學習的緣故?,F在我們把各種for都挨個辨明。
一、for創建一個循環,包含三個可選表達式。三個可選表達式在圓括號中,由分號分隔。后跟一個循環中執行的語句或塊語句。語法
initializationfor ([initialization]; [condition]; [final-expression]) statement
初始化語句??蓪懕磉_式、賦值語句、變量聲明。
condition循環條件表達式。如果表達式結果為true,statement會被執行。如果表達式結果為false,那么執行流程跳到for語句結構后面的第一條語句。不寫表達式,就是永遠為true。
final-expression每次循環的最后都要執行的表達式。執行時機是在下一次condition的計算之前。
statement只要condition的結果為true就會被執行的語句。多條語句使用塊語句({...})來包含。沒有語句執行,使用空語句(;)。
示例我想輸出五個數字。
for (let i = 0; i < 5; i++) console.log(i); /* 0 1 2 3 4 */
另一種寫法輸出五個數字。可選的三個表達式,多行語句,需要使用{}包含起來。
for (let i = 0; ; i++) { if (i >= 5) break; console.log(i); } /* 0 1 2 3 4 */
注意,如果不寫條件表達式,就要確保循環體內能夠跳出,防止死循環。break可以跳出循環。
二、for...in以任意順序遍歷一個對象的可枚舉屬性。對于每個枚舉的屬性,...部分都會被執行。語法
variablefor (variable in object) {...}
每次迭代的時候,將對象的屬性名分配給變量。
object被迭代枚舉的對象。
示例我想輸出對象里所有的屬性和值。
let o = { a: 1, b: 2, c: 3 }; for (const v in o) { console.log(`o.${v} = ${o[v]}`); } /* o.a = 1 o.b = 2 o.c = 3 */
可以看見for...in把所有的可枚舉屬性都枚舉了出來,v的類型是String,所以訪問當前遍歷到的屬性值使用了關聯數組o[v]的方式。
for...in在遍歷的時候,是以任意順序遍歷的。
let o = []; o[0] = 1; o["one"] = 2; o[2] = 3; for (const v in o) { console.log(`o[${v}] = ${o[v]}`); } /* o[0] = 1 o[2] = 3 o[one] = 2 */
因此當遇到對迭代訪問順序很重要的數組時,最好用整數索引。
我想累加數組所有的成員。
Array.prototype.age = 97; let o = [1,2]; let sum = 0; for (const v in o) { sum += o[v]; console.log(`o[${v}] = ${o[v]}`); } console.log(`sum = ${sum}`); /* o[0] = 1 o[1] = 2 o[age] = 97 sum = 100 */
很顯然這里不符合我們的預期,因為for...in循環語句將返回所有可枚舉屬性,包括非整數類型的名稱和繼承的那些。還會獲取到原型鏈上的可枚舉屬性。
我只想累加自身所有屬性。
Array.prototype.age = 97; let arr = [1, 2]; let sum = 0; for (const v in arr) { if (arr.hasOwnProperty(v)) { sum += arr[v]; } console.log(`arr[${v}] = ${arr[v]}`); } console.log(`sum = ${sum}`); /* o[0] = 1 o[1] = 2 o[age] = 97 sum = 3 */
如果你只要考慮對象本身的屬性,而不是它的原型,那么使用Object.getOwnPropertyNames()或執行Object.prototype.hasOwnProperty()來確定某屬性是否是對象本身的屬性(也能使用propertyIsEnumerable)。
三、Array.prototype.forEach()對數組的每個元素執行一次提供的函數。返回值為undefined。語法
callbackArray.forEach(callback[, thisArg])
為數組每個元素執行的函數,這個函數接受三個參數。
currentValue數組中正在處理的當前元素值。
index數組中正在處理的當前元素的索引。
arrayforEach()方法正在操作的數組。
thisArg可選參數。當執行回調 函數時用作this的值(參考對象)。
示例我想輸出所有元素。
function logArrayElements(element, index, array) { console.log(`a[${index}] = ${element}`); } [4, 2, 3].forEach(logArrayElements); /* a[0] = 4 a[1] = 2 a[2] = 3 */
forEcah()會跳過已經刪除或者為初始化的項(但不包括那些值為undefined的項,例如在稀疏數組上)。
function logArrayElements(element, index, array) { console.log(`a[${index}] = ${element}`); } [4, , 3].forEach(logArrayElements); [1, undefined, 3].forEach(logArrayElements); /* a[0] = 4 a[2] = 3 a[0] = 1 a[1] = undefined a[2] = 3 */
沒有辦法終止會跳出forEcah()循環,除了拋出一個異常。
function logArrayElements(element, index, array) { console.log(`a[${index}] = ${element}`); break; } [1, 2, 3].forEach(logArrayElements); /* Uncaught SyntaxError: Illegal break statement at Array.forEach () at :5:11 */
使用return也無法中止循環。
使用thisArg,舉個勉強的例子。通過自定義的add()方法,計算所添加數組的和sum和成員數count。
function Counter() { this.sum = 0; this.count = 0; } Counter.prototype.add = function(array) { array.forEach(function(element) { this.sum += element; ++this.count; }, this); }; let obj = new Counter(); obj.add([1, 3, 5, 7]); console.log(obj.count); // 4 === (1+1+1+1) console.log(obj.sum); // 16 === (1+3+5+7) /* 4 16 */
注意:如果使用箭頭函數表達式傳入函數參數,thisArg參數會被忽略,因為箭頭函數在詞法上綁定了this值。
如果數組在迭代時被修改了,則其他元素會被跳過。
let words = ["one", "two", "three", "four"]; words.forEach(function(word) { console.log(word); if (word === "two") { words.shift(); } }); /* one two four */
當到達包含值"two"的項時,整個數組的第一個項被移除了,這導致所有剩下的項前移了一個位置。因為元素"four"現在在數組更前的位置,"three"會被跳過。forEach()不會在迭代之前創建數組的副本。
四、for...offor...of語句在可以迭代的對象(Array、Map、Set、String、TypedArray、arguments對象等等)上創建一個迭代循環,調用自定義迭代鉤子,并為每個不同屬性的值執行語句。語法
variablefor (variable of iterable) { ... }
在每次迭代中,將不同屬性的值分配給變量。
iterable被迭代枚舉其屬性的對象。
示例 迭代Arraylet a = [10, 20, 30]; for (let v of a) { console.log(v); } /* 10 20 30 */迭代String
let s = "Tang"; for (let v of s) { console.log(v); } /* T a n g */迭代arguments
(function() { for (let v of arguments) { console.log(v); } } )(1, 2, 3); /* 1 2 3 */區別
無論是for...in還是for...of語句都是迭代一些東西。它們之間的主要區別在于它們的迭代方式。
for...in語句以原始插入順序迭代對象的可枚舉屬性。
for...of語句遍歷可迭代對象定義要迭代的數據。
以下示例顯示了與Array一起使用時,for...of循環和for...in循環之間的區別。
Object.prototype.objCustom = function() {}; Array.prototype.arrCustom = function() {}; let iterable = [3, 5, 7]; iterable.foo = "hello"; for (let i in iterable) { console.log(i); } /* 0 1 2 foo arrCustom objCustom */ for (let i in iterable) { if (iterable.hasOwnProperty(i)) { console.log(i); } } /* 0 1 2 foo */ for (let i of iterable) { console.log(i); } /* 3 5 7 */
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/108069.html
摘要:四則運算編譯器,雖然說功能很簡單,只能編譯四則運算表達式。再復雜的編譯器再簡單的編譯器,功能上是差不多的,只是復雜的編譯器實現上會更困難。每一章都是理論與實踐結合的經典,從計算機硬件知識到軟件體系,再到編譯原理和操作系統。 四則運算編譯器,雖然說功能很簡單,只能編譯四則運算表達式。但是編譯原理前端部分幾乎都有涉及,詞法分析,語法分析,還有代碼生成。 再復雜的編譯器、再簡單的編譯器,功能...
摘要:證書證書被稱為擴展驗證型證書,是因為申請證書不僅需要驗證域名所有權,按規定提交企業真實身份驗證材料,還要求提供更加詳細的企業信息如具體營業地址等信息,并提供具有法律效力的證明文件如律師函等。以最大限度降低用戶訪問不安全網站的風險。 什么是 HTTPS? HTTPS(超文本傳輸安全協議)是一種互聯網通信安全協議,它確保在用戶的計算機與網站終端服務器之間傳遞的數據的完整性和機密性。所以,為...
摘要:一個開放高效敏捷的物聯網應用開發平臺,就此誕生,也被稱為全球最好用的物聯網操作系統。區塊鏈技術再加碼,物聯網生態持續精進隨著區塊鏈技術的出現及持續升溫,如今區塊鏈已經成為大眾廣泛關注的一個話題。 showImg(https://segmentfault.com/img/bV8bKH?w=2121&h=1414); 世界正在發生改變。 在無錫,中國第一個物聯網之城——鴻山小鎮已經悄然誕生...
摘要:而且在這一版本里,微軟沒有提供圖形界面到的轉換。之父,在加入微軟之前是搞的。在發明了這后,直接就晉升為微軟的并且主導了的架構設計跑遠了,回來。通過遠程在客戶端機器上運行以下命令即可是客戶端機器的文件位置。 摘要: 相信有部分同學們會有這樣的體驗,在公有云上購買了Windows Server Version 1709數據中心版的虛擬機,通過遠程連接進去之后,里面全是黑乎乎的一個命令行,其...
摘要:這也解答了我曾經的一個疑問同樣的道理,在調用屬性的瞬間,也是使用先來實例化一個對象,所以那一瞬間他們的構造函數以及原型對象是相同的,但也僅僅是那一瞬間。 經常在國內的各大網站博客上看到一句話,叫做JS中萬物皆對象,那是否真是如此? 那么,我們先來捋一捋JS中的數據類型,JS中的數據類型有下面幾種 Undefined Null Boolean Number String Symbol ...
閱讀 1078·2021-11-25 09:43
閱讀 699·2021-11-22 14:45
閱讀 3825·2021-09-30 09:48
閱讀 1065·2021-08-31 09:41
閱讀 1974·2019-08-30 13:52
閱讀 1979·2019-08-30 11:24
閱讀 1347·2019-08-30 11:07
閱讀 956·2019-08-29 12:15