JavaScript 學習筆記 之 語句和表達式

語句和表達式

語句和表達式的區別就像英語中的句子和短語的區別一樣,多個表達式通過標點符號或者連接詞連接成語句

JavaScript中表達式可以返回一個結果值

		var a = 3 * 6;
		var b = a;
		b;

這三行代碼都是包含表達式的語句

其中 第一行的3*6 , 第二行的a , 第三行的b都是一個表達式,結果值都是18

var  a=3*6和var b=a被稱爲"聲明語句",因爲他們聲明瞭變量

a=3*6和b=a(不帶var)叫"賦值表達式".

第三行代碼只有一個表達式b,同時也是一個語句,被稱爲"表達式語句"

 

語句的結果值

每個語句都有一個結果值(undefined也算)

獲得結果值最直接的方法是在瀏覽器控制檯中輸入語句,默認情況下控制檯會顯示所執行的最後一條語句的值

如 輸入 b=a ,其結果值是賦給b的值

但 規範定義var 的結果值是undefined,如果在控制檯中輸入var a= 42會得到undefined而不是42

(ES5中其實變量聲明算法是有一個返回值的(是一個包含聲明變量名稱的字符串),但是這個值被變量語句算法屏蔽掉了(for..in除外))

但是在代碼中我們無法直接獲取這個結果值(賦值表達式,表達式語句除外)

先來看看其他語句

比如代碼塊{..}的結果值是最後一個語句/表達式的結果

換句話來說,代碼塊的結果值就如同一個隱式的返回,即返回最後一個語句的結果值

但下面這樣的代碼無法運行

		a = if(true) {
				b = 2;
			}//Uncaught SyntaxError

因爲語法不允許我們獲得語句的結果值並賦給另一個變量

那應該怎麼獲取語句的結果值呢

		a = eval(`if(true) {
				b = 2;
			}`);

		a; //2

注意!! 永遠不要在實際開發中使用這種方法!!會導致代碼運行速度變慢!!(具體原因看這篇)

ES7中有一項提案 "do表達式" (未實裝)

		a = do {
			if(true) {
				b = 2;
			}
		}

類似於這樣,do{..}表達式執行一個代碼塊,並返回最後一個語句的結果值,然後賦值給a

 

表達式的行爲

表達式除了會返回一個結果值,還會有一些附加的行爲

比如 

		var a = 42;
		var b = a++;

其中a=42和b=a++(不帶var)都是一個賦值表達式

a++首先返回變量a的當前值42(再將該值賦給b),然後將a的值加1(附加行爲)

遞增運算符++和遞減運算符--都是一元運算符(會強制轉換爲數字),她們既可以用在操作數的前面,也可以用在後面

在前面的時候,如++a,她的附加行爲(將a遞增)產生在表達式返回結果之前,在後面的時候,則發生在表達式返回結果之後

而++a++則會報錯,根據優先級會先執行a++,返回結果值42,然後執行++42,這時候會產生ReferenceError錯誤

 

還有一種常見的誤解是()能將a++的行爲封裝起來

然而事實上(a++)還是會先返回原本的值後在執行加1的行爲,除非在++後再次對a進行運算

比如(a++,a)

(由於優先級的關係,所以需要放在括號中)

返回的是最後一個語句的結果值,也就是a+1後的值

		var a = 42;
		var b = (a++, a);
		b; //43

 

標籤語句

類似於 foo:fun() 這樣的語法叫做標籤語句,foo是語句fun()的標籤

使用情形如下,continue foo的作用是執行foo循環的下一輪循環,直接寫continue的話,則是執行當前循環的下一循環

		foo: for(let i = 1; i < 3; i++) {
			for(let j = 1; j < 3; j++) {
				console.log(i, j);
				if(i == j) {
					continue foo;
				}
			}
		}

注意, continue ___只能對帶標籤的循環代碼使用

但是 break ___可以對帶標籤非循環代碼使用,作用是挑出標籤___所在的循環/代碼塊

			(function() {
				foo: {
					console.log("hello");
					break foo;
					console.log("never show");
				}
			})()

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章