詞法作用域後續
舉書上的例子
function foo(a){
var b = a * 2;
function bar(c){
console.log(a,b,c);
}
bar(b*3);
}
foo(2);
複製程式碼
我在這裡把書中的例子再囉嗦一遍hhh
2.2中主要講了開發者如何欺騙詞法
欺騙詞法主要有兩種途徑,在這裡提及一下,不做大篇幅的說明,作者也有說盡量避免使用
- eval()
- with
大家知道一下就可以啦,在這裡把作者不推薦使用的原因大概羅列一下把。
- eval()和with會被嚴格模式所影響(限制)。
- 這兩個機制的副作用是引擎無法在編譯時對作用域查詢進行優化,因為引擎只能謹慎的認為這樣的優化是無效的。使用者其中任何一個機制都將導致程式碼執行變慢。不要使用它們。
好啦第二者完結^_^,棒棒的。開啟第三章的總結
第三章 , 函式作用域和塊作用域
3.1函式中的作用域
明確概念
函式作用域的含義是指,屬於這個函式的全部變數都可以在整個函式的範圍內使用及複用(事實上在巢狀的作用域中也可以使用)。這種方案是非常有用的,能充分利用javascript變數可以根據需要改變值型別的**"動態"**特徵
3.2 隱藏在內部的實現
這裡著重說一下規避衝突
function foo(){
function bar(a){
i = 3; //for迴圈的時候會修改所屬作用域中的 i
console.log(a+i)
}
for(var i = 0;i<10;i++){
bar(i*2) //程式碼執行到這裡的時候就會將i賦值為3,從而導致無線迴圈
}
}
複製程式碼
變數衝突常見的就是存在於全域性作用域中,當程式中載入了多個第三方庫時,如果它們沒有妥善的將內部私有的函式或者變數隱藏起來,就會很容易引發衝突,還有就是多人合作開發的時候,儘量將全域性變數都做好註釋,或者少用全域性變數。
類庫的通常做法是暴露出去一個物件
eg:
var Jquery = {
hide: function(){
/*doSomething*/
},
show: function(){
/*doSomething*/
}
}
複製程式碼
3.3函式作用域
我們知道在任何程式碼外面加都可以新增包裝函式,可以將內部的變數和函式定義**“隱藏”**起來,外部作用域無法訪問到包裝函式內部的任何內容。
eg
var a = 100;
var b = 200;
var c = a + b;
//這樣的程式碼我們通常會封裝成為一個功能型的函式
function add(a,b){
return a + b;
}
//------------------------------------變形---------------------------------------------
(function(a,b){
return a + b;
})(100,200);
//包裝函式的宣告以(function...而不僅僅是以function...開始,在這裡函式會被當做表示式而不是一個標準的函式宣告來處理。
複製程式碼
3.3.1 匿名和具名
- 匿名函式
- 匿名函式在棧記憶體追蹤中不會顯示出有意義的函式名,使得除錯很困難。
- 對於程式碼的可讀性,有著很重要的作用,一個描述性的名稱可以讓程式碼不言而明。
3.3.2 立即執行函式
var a = 2;
(function(){
var a = 3;
console.log(a); //3
})()
console.log(a) //2
複製程式碼
3.4 塊級作用域
- try/catch
非常少有人注意到Javascript的ES3規範中規定try/catch分句會建立一個塊作用域,其中宣告的變數僅在catch作用域內部有效
eg
try {
undefined(); //執行一個非法操作
}
catch(err){
console.log(err) //能夠正常執行
}
console.log(err); //err not found
複製程式碼
-
let
-
let關鍵字可以將變數繫結到所在的任意作用域中,通常是{....}內部。換句話說,let可以顯示的將作用域用{}清楚的分來,以便於程式的開發,以及維護。
-
let 宣告的變數不會再作用域內產生變數提升,宣告的程式碼在執行之前並不“存在”而非var 宣告的變數會輸出undefined
eg
//var { console.log(a); //undefined var a = 100; } // let { console.log(a) let a = 100; //ReferenceError!a is not defined } 複製程式碼
-
好啦,今天先寫到這裡,待後續。。。