變量的作用域:
1.不在任何函數內定義的變量具有全局性,實際上JavaScript默認有一個全局對象window,全局作用域的變量實際上綁定成了window的一個屬性
2.不在函數中定義的函數(頂層函數),其實也就是window的一個屬性。
var a = "我是一個全局變量";
console.log(a);//"我是一個全局變量"
console.log(window.a);//"我是一個全局變量"
var func1 = function(){
console.log('hello world');
}
func1();//'hello world'
window.func1();//'hello world'
變量提升:
1.JavaScript的函數有個特點,就是會先掃描整個函數的語句,將其中的變量自動提升到函數的頂部。
先給個代碼大家看看會輸出什麼?
function func2(){
var a = 0;
console.log('a'=a);
console.log('b'=b);
var b = 1;
}
肯定有人覺得這個函數肯定會報錯,因爲b都還沒聲明就已經在使用了。其實輸出結果是
a = 0
b = undefine
說明JavaScript引擎將變量的申明進行了提升,但是注意,這裏僅僅是申明進行了提升,並沒有把賦值也提升。所以這裏b是undefined,而不是1.
名字空間:
1.我們知道全局變量會自動綁定到window對象上面。那麼如果有多個js文件其中出現了相同的變量名,並且都是全局變量,那麼就會導致命名衝突,並且不容易找出錯誤。所以名字空間就起作用了。
2.名字空間是將自己的所有變量和函數全部綁定到一個全局變量中。這樣就能夠保證不會出現命名衝突。
例如:
var MYAPP={}; //唯一的全局變量
MYAPP.name='myapp'; //將name這個變量變成MYAPP的屬性
MYAPP.version=1.0;
MYAPP.foo=function(){ //將foo函數放到MYAPP中,成爲它的屬性
return 'foo';
};
var name='haha';
var foo1=function(){
return '全局foo1';
}
MYAPP.foo1=function(){
return '被綁定在MYAPP中的foo1';
};
console.log(MYAPP.foo()); //'foo'
console.log(MYAPP.name); //'myapp'
console.log(name); //'haha'
console.log(foo1()); //'被綁定在MYAPP中的foo1'
//許多著名的JavaScript庫都是這樣做的:jQuery,YUI,underscore等
塊級作用域:
由於在JavaScript中變量作用域實際上是函數內部,所以例如在for循環中定義的變量,在外部依然可以引用。
例如:
function foo(){
for(var i=0;i<10;i++){
//
}
console.log(i); //此時還是會獲取到i的值,9
}
所以在ES6中引入了let這個關鍵字,用let代替var可以創造一個塊級作用域的變量
例如:
function foo(){
for(let i=0;i<10;i++){
//
}
console.log(i);// i is not defined
}
es6中還引入了一個定義常量的關鍵字 const:
在es6之前定義常量都是全部大寫,來提示這是一個常量,但是這個常量還是可變的,並不像java中的final關鍵字。所以es6引入了一個新關鍵字,和java的final一樣,就是const。專門用來定義常量。用const定義的變量不可以修改
例如:
const PI = 3.14;
PI = 6;//給PI重新賦值,有的瀏覽器會報錯,有的不報錯,但是修改之後沒效果
console.log(PI); //3.14
注意:
const和let都是具有塊級作用域的。個人覺得以後能用let的就不用var了。