国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

溫故js系列(8)-詳解代碼中的流程控制

blastz / 2088人閱讀

摘要:甚至包括原型鏈上的所有可枚舉的屬性顯然,我們習慣的數組遍歷的結果是只有這樣的結果的。當代碼運行到語句時,執行上下文的作用域鏈臨時被改變了。

前端學習:教程&開發模塊化/規范化/工程化/優化&工具/調試&值得關注的博客/Git&面試-前端資源匯總

歡迎提issues斧正:流程控制

JavaScript-流程控制

JavaScript是單線程的,一個語句一個語句的執行。語句是執行過程中的流程、限定與約定,形式上可以是單行語句,或者由一對大括號"{}"括起來的復合語句,復合語句整體可以作為一個單行語句處理。那么,代碼中,流程控制就顯得格外重要了。JavaScript也規定了一些語句和一些關鍵字用于流程控制。

if語句 if (條件表達式) {語句}
if(2 > 1){
    console.log("xzavier win");
}

javascript會判斷括號里的條件表達式的值。如果值為truthy類型的值,也就是真,則執行后面的一條語句,否則不執行。這個語句無可厚非,使用率也是極高的,有時候會使用短連接來替代:

2 > 1 && console.log("xzavier win");

想了解此運算符以及更多運算符參考: 運算符詳解

關于判斷參見本系列文章:代碼中的那些判斷

if (條件表達式) {語句;} else {語句;}

if為真值(Boolean轉換),則執行if里的代碼,否則執行else里的代碼。

if (2 > 1) {
    console.log("xzavier win"); 
} else {
    console.log("xzavier fail"); 
}

這個語句的使用也無需多說,有時候會使用三目運算符代替:

2 > 3 ? console.log("xzavier win") : console.log("xzavier fail");

有時候設計到賦值的if...else,也可以使用短連接。同參考上面一篇文章。

if (條件表達式) {語句;} else if (條件表達式) {語句;} ... else {語句;}
if (1 > 2) {
    console.log("xzavier win"); 
} else if(3 > 2){
    console.log("xzavier win2"); 
} else {
    console.log("xzavier fail"); 
}

JavaScript其實是沒有else if的,else if算是一種封裝。看這里的js判斷:

var a = 3, b = 2;
a > b // true
a > b // false
a = b // false

額(⊙o⊙)…這不是在逗我嗎?不,我只是用最簡單的判斷說一下js的判斷:

a >= b // true  
//其實它是先判斷了 a < b 為false 再用“非正即反” 來返回 a >= b 的值

不信?看這個:

var a = {};  // 你可以添加任意屬性 {x:3};
var b = {};  // 你可以添加任意屬性 {z:2};;
a < b;    // false
a == b;   // false
a > b;    // false

對象的比較,可以參見本系列判斷相關的文章。
看上面沒問題是吧,但是用 >= 就不一樣了:

a <= b;    // true
a >= b;    // true

我...所以,也根據語言規范,先對 <= 的另一面求值,再“非正即反”。

那么回到else if呢,上面的代碼其實最終是這樣的:

if (1 > 2) {
    console.log("xzavier win"); 
} else {
     if(3 > 2){
        console.log("xzavier win2"); 
    } else {
        console.log("xzavier fail"); 
    }
}

把它拆分為多個if...else... 這只是個探究,因為else if司空見慣,代碼又少,語義很好,所以使用得多。所以,盡情的使用吧,我的意思是別避開寫else...if...,不是寫一大堆else...if...,如果有一堆else...if...,那還是用下面的switch吧

switch語句

switch 語句是多重條件判斷,用于多個值相等的比較。

var xzavier = "boy";
switch (xzavier) {
    case "girl" :
        console.log("xzavier is a girl");
        break;
    case "boy" :
        console.log("xzavier is a boy");
        break;
    case "man" :
        console.log("xzavier is a man");
        break;
    default : 
        console.log("time error");
}

if和switch之間可以轉換,當條件過多時,使用switch可以讓代碼更清晰,更好看。

這里說一下switch,它對括號里的語句求值一次,然后將返回值與每個case表達式進行匹配。如果找到一個匹配,就會開始執行那個匹配的case里的代碼,直到遇到一個break或者直到switch塊末尾。
所以,寫好break,很重要:

var xzavier = "boy";
switch (xzavier) {
    case "girl" :
        console.log("xzavier is a girl");
        break;
    case "boy" :
        console.log("xzavier is a boy");
    case "man" :
        console.log("xzavier is a man");
        break;
    default : 
        console.log("time error");
}
VM293:7 xzavier is a boy
VM293:9 xzavier is a man

沒有break掉,你的業務代碼可能就出現bug.使用switch就需要好好的考慮業務場景,該break的地方切勿忘記。

另外,表達式的返回值和每一個case表達式之間的匹配判斷使用的是全等運算符===

var xzavier = "1";
switch (xzavier) {
    case 1 :
        console.log("xzavier is a girl");
        break;
    case 2 :
        console.log("xzavier is a boy");
    case 3 :
        console.log("xzavier is a man");
        break;
    default : 
        console.log("type error");
}
// type error

還有一點就是 default 非必需,位置也可以不固定。因為js總是先去匹配表達式的返回值和每一個case表達式,最終沒有找到匹配的case,就會尋找default,找到了則執行default里的語句。沒找到則執行到switch塊末尾。

do...while語句

do...while 語句是一種先運行,后判斷的循環語句。也就是說,不管條件是否滿足,至少先運行一次循環體。

var xzavier = 1; 
do {
    console.log(xzavier);
    xzavier++;
} while (xzavier <= 10); 
// 1 2 3 4 5 6 7 8 9 10

var xzavier = 1; 
do {
    console.log(xzavier);
    xzavier++;
} while (xzavier <= 0);//先運行一次,再判斷
// 1
while語句

while 語句是一種先判斷,后運行的循環語句。

var xzavier = 1; 
while (xzavier <= 10) {  //先判斷,再運行
    console.log(xzavier);
    xzavier++;
}
// 1 2 3 4 5 6 7 8 9 10

var xzavier = 1; 
while (xzavier <= 0) {  //先判斷,再運行
    console.log(xzavier); // 不會執行
    xzavier++;
} 
for語句

for 語句也是一種先判斷,后運行的循環語句。但它具有在執行循環之前初始變量和定義循環后要執行代碼的能力。

for (var i = 0; i <= 10 ; i++) { 
    console.log(i); 
} 

第1步: 聲明變量var i = 1;
第2步: 判斷i <= 10
第3步: console.log(i);
第4步: i++
第5步: 重復2-5,直到判斷為false

這里我們經常會遇到這樣的寫法:

for (var i = 0; i <= data.length ; i++) {

建議先緩存data.length 為一個變量:

for (var i = 0, l = data.length; i <= l ; i++) {

這樣做的目的并不是一定能提升程序的性能,因為length屬性是一個字典屬性,讀取它和讀取變量的復雜度都為O(1)。
這樣做主要是為了防止在for循環中改變了data.length,具體使用還應視具體代碼而定。

當然,如果涉及到DOM,那么緩存變量就一定能提升代碼性能了。

for (var i = 0; i <= $(".item").length ; i++) {

每循環一次都$(".item") 就相對耗費性能了,與DOM有關的讀取大多情況都應先用變量緩存,特殊業務視情況而定。

var ietm_l = $(".item").length;
for (var i = 0; i <= ietm_l ; i++) {
for...in語句

for...in 語句可以用來枚舉對象的屬性。

var xzavier = { 
    "name" : "xzavier", 
    "age" : 23,
    "job" : "Jser",
    "width" : 100,
    "height" : 100,
    "border" : 10
};
for (var i in xzavier) { 
    console.log(i);
}
//name age job width height border
for (var i in xzavier) { 
    console.log(xzavier[i]);
}
//xzavier 23 Jser 100 100 10

for...in是為遍歷對象屬性設計的,但是它可以遍歷數組,我去,因為數組也是對象啊。 不過,for...in 循環遍歷的是對象的屬性,而不是數組的索引。我們看一下打印的結果就知道了:

var arr = [1,2,3];
for(var i in arr) {
    console.log(typeof(i));
}
// string string string

而經典的for語句遍歷是數組的索引:

var arr = [1,2,3];
for(var i = 0; i < arr.length; i++) {
    console.log(typeof(i));
}
// number number number

我們用for...in遍歷數組時,取arr[i]時是我們期望得到的結果:

var arr = [1,2,3];
for(var i in arr) {
    console.log(i + "--" + arr[i]);
}
// 0--1 1--2 2--3

但是:

var arr = [1,2,3];
arr.name = "xzavier";
for(var i in arr) {
    console.log(i + "--" + arr[i]);
}
VM230:4 0--1
VM230:4 1--2
VM230:4 2--3
VM230:4 name--xzavier

它訪問了數組新增的 "name" 屬性,因為 for-in 遍歷了對象的所有屬性。

甚至包括原型鏈上的所有可枚舉的屬性:

var arr = [1,2,3];
    arr.name = "xzavier";Array.prototype.oname = "xzavier.chris"
    for(var i in arr) {
        console.log(i + "--" + arr[i]);
    }
VM236:4 0--1
VM236:4 1--2
VM236:4 2--3
VM236:4 name--xzavier
VM236:4 oname--xzavier.chris

顯然,我們習慣的數組遍歷的結果是只有1,2,3 這樣的結果的。

所以,綜合來說:
for...in 循環遍歷的是對象的屬性,而不是數組的索引。正如例子,輸出的索引值 "0"、 "1"、 "2"不是 Number 類型的,而是 String 類型的,因為是對象的屬性都是string類型。

這樣看來,for...in是不適合遍歷數組的。確實,for...in本來就是為遍歷對象屬性設計的。

不過,在對于比較特殊的數組,for...in或許有用:

var arr = Array(1000), count = 0;
arr[100] = 100;
arr[200] = 200;
arr[300] = 300;
for(var i in arr) {
    count += 1;
    console.log(i + "--" + arr[i]);
}
console.log(count);
VM242:7 100--100
VM242:7 200--200
VM242:7 300--300
VM242:9 3   // 只循環了3次額

而for循環:

var arr = Array(1000), count = 0;
arr[100] = 100;
arr[200] = 200;
arr[300] = 300;
for(var i = 0; i < arr.length; i++) {
    count += 1;
    console.log(i + "--" + arr[i]);
}
console.log(count);
// count 1000  循環了這么多次
// 打印出100 200 300 和一堆的undefined

so :
for...in 只會遍歷對象中存在的實體,而for 循環則會遍歷 1000 次。如果你的業務剛好有這樣的需要,那么合適的使用for..in遍歷數組將會發揮更奇妙的作用。
但是一般來看,這樣用到的機會很少,上面的指定索引是一種,另外你使用了delete去刪除數組元素之后(非特殊,不要用delete去刪除),也是可以這樣遍歷的:

var arr = [1,2,3];
delete arr[1]
for(var i in arr) {
    console.log(i + "--" + arr[i]);
}
VM246:4 0--1
VM246:4 2--3

但是,一般情況誰允許你用delete去刪除數組元素呢。關于數組可以參考我的另一篇對數組詳解的文章。

forEach循環

for...in是為遍歷對象屬性設計的,當然也可以遍歷數組。后來,ES5也為素組設計了一個forEach方法來遍歷。
forEach方法為數組中含有有效值的每一項執行一次 callback。callback有三個參數:
callback(數組當前項的值,數組當前項的索引,數組對象本身)

var arr = [1,2,3,4,5,"xzavier",7];
arr.forEach(function (value, index, arr) {
    console.log(value);
});
// 1 2 3 4 5 xzavier 7

注意:

1.使用forEach循環的時候,需要注意,forEach 遍歷的范圍在第一次調用 callback 前就會確定。調用forEach 后添加到數組中的項不會被 callback 訪問到。

在數組后面添加:

var arr = [1,2,3,4,5,"xzavier",7];
arr.forEach(function (value, index, arr) {
    if (value == 3) {
        arr.push(8);
    }
    console.log(value);
});
// 1 2 3 4 5 xzavier 7

在數組前面添加:

var arr = [1,2,3,4,5,"xzavier",7];
arr.forEach(function (value, index, arr) {
    if (value == 3) {
        arr.unshift(0);
    }
    console.log(index + "--" +value);
});
VM316:6 0--1
VM316:6 1--2
VM316:6 2--3
VM316:6 3--3
VM316:6 4--3
VM316:6 5--3
VM316:6 6--3

什么情況?因為你在數組前添加1項后,遍歷下一項的值,發現值還是3,所以后面的遍歷一直都走到if語句里了。
但是數組的遍歷范圍是不可變的。

2.如果已經存在的值被改變,則傳遞給 callback 的值是 forEach 遍歷到他們那一刻的值。

var arr = [1,2,3,4,5,"xzavier",7];
arr.forEach(function (value, index, arr) {
    arr[5] = "xx";
    console.log(value);
});

3.已刪除的項不會被遍歷到(使用delete方法等情況,或者直接置為undefined)。

var arr = [1,2,3,4,5,"xzavier",7];
arr.forEach(function (value, index, arr) {
    if (value == 3) {
        delete arr[5];;
    }
    console.log(value);
});
// 1 2 3 4 5 7

但是使用別的方法刪除就就會出錯哦:

var arr = [1,2,3,4,5,"xzavier",7];
arr.forEach(function (value, index, arr) {
    if (value == 3) {
        arr.shift(0);
    }
    console.log(value);
});
// 1 2 3 5 xzavier 7   

第四個值不在了,因為forEach記住了最開始的length,但是shift卻改變了length。其他的方法同理。
而delete并沒有把數組項刪掉,只是把值置為了undefined,所以length未變。

4.不能使用break或continue中斷或跳出循環,報錯。不過可以return false 跳出當前循環,達到一定效果:

var arr = [1,2,3,4,5,"xzavier",7];
arr.forEach(function (value, index, arr) {
    if (value == 3) {
        return false;
    }
    console.log(value);
});
// 1 2 4 5 xzavier 7
for...of語句

for...in循環,只能獲得對象的鍵名,不能直接獲取鍵值,并且遍歷數組不友好。
forEach中又不能使用break語句中斷循環,也不能使用return語句返回到外層函數。

ES6提供for...of循環,允許遍歷獲得鍵值。如果要通過for...of循環,獲取數組的索引,可以借助數組實例的entries方法和keys方法。它還可以正確響應break、continue和return語句。for-of 還可以遍歷 Map 和 Set (ES6 中新增數據集合類型),以及其他可迭代對象。

var arr = ["a", "b", "c", "d"];   
for (let i in arr) {
      console.log(i); // 0 1 2 3
}
for (let i of arr) {
      console.log(i); // a b c d
}
for (var i of arr) {
    if(i == "c"){
        break;
    }
      console.log(i); // a b
}

let str = "xzavier";
for (let i of str) {
      console.log(i); // x z a v i e r
}
break和continue語句

break 和continue 語句用于在循環中精確地控制代碼的執行。其中,break 語句會立即退出循環,強制繼續執行循環體后面的語句。而continue 語句退出當前循環,繼續后面的循環。

for (var i = 1; i <= 10; i++) {
    if (i == 5) break; //如果i等于5,就退出循環
    console.log(i); //1 2 3 4
}
for (var i = 1; i <= 10; i++) {
    if (i == 5) continue; //如果i等于5,就退出當前循環
    console.log(i); // 1 2 3 4 6 7 8 9 10
}
標記跳轉

我們程序員應該都知道有個字段叫:goto,可以讓你的程序跳到指定的地方執行。由于goto遭到非議太多,使用這類編碼形式會使你的代碼難以理解和維護,基本不建議使用,如果JavaScript也有goto語句,那么在上面continue的基礎上我們還可以讓程序的執行跳轉到指定的代碼中的那個位置。不過,幸好,JavaScript沒有這個標識,所以,我們的世界很歡暢。不過,你要是想這樣做,我們還是有類似的實現的:

xzavier: for (var i = 1; i <= 10; i++) {
    if (i == 5) {
        continue xzavier; // 一層循環,與continue無異
    }
    console.log(i);
}
// 1 2 3 4 6 7 8 9 10

在多層循環的時候作用就區別出來了:

xzavier: for (var i = 1; i <= 10; i++) {
    for( var j = 1; j <= 10; j++) {
        if (i == j) {
            continue xzavier;
        }
        console.log(i + ">" + j);
    }
}
VM123:6 2>1
VM123:6 3>1
VM123:6 3>2
VM123:6 4>1
VM123:6 4>2
VM123:6 4>3
VM123:6 5>1
VM123:6 5>2
VM123:6 5>3
VM123:6 5>4
VM123:6 6>1
VM123:6 6>2
VM123:6 6>3
VM123:6 6>4
VM123:6 6>5
VM123:6 7>1
VM123:6 7>2
VM123:6 7>3
VM123:6 7>4
VM123:6 7>5
VM123:6 7>6
VM123:6 8>1
VM123:6 8>2
VM123:6 8>3
VM123:6 8>4
VM123:6 8>5
VM123:6 8>6
VM123:6 8>7
VM123:6 9>1
VM123:6 9>2
VM123:6 9>3
VM123:6 9>4
VM123:6 9>5
VM123:6 9>6
VM123:6 9>7
VM123:6 9>8
VM123:6 10>1
VM123:6 10>2
VM123:6 10>3
VM123:6 10>4
VM123:6 10>5
VM123:6 10>6
VM123:6 10>7
VM123:6 10>8
VM123:6 10>9

continue xzavier表示跳到標記為xzavier的循環,并繼續下一次迭代。如果不使用這個標識符的話只會在內層循環中跳出當次循環并繼續下一次循環。

當然,我們也不建議使用這樣的寫法,并沒有那么好用。舉例很隨意,并非要實現一個這樣的業務。如果要實現類似的功能,用continue換個寫法就OK了。這里主要說明下我們還是有這樣的寫法存在的,用不用看你心情,看你的場景,以及你的團隊同不同意。

with語句

with語句的作用是將代碼的作用域設置到一個特定的對象中。當代碼運行到with語句時,執行上下文的作用域鏈臨時被改變了。一個新的可變對象被創建,它包含了參數指定的對象的所有屬性。這個對象將被推入作用域鏈的頭部,這意味著函數的所有局部變量現在處于第二個作用域鏈對象中,因此訪問代價更高了。如果,再挖深一點,JavaScript 引擎在編譯階段遇到with字段都不能好好的干活兒了,因為它不知道這個with最后會怎么改變作用域,本想把變量作用域都安置好都不行了。所以,一般不建議使用。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/80121.html

相關文章

  • 溫故js系列(16)-數組&數組方法使用詳解

    摘要:創建數組數組字面量數組構造函數參數為數組建議使用數組字面量方式,性能好,代碼少,簡潔,畢竟代碼少。數組判斷方法用來判斷某個值是否為。的這是最簡潔最直接的遍歷數組元素的語法。把數組轉換為本地數組,并返回結果。 前端學習:前端教程&開發模塊化/規范化/工程化/優化&工具/調試&值得關注的博客/Git&面試-前端資源匯總 歡迎提issues斧正:數組&數組方法使用詳解 Array對象 之前一...

    morgan 評論0 收藏0
  • 溫故js系列(4)-運算符詳解

    摘要:一元運算符一元運算符只能操作一個值。邏輯非邏輯非參考數據判斷邏輯非運算符可以用于任何值。無論這個值是什么數據類型,這個運算符都會返回一個布爾值。 前端學習:教程&開發模塊化/規范化/工程化/優化&工具/調試&值得關注的博客/Git&面試-前端資源匯總 歡迎提issues斧正:運算符 JavaScript-運算符 JavaScript 有一系列操作數據值的運算符,運算符按照特定運算規則對...

    王軍 評論0 收藏0
  • 溫故js系列(17)-詳解加法運算符

    摘要:數字和解釋因為沒有任何一個操作數是字符串,將轉換為一個數字做數字加法運算因為沒有操作數是對象或字符串,將轉換為。結論以避免潛在的問題,不使用加法運算符處理對象,除非你清楚地使用或方法。 前端學習:教程&模塊化/規范化/工程化/優化&工具/調試&值得關注的博客/Git&面試資源匯總 JavaScript一路走來,備受爭議,與其說它備受爭議,不如說它不夠完美。不夠完美?那完美了還得了,它的...

    gxyz 評論0 收藏0
  • 溫故js系列(18)-對象&對象使用

    摘要:對象創建字面量方式構造函數方式也可以這樣不過這樣的話,為何不選擇字面量方式字面量方式和方式的寫法是等價的,返回的結果是同種類的對象。構造函數產生實例時,實例通過其對應原型對象的訪問對應的構造函數對象。 前端學習:教程&模塊化/規范化/工程化/優化&工具/調試&值得關注的博客/Git&面試資源匯總 歡迎提issues斧正:對象&對象使用 Object對象 在 JavaScript 中,對...

    keke 評論0 收藏0
  • 溫故js系列(14)-閉包&垃圾回收&內存泄露&閉包應用&作用域鏈&

    摘要:該對象包含了函數的所有局部變量命名參數參數集合以及,然后此對象會被推入作用域鏈的前端。如果整個作用域鏈上都無法找到,則返回。此時的作用域鏈包含了兩個對象的活動對象和對象。 前端學習:教程&開發模塊化/規范化/工程化/優化&工具/調試&值得關注的博客/Git&面試-前端資源匯總 歡迎提issues斧正:閉包 JavaScript-閉包 閉包(closure)是一個讓人又愛又恨的somet...

    Amio 評論0 收藏0

發表評論

0條評論

blastz

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<