JavaScript之做用域

     幾乎全部的編程語言都有做用域的概念,並且理解該門語言做用域是掌握這門語言的必經之路。若是你要訪問某個變量或函數,做用域則決定了你可否訪問到,換句話說做用域控制着變量與函數的可見性和生命週期。javascript

    記得剛剛學js的時候(其實當時壓根沒怎麼學js,按照對Java的理解就直接開始用了),對於js的做用域這塊徹底是按照Java的做用域來理解的,結果就這樣寫點簡單的js倒也沒有太大的問題,可是後來業務愈來愈複雜,須要寫的js也愈來愈複雜,就發現js的做用域和Java的不同呢!(對於Java和JavaScript之間的關係還有疑問的同窗,只須要記住這兩種語言的共同點就是名字都含有Java就是了。)那麼js的做用域是怎麼的樣呢?下面咱們就說道說道。html

    在js裏面,以函數來分隔做用域,又稱函數做用域: 做用域在函數內修改。 如:java

function scopeFunc(){
	for(var i=0;i<5;i++){
		//console.log(i);
	}
	console.log(i);
}
scopeFunc();//5
//若是js有塊級做用域,那麼在for循環外應該是取不到i的值的,應該報錯,可是咱們照樣取到了i的值;這裏的i是局部變量

function scopeFunc2(){
	for(let i=0;i<5;i++){
		//console.log(i);
	}
	console.log(i);
}
scopeFunc2();//i is not defined
//在ES6(ES2015)以前,咱們看到js是沒有塊級做用域的,可是ES6新有的定義變量的let關鍵字,能夠定義塊級做用域

function Student(name){
	console.log(name);//ly
	var score;
	console.log(score);//undefined
	console.log(age);//ReferenceError: age is not defined
}
Student('ly');
console.log(name);//undefined;函數參數只在函數內起做用,是局部變量。
//咱們看到在函數內使用一個定義了可是未賦值的變量的時候,提示undefined,使用一個未定義的變量時提示出錯了。

//scopeFunc是函數的句柄,在js中,對象和函數一樣也是變量,此處,scopeFunc是全局函數,也是全局變量了
setTimeout(scopeFunc,500);
//setTimeout這裏用的是函數的句柄,若是寫成setTimeout(scopeFunc(),500);會形成內存泄露

/*
最外層函數和在最外層函數外面定義的變量擁有全局做用域,因此聲明全局變量比較簡單,不過有種特殊的狀況,在函數內,
若是不使用var聲明,直接給變量賦值,這個變量直接就擁有全局做用域
*/
function wholeScopeFn(){
	testw='imwhole';//若是不使用var聲明變量,此處就至關因而window.testw='imwhole';
	var testpart='impart';
	console.log(testpart);
}
console.log(testw);//ReferenceError: testw is not defined 
wholeScopeFn();//impart
console.log(testw);//imwhole
/*
全局變量咱們均可以經過window.變量名 的方式來獲取,可是當使用var聲明一個全局變量時,
建立的這個屬性是不可配置的,也就是說沒法經過delete運算符刪除,不使用var聲明的全局變量,能夠經過delete刪除
*/

//函數運行在它們被定義的做用域裏,而不是它們被執行的做用域裏
function Student(name){
	console.log(name);//ly
	var score;
	console.log(score);//undefined
	console.log(age);//ReferenceError: age is not defined
}
function myCare(){
	var age=10;
	Student('ly');
}
myCare();
//咱們看到,myCare函數內已經聲明並初始化了一個變量age,而在Student函數內,在執行到打印age變量的時候任然提示爲定義

    總結一下就是變量在函數外定義,就是全局變量。 變量在函數內聲明,就是局部變量, 只能在函數內部訪問。編程

    說了變量的做用範圍,還得說說變量的生命週期。生命週期意味着你用了當前變量以後下次用的時候他得是個什麼。簡單的說,變量在他還能被用到的時候就不會被銷燬,不能再被用到的時候就該銷燬了,生命也就走到盡頭了。如:編程語言

function scopeLife(){
	var sl=0;
	console.log(++sl);
}
var wsl=0;
scopeLife();//1
scopeLife();//1
scopeLife();//1 ;局部變量在函數執行完畢後銷燬。
console.log(++wsl);//1
console.log(++wsl);//2
console.log(++wsl);//3 ;全局變量在頁面關閉後銷燬。

    好的,咱們再來看看和做用域有關的一個有趣的地方,變量聲明提高。函數

var name='ly';
function Student(){
	console.log(name);//undefined
	var name='liuyong';
	console.log(name);//liuyong
}
//上面的代碼能夠寫成以下
var name='ly';
function Student(){
        var name;
	console.log(name);//undefined
	name='liuyong';
	console.log(name);//liuyong
}
//這樣是否是好理解得多了,當執行函數的時候,會先函數內的變量的聲明。

//若是函數內不寫var直接定義全局變量,這樣的變量是不會被提高的
function Student(){
	console.log(name);
	name='liuyong';
	console.log(name);//liuyong
}
Student();

    說到js做用域,若是不說做用域鏈,會不會顯得過低端了呢?哈哈,能夠看下這兩篇文章(JavaScript做用域鏈詳細介紹JavaScript 開發進階:理解 JavaScript 做用域和做用域鏈),我的以爲做用域鏈這塊,這兩篇文章講得挺不錯的。有什麼問題也歡迎交流。spa

相關文章
相關標籤/搜索