看到這樣一個問題:為什麼直接在控制台運行{} + []和用console.log({} + [])輸出,兩者結果不一樣? 於是乎打開chrome的控制台運行了一下: 為什麼結果會這樣呢?不得已學習一下JS中的{}吧 複合語句 1 if() { 2 //... 3 }else { 4 //... 5
看到這樣一個問題:為什麼直接在控制台運行{} + []和用console.log({} + [])輸出,兩者結果不一樣?
於是乎打開chrome的控制台運行了一下:
為什麼結果會這樣呢?不得已學習一下JS中的{}吧
複合語句
1 if() { 2 //... 3 }else { 4 //... 5 } 6 for() { 7 //... 8 } 9 while() { 10 //... 11 } 12 with(obj) { 13 //... 14 }
聲明對象直接量
1 var obj = { 2 name: 'Marco', 3 age: 22, 4 sex: male 5 };
聲明函數或函數直接量
1 function fn1() { 2 //... 3 } 4 var fn2 = function() { 5 //... 6 }
沒有塊級作用域
1 for( var i = 0; i < 10; i++) { 2 doSomething(i); 3 } 4 5 alert(i); //10
javascript只有函數作用域,以下做法會聲明全局變數:
- 直接為window添加屬性或者賦值 //window.a = 1;
- 在function內不使用var聲明變數而直接使用
- 在function外使用聲明變數(無論是否適用var聲明)
1 function(num1 , num2) { 2 var sum = num1 + num2; 3 return sum; 4 } 5 6 var result = add(10,20); //30 7 alert(sum); //錯誤 8 9 10 function(num1 , num2) { 11 sum = num1 + num2; 12 return sum; 13 } 14 15 var result = add(10,20); //30 16 alert(sum); //30
建議在初始化變數之前一定要先聲明,這樣可以避免不聲明而直接初始化變數造成的錯誤。
當在某個環境中使用一個標識符時,必須先通過搜索來確定該標識符代表什麼。搜索過程從作用域鏈的前端開始,向上逐級查詢與給定名字匹配的標識符。若在該環境中找到了該標識符,則搜索停止,變數就緒。若在該局部環境沒有找到該變數,則繼續沿作用域鏈向上搜索,一直追溯到全局環境的變數對象。若在全局環境中沒有找到該標識符,則說明該變數尚未聲明。
1 var num = 1; 2 3 function getNum() { 4 var num = 10; 5 return num; 6 } 7 8 alert(getNum()); //10
變數查詢是有代價的。很明顯,訪問局部變數要比訪問全局變數更快,因為不用向上搜索作用域鏈。來看看jquery這麼做的:
(function(window, undefined) { var jQuery = function() {} // ... window.jQuery = window.$ = jQuery; })(window);
這樣寫的優勢:
1、window和undefined都是為了減少變數查找所經過的scope作用域。當window通過傳遞給閉包內部之後,在閉包內部使用它的時候,可以把它當成一個局部變數,顯然比原先在window scope下查找的時候要快一些。(原來的window處於作用域鏈的最頂端,查找速度慢)
2、在jquery壓縮版本jquery.min.js中可以將局部變數window替換成單個字母,減小文件大小,提高載入速度。
3、undefined也是JavaScript中的全局屬性。將undefined作為參數傳遞給閉包,因為沒給它傳遞值,它的值就是undefined,這樣閉包內部在使用它的時候就可以把它當做局部變數使用,從而提高查找速度。undefined並不是JavaScript的保留字或者關鍵字。
4、undefined在某些低版本的瀏覽器(例如IE8、IE7)中值是可以被修改的(在ECMAScript3中,undefined是可讀/寫的變數,可以給它賦任意值,這個錯誤在ECMAScript5中做了修正),將undefined作為參數並且不給它傳值可以防止因undefined的值被修改而產生的錯誤。
結構化異常處理的語法符號
1 try { 2 //... 3 }catch( ex ){ 4 //... 5 }finally{ 6 //... 7 }
語句優先
當{}既可以被理解為複合語句塊也可以被理解為對象直接量或函數聲明的時候,JavaScript將會將其理解成為複合語句塊
1 {a:10} //返回1,而不是對象 : 為標簽 2 3 var x = { a:10 } // {a:10}作為右值出現,不能是語句塊,只能理解為對象直接量
至此,{}的基本知識就說完了。那麼最開始的問題也很好解釋了:
{}+[] :根據語句優先原則 {}被理解為複合語句塊,因此相當於 {}; +[] 。[]為空,結果為0
console.log({}+[]) : js把()中的語句當做一個表達式,因此{}不能被理解為語句塊,而被理解為對象直接量,因此結果為對象
其實 console.log({}+[])和[]+{}的結果相同,原理相同,{}作為右值出現被理解為對象直接量
{}+[] 和[]+{}結果不相同,是不是很神奇。
來來來,做幾個練習題壓壓驚:
1 {a: 1} + 2 // 2 2 2 + {a: 1} // 2[object Object] 3 + {a: 1} // NaN 4 {foo:[1,2,3]}[0]; // [0]
以上