1. var bb = 1;
function aa(bb) {
bb = 2;
};
aa();
console.log(bb );
2. var bb = 1;
function aa() {
bb = 2;
};
aa();
console.log(bb );
你覺得會輸出什么呢谷誓,想必很多人和我一樣認(rèn)為會輸出2 2
答案應(yīng)該是1 2,為什么呢?
首先我們先來看一下作用域
1.js編程環(huán)境的頂級作用域是window對象下的范圍爷光,稱為全局作用域峻贮,全局作用域中的變量稱為全局變量席怪。
注意:代碼的任何位置隱士聲明(不用var),都是全局變量纤控,具有全局作用域挂捻。
2.js函數(shù)內(nèi)的變量無法在函數(shù)外面訪問,在函數(shù)內(nèi)卻可以訪問函數(shù)外的變量船万,函數(shù)內(nèi)的變量稱為局部變量刻撒。
3.js函數(shù)可以嵌套,多個函數(shù)的層層嵌套構(gòu)成了多個作用域的層層嵌套耿导,這稱為js的作用域鏈声怔。
4.js作用域鏈的變量訪問規(guī)則是:如果當(dāng)前作用域內(nèi)存在要訪問的變量,則使用當(dāng)前作用域的變量舱呻,否則到上一層作用域內(nèi)尋找醋火,直到全局作用域,如果找不到,則該變量為未聲明胎撇。
全局變量和局部變量
全局變量:變量在全局聲明介粘,或者在代碼的任何位置隱士聲明(不用var),則該變量在全局可見
局部變量:變量在函數(shù)內(nèi)顯示申明(使用var),則在該函數(shù)內(nèi)可見”
具體的全局變量和局部變量在內(nèi)存中的區(qū)域
http://www.reibang.com/p/b42715694c80
知道了作用域晚树,我們就可以看一下這道題啦
第一個例子
在函數(shù)aa里面?zhèn)髁艘粋€參數(shù)bb,bb變成了函數(shù)的局部變量姻采,也就是相當(dāng)于在函數(shù)體內(nèi)聲明了var bb,再去改變bb的值爵憎,bb的值在函數(shù)里面就變成了2慨亲,但是這個變化不會影響到外部作用域下的bb,因此,全局變量bb的值還是1
第二個例子
在函數(shù)內(nèi)部直接給bb賦值宝鼓,并沒有var刑棵,此時bb是一個全局變量愧驱,給函數(shù)里面的bb賦值淆珊,相當(dāng)于在函數(shù)內(nèi)部重新將bb申明了一遍,并且是以全局變量的形式申明的摸柄。因此bb會輸出2.
參數(shù)的傳遞是按值類型還是引用類型傳遞的
上面的例子是參數(shù)為基本類型的值沥寥,那么向參數(shù)傳一個對象會怎么樣呢碍舍?看下面這個例子
function setName(obj) {
obj.name = "Nicholas";
}
var person = new Object();
setName(person);
alert(person.name);
這端代碼會輸出Nicholas,看到這個結(jié)果邑雅,很多人會認(rèn)為片橡,在局部作用域中修改的對象會在全局作用域中反映出來,就說明參數(shù)是按引用傳遞的淮野,其實(shí)不是這樣的捧书, 我們可以看一下下面這個例子。
function setName(obj) {
obj.name = "Nicholas";
obj = new Object();
obj.name = "Greg";
}
var person = new Object();
setName(person);
alert(person.name);
這個會輸出Nicholas骤星,而不是Greg经瓷。
其實(shí)是這樣的,如果person是按引用傳遞的洞难,obj是person的引用舆吮,obj指向一個新對象,那么person就會自動被修改為指向其name屬性值為"Greg"的新對象廊营。實(shí)際上歪泳,當(dāng)在函數(shù)內(nèi)部重寫obj時萝勤,這個變量引用的就是一個局部對象了露筒。而這個局部對象會在函數(shù)執(zhí)行完畢后立即被銷毀。下面敌卓,我們就用圖示來看一下
首先 person將指向堆的地址賦給obj慎式,此時,obj也指向了同一塊地址空間。
但是當(dāng)obj指向了堆中的另一塊空間(new Object)的時候瘪吏,obj里面存的指向堆的地址沒有變化癣防,因此他還是指向之前的空間(Object)
因此我們得出結(jié)論