前言
上次??途W(wǎng)做到這樣一個(gè)題,非常有意思,陷阱非常多,當(dāng)時(shí)覺得搞明白了,現(xiàn)在再看到,又糊涂了,發(fā)現(xiàn)了新的點(diǎn),看一下:
var foo={n:1}; (function (foo) { console.log(foo.n); foo.n = 3; var foo = {n:2}; console.log(foo.n); })(foo); console.log(foo.n);
乍一看,是局部和全局變量的一些區(qū)分問題,其實(shí)坑很多,下面我們一點(diǎn)點(diǎn)分析下;
變量的定義(宣告)和賦值
首先我們看一段代碼:
var a = 1; var a; console.log(a);//1
這里第二行對(duì)a是一個(gè)重復(fù)宣告,而不是賦值,變量只有定義(宣告)后未賦值的情況下才會(huì)輸出undefined,除非手動(dòng)賦值undefined;那么這里,JS引擎對(duì)于重復(fù)宣告的規(guī)定以最近的變量指定(也就是賦值)作為變量在執(zhí)行時(shí)的值,所以第二行的var a;其實(shí)相當(dāng)于無效;
函數(shù)中形參和局部變量同名
在我們自己寫代碼時(shí),一般不會(huì)做這種蠢事情,把形參和局部變量定義為同名,可如果真的這樣做了呢?
那就要分析下JS執(zhí)行上下文中的變量對(duì)象了,這個(gè)知識(shí)點(diǎn)不牢固的同學(xué)可以移步這里:重拾ECMAScript基礎(chǔ)——變量、作用域;
作用域鏈對(duì)變量的保存都是在變量對(duì)象中的,那么ES5對(duì)形參在變量對(duì)象中是如何保存的呢,請看規(guī)范:
10.5 Declaration Binding Instantiation
Every execution context has an associated VariableEnvironment. Variables and functions declared in ECMAScript code evaluated in an execution context are added as bindings in that VariableEnvironment‘s Environment Record. For function code, parameters are also added as bindings to that Environment Record.
就是說,無論是形參還是函數(shù)中聲明的變量,JS對(duì)他們的處理是沒有區(qū)別的,都是保存在這個(gè)函數(shù)的變量對(duì)象中作為局部變量進(jìn)行處理;那么結(jié)合上面我們說到的變量的重復(fù)宣告,接下來同名的問題就很簡單了,看代碼:
(function fun (param) { var param; console.log(param);//1 param = 2; console.log(param);//2 })(1);
在這里,同名的局部變量和形參其實(shí)是同一個(gè)東西,都是在函數(shù)的變量對(duì)象里的保存的那個(gè)變量;
如果變量是引用類型呢?
那么如果變量是個(gè)對(duì)象的話,就是我們文章一開始提到的題目了,下面我們分析下:
var foo = {n : 1}; (function(foo) { console.log(foo.n); foo.n = 3; var foo = {n : 2}; console.log(foo.n); })(foo); console.log(foo.n);
var foo = {n : 1}; function fun(foo) { var foo; console.log(foo.n); foo.n = 3; foo = {n : 2}; console.log(foo.n); }; fun(foo); console.log(foo.n);
上下兩段代碼,意思是一樣的,我把匿名立即執(zhí)行函數(shù)換成了普通函數(shù)并在下一行調(diào)用,方便大家理解;
其實(shí)分析一下,就是這么幾個(gè)問題;
內(nèi)部foo變量提升;
內(nèi)部foo和形參同名;
內(nèi)部foo重復(fù)宣告;
所以內(nèi)部var的那個(gè)foo和形參foo是同一個(gè)東西,并沒有發(fā)生變化;
然后重復(fù)宣告不影響之前的賦值,所以第一個(gè)為1;
接下來,foo.n=3,由于形參為對(duì)象,所以是傳進(jìn)來的是一個(gè)對(duì)象的引用(指針);
對(duì)這塊知識(shí)點(diǎn)不牢固的同學(xué)還是請移步我之前那篇文章;
那么這個(gè)引用指向的堆內(nèi)存的那塊空間里的n改變?yōu)?;
接下來,foo={n:2};這個(gè)就很有意思了,我們剛才也說了,傳進(jìn)來的是個(gè)引用;
現(xiàn)在給這個(gè)引用賦值,實(shí)際上就是讓它指向新開辟的空間,存放著{n:2}這個(gè)對(duì)象;
那么之前的引用就斷掉了,也就是說形參foo已經(jīng)不指向全局里那個(gè)foo指向的空間了;
固然,在函數(shù)里,會(huì)輸出新空間里的2;
而在函數(shù)外,舊空間仍然沒有改變,故為3;
總結(jié)
其實(shí)這個(gè)題目考了很多知識(shí)點(diǎn),最后就是參數(shù)傳遞中引用類型的用法,這個(gè)也是ECMAScript中基礎(chǔ)的一個(gè)難點(diǎn),結(jié)合前面的一些,變量提升,重復(fù)宣告,形參與局部變量同名,算是解釋清楚了。
若有錯(cuò)誤,歡迎指出。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/108588.html
摘要:延長作用域鏈下面兩種語句可以在作用域鏈的前端臨時(shí)增加一個(gè)變量對(duì)象以延長作用域鏈, 問題 今天看筆記發(fā)現(xiàn)自己之前記了一個(gè)關(guān)于同名標(biāo)識(shí)符優(yōu)先級(jí)的內(nèi)容,具體是下面這樣的: 形參優(yōu)先級(jí)高于當(dāng)前函數(shù)名,低于內(nèi)部函數(shù)名 形參優(yōu)先級(jí)高于arguments 形參優(yōu)先級(jí)高于只聲明卻未賦值的局部變量,但是低于聲明且賦值的局部變量 函數(shù)和變量都會(huì)聲明提升,函數(shù)名和變量名同名時(shí),函數(shù)名的優(yōu)先級(jí)要高。執(zhí)行代...
摘要:函數(shù)使用它們實(shí)參的值來計(jì)算返回值,稱為該函數(shù)調(diào)用表達(dá)式的值。通常函數(shù)名的第一個(gè)字符為小寫。在函數(shù)內(nèi)部定義的變量,外部無法讀取,稱為局部變量。注意對(duì)于命令來說,局部變量只能在函數(shù)內(nèi)部聲明,在其他區(qū)塊中聲明,一律都是全局變量。 函數(shù) 1.函數(shù)簡介 通過函數(shù)可以封裝任意多條語句,而且可以在任何地方、任何時(shí)候調(diào)用。 ECMAScript中的函數(shù)使用function關(guān)鍵字來聲明,后跟一組參數(shù)以及...
摘要:函數(shù)函數(shù)的概述所謂函數(shù)就是只被定義一次但可能被執(zhí)行或調(diào)用多次變量與函數(shù)的區(qū)別變量存的是數(shù)據(jù)內(nèi)容而函數(shù)存的是語句塊定義函數(shù)備注定義函數(shù)時(shí)函數(shù)體的內(nèi)容不會(huì)被執(zhí)行調(diào)用函數(shù)時(shí)函數(shù)體才被執(zhí)行注意一般以個(gè)函數(shù)就去完成一個(gè)功能函數(shù)聲明方式語法函數(shù)名稱 函數(shù) 函數(shù)的概述 所謂函數(shù)就是只被定義一次,但可能被執(zhí)行或調(diào)用多次 變量與函數(shù)的區(qū)別: 變量存的是數(shù)據(jù)內(nèi)容而函數(shù)存的是語句塊 定義函數(shù) 備注: ...
摘要:因?yàn)榧词拱似渌拇a,也只會(huì)下載并執(zhí)行屬性內(nèi)的外部腳本文件,嵌入的額外代碼會(huì)被忽略。在腳本中,如果程序員在對(duì)某個(gè)變量賦值之前未聲明,賦值操作將自動(dòng)聲明該變量。共有中數(shù)據(jù)類型。阻止事件冒泡火狐瀏覽器創(chuàng)建元素添加子元素刪除子元素?cái)?shù)組拼接方法 所有的web開發(fā)都是【請求】+【響應(yīng)】 推薦JavaScript中使用單引號(hào)引用字符串,HTML中使用雙引號(hào),防止沖突 JavaScript代碼...
摘要:函數(shù)函數(shù)是什么函數(shù)是這樣的一段代碼它只定義一次但可能被執(zhí)行或調(diào)用多次簡單來說函數(shù)就是一組可重用的代碼可以在程序的任何地方調(diào)用定義函數(shù)函數(shù)聲明方式定義函數(shù)時(shí)函數(shù)體的內(nèi)容是不會(huì)被執(zhí)行的這是一個(gè)函數(shù)字面量直接量方式這是一個(gè)函數(shù)調(diào)用函數(shù)定義一個(gè)函數(shù) 函數(shù) 函數(shù)是什么 函數(shù)是這樣的一段JavaScript代碼 它只定義一次 但可能被執(zhí)行或調(diào)用多次簡單來說 函數(shù)就是一組可重用的代碼 可以在程序的任...
閱讀 2655·2021-09-26 10:13
閱讀 6186·2021-09-08 10:46
閱讀 752·2019-08-30 15:53
閱讀 3025·2019-08-29 16:13
閱讀 2814·2019-08-26 12:23
閱讀 3538·2019-08-26 11:24
閱讀 1186·2019-08-23 18:09
閱讀 1082·2019-08-23 17:08