1. 程式人生 > >Javascript筆記(六)之程式結構與流程控制語句

Javascript筆記(六)之程式結構與流程控制語句

一、程式結構簡介

1、幾個基本概念

程式結構分為順序結構、分支結構、迴圈結構,通常伴隨著這幾種程式結構存在的還有流程控制語句; 在ECMA-262規定來一組流程控制語句,語句定義了ECMAScript中的主要語法,語法通常由一個或多個關鍵字來完成給定的任務,例如:判斷、迴圈、退出等;

語句:在ECMAScript之中,所有的程式碼都是由語句來構成都。語句表明執行過程中都流程、限定與約定,形式上可以是單行語句,或者由一對大擴號{}括起來都複合語句,在語法描述之中,複合語句整體可以作為一個單行語句處理;

語句的種類: 1、宣告語句 變數宣告語句、標籤宣告語句 2、表示式語句 變數賦值語句、函式呼叫語句、屬性賦值語句、方法呼叫語句 3、分支語句 條件分支語句、多重分支語句 4、迴圈語句 for、for…in、for…of、while、do…while 5、控制結構 繼續執行子句、終端執行子句、函式返回子句、異常觸發子句、異常捕獲與處理 6、其他語句 空語句;

with語句、debugger語句

2、順序結構

順序結構是最為簡單的結構,程式自上而下依次執行的結構就成為順序結構

二、分支結構

程式結構分為順序結構、分支結構、迴圈結構,通常伴隨著這幾種程式結構存在的還有流程控制語句

1、if語句

隨著條件的不同,我們可以由if結構、if…else…結構、if…else if…else結構。

在if語句的括號裡的表示式會進行自動轉換為Boolean型別,如果為true,則執行後面一條語句,否則不執行後面那一條語句; 在if條件成立之後,只執行其後的一條語句,如果要執行多條語句,那麼必須使用{}包含在內,形成一個程式碼塊;

1.1、if結構

if(表示式)
[{] // 迴圈體; [}]

大括號不存在,則迴圈體為單行語句,否則為複合語句;

1.2、if…esle…結構

if(表示式) {
     // 表示式為true執行的位置
} else {
	// 表示式為false執行的位置
}

1.3、if…esle if…else結構

if(表示式1) {
     // 表示式1為true執行的位置
}else if(表示式2) {
	// 表示式1為false,表示式2為true執行的位置
}... else{
	// 表示式n-1為false,表示式n為true執行的位置
}

2、條件表示式:三目運算子

	條件表示式?成立執行的表示式:不成立執行的表示;

3、switch…case結構

	switch(表示式){
		case1:語句1;[break;]
		case2:語句2;[break;]
		case3:語句2;[break;]
		case 值n:語句2;[break;]
		[default:] //都不匹配執行的語句;
	}

注: switch語句會先計算表示式,然後在每個case語句去比較表示式的值,使用嚴格運算子(===),並將控制權轉換給該子句;如果都沒有則執行defualt子句,然後switch語句執行結束,defualt子句是最後一個子句,但不是必須的;

break語句是可選的,該語句確保可以在相關的case語句執行後,結束switch之後的語句,如果省略,則會繼續執行switch語句中的下一條語句;

defualt語句的順序不是固定的,可以在case之前;

case表示式之中可以使用複雜的運算

三、迴圈結構

1、while語句

while(表示式) {
   // 迴圈體
}

while語句中的表示式,也會自動進行型別轉換,轉換為Boolean型別,當表示式為true的時候,則執行迴圈體中的內容,否則不執行;

2、do..while語句

do {
  // 迴圈體
}while(表示式);

do..while語句先執行迴圈體,在判斷,所以該語句結構,不管表示式是否成立,都會執行一次,迴圈體至少執行一次;

3、for語句

for ([initialization]; [condition]; [final-expression]){
    // 迴圈體 
}

for迴圈也被成為for i迴圈,通常的用法如下

for(var i = 0 ;i < 條件; i++){
    // 迴圈體
}

4、for...in...語句

語法介紹

for (variable in object) {...}
或者相容性表示式
for (var variable in object) {...}

注:

  1. 相容IE6
  2. for...in...可以任意順序遍歷一個物件的可列舉屬性,包括原型,對於每個不同的屬性,語句都會被執行;
  3. for...in...只遍歷可列舉屬性;
  4. 如果一個屬性在一次迭代中被修改,在稍後被訪問,其在迴圈中的只是其稍後時間的
// for in 遍歷物件
var personObj = {
    name:"xiaojia",
    age:26,
    hobby:'football,programming',
    test:function(){
        console.log("111");
    }
}

for(var key in personObj){
    console.log(key,personObj[key]);
}
/* 以下為輸出結果
name xiaojia
age 26
26
hobby football,programming
football,programming
test function (){
        console.log("111");
    }
*/

// for in 遍歷陣列
var arr = ["xiaojia",26,"程式設計"]
for(var key in arr){
    console.log(key,arr[key]);
}
/* 以下為輸出結果
0 xiaojia
1 26
2 程式設計
*/

for...in...潛在問題與解決方案

1、for...in...只遍歷可列舉的屬性,包括繼承來的屬性,不可列舉的屬性在重寫之後,也變得可列舉,此時可以使用hasOwnProperty()或者Object.defineProperty來解決;

Object.prototype.test = "test1";
Array.prototype.test2 = "test2";

Object.prototype.say1 = function(){
    console.log("你好");
};


Array.prototype.say2 = function(){
    console.log("你好");
};

var arr = ["xiaojia",26,"程式設計"]
for(var key in arr){
    console.log(key,arr[key]);
}

/*
0 xiaojia
1 26
2 程式設計
test2 test2
say2 function (){
    console.log("你好");
}
test test1
say1 function (){
    console.log("你好");
}
*/

顯然,我們就出現了不屬於陣列的屬性,而是Object繼承而來的,我們這裡也輸出了;解決方案就是使用hasOwnProperty()或者Object.defineProperty來解決;

// 解決方法一:
Object.prototype.test = "test1";
Array.prototype.test2 = "test2";
Object.prototype.say2 = function(){
    console.log("你好");
};
Array.prototype.say3 = function(){
    console.log("你好");
};
var arr = ["xiaojia",26,"程式設計"]
for(var key in arr){
    if(arr.hasOwnProperty(key)){
        console.log(key,arr[key]);
     }
}

/*
0 xiaojia
1 26
2 程式設計
test2 test2
say2 function (){
    console.log("你好");
}
test test1
say1 function (){
    console.log("你好");
}
*/

// 解決方法二:使用Object.defineProperty來解決(支援IE9,也支援IE8,但是隻支援Dom物件和非標準行為)
Object.defineProperty(Object.prototype,'say',{
            value:function(){
                console.log('say1!');
            },
            enumerable: false //讓say屬性不可列舉,需設定enumerable屬性值為false
        });

Object.defineProperty(Array.prototype,'say',{
            value:function(){
                console.log('say2!');
            },
            enumerable: false //讓say屬性不可列舉,需設定enumerable屬性值為false
        });
var arr = ["xiaojia",26,"Java開發工程師"]
for(var key in arr){
    console.log(key,arr[key]);
}
/*
0 xiaojia
1 26
2 程式設計
*/

2、for...in...在遍歷陣列的時候,key為string,而不是int型別;

// for in 存在的問題2
Object.defineProperty(Object.prototype,'say',{
            value:function(){
                console.log('say1!');
            },
            enumerable: false //讓say屬性不可列舉,需設定enumerable屬性值為false
        });

Object.defineProperty(Array.prototype,'say',{
            value:function(){
                console.log('say2!');
            },
            enumerable: false //讓say屬性不可列舉,需設定enumerable屬性值為false
        });
var arr = ["xiaojia",26,"程式設計"]
for(var key in arr){
    console.log(typeof key);
}
/*
string
string
string
*/

5、for...of...語句(ES6語法)

for (variable of iterable) {
    //statements
}

注: 此為ES6的語法結構,for...of...在可迭代物件(ArrayMapSet、String、TypedArrayarguments等)上建立一個迭代迴圈,呼叫自定義迭代鉤子,併為每個不同屬性的值執行語句

由於for...in結構存在問題,所以ES6就推出來一個for..of語法

Object.defineProperty(Object.prototype,'say',{
            value:function(){
                console.log('say1!');
            },
            enumerable: false //讓say屬性不可列舉,需設定enumerable屬性值為false
        });

Object.defineProperty(Array.prototype,'say',{
            value:function(){
                console.log('say2!');
            },
            enumerable: false //讓say屬性不可列舉,需設定enumerable屬性值為false
        });


var arr = ["xiaojia",26,"程式設計"]
for(var value of arr){
    console.log(value,typeof value);
}

/*
xiaojia string
26 'number'
程式設計 string
*/

注: IE不相容,edge12相容

6、死迴圈

當條件的恆成立的時候,就構成來死迴圈了;

7、for...of...for...in...的區別

結論: 1、for...in...迴圈的是key,for...of...迴圈的是value 2、推薦在迴圈物件屬性的時候,使用for...in...,在遍歷陣列的時候使用for...of...fori或者Array.prototype.forEach() 3、for...of...是ES6新引入的特性,修復了ES5的for...in...的不足 4、for...of...不能迴圈普通的物件,需要通過和Object.keys()搭配使用 5、for...of...不相容IE,for...in...相容ie6

四、流程控制語句

1、break

break用於終止switch語句的執行,和跳出當前迴圈,也可以跳出指定標號位置的迴圈;

2、continue

continue用於結束當前迴圈,繼續下一輪迴圈;

3、標號的使用

所謂標號,就是label:,一般就是為某個程式碼段設定一個標記,方便break和continue能夠跳出或結束多層迴圈, 而不僅僅是當前層迴圈;