函數中的做用域 es6
所謂函數做用域,就是屬於這個函數的所有變量均可以在整個函數的範圍內使用及複用。函數
1 function foo(a) { 2 var b=a; 3 function bar(c){ 4 var c=b*2; 5 console.log(c); 6 } 7 bar(); //4 8 } 9 foo(3);
1 function foo(a) { 2 var b=a; 3 function bar(c){ 4 var c=b*2; 5 console.log(c); 6 } 7 bar(); 8 } 9 bar(2); //not defined
命名衝突工具
在同一做用域中,相同的命名會引發衝突。spa
1 function foo() { 2 function bar(a){ 3 i=3; 4 console.log(i+a); 5 } 6 for(var i=0;i<10;i++){ 7 bar(i); 8 } 9 } 10 foo();
上面的代碼將會引發衝突,函數會一直執行下去,行成死循環。code
如何避免命名衝突呢?對象
(1)全局命名空間blog
一些第三方庫一般都是在全局對象中聲明一個獨特的對象,庫的方法和實例都在這個對象中,當咱們調用時直接調用這個獨特的對象就行了。作用域
1 var MyLibrary={ 2 param1:'param1', 3 doSomething:function () { 4 5 }, 6 doElseThing:function () { 7 8 } 9 //....... 10 }
(2)模塊管理get
另外一種避免衝突的方法和如今的模塊機制很接近,就是從衆多模塊管理器中挑選一個來使用。使用這些工具,任何庫都無需將標識符加入到全局做用域中,而是經過依賴管理器的機制將庫的標識符顯示地導入到另外一個特定的做用域中it
立執行函數
將函數包裹在一對括號中,使之成爲一個表達式,再在後面加一個括號,使之執行,這樣函數就會自執行。這種模式又稱IIFE。
自執行函數有兩種寫法形式,第一種是將整個函數寫在括號中,再在括號外面加一對括號:(function(){//do something})();
還有一種是:(function(){//do something}())。
這兩種寫法功能都相同。
自執行函數傳參
1 (function(doc){ 2 var a='按鈕'; 3 doc.getElementById('btn').innerText=a; 4 })(document);
塊做用域
當咱們寫for循環時,咱們都但願i只在循環的上下文中起到做用,而事實上i會被綁定到他所在的做用域中。好比上面的命名衝突中的例子。
那麼如何解決塊做用域的問題呢?
(1)使用自執行函數將循環包住,設置私有做用域。
1 function foo(a) { 2 function bar(a){ 3 i=3; 4 console.log(a+i); 5 } 6 (function(){ 7 for(var i=0;i<10;i++){ 8 bar(i); 9 } 10 })(); 11 } 12 foo(3); //3 4 5 6 7 8 9 10 11 12
(2)使用es6中的let
let關鍵字爲其聲明的變量隱式地劫持了所在的做用域,上述例子能夠改爲:
1 function foo(a) { 2 function bar(a){ 3 i=3; 4 console.log(a+i); 5 } 6 for(let i=0;i<10;i++){ 7 bar(i); 8 } 9 } 10 foo(3); //3 4 5 6 7 8 9 10 11 12
(3)es6中const也會建立塊級做用域。
const能夠建立塊級做用域,可是他表示常量。修改const建立的變量的值會報錯。
1 var foo=true; 2 3 if(foo){ 4 var a=2; 5 const b=3; 6 7 a=3;//正常 8 b=4;//錯誤 9 } 10 11 console.log(a); //3 12 console.log(b); //b is not defined