国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > JavaScript > 正文

網易JS面試題與Javascript詞法作用域說明

2019-11-21 00:08:48
字體:
來源:轉載
供稿:網友
調用對象位于作用域鏈的前端,局部變量(在函數內部用var聲明的變量)、函數參數及Arguments對象都在函數內的作用域中――這意味著它們隱藏了作用域鏈更上層的任何同名的屬性。

2010年9月14日,我去參加網易網頁工程師招聘會,應聘JS工程師職位。有幸參加筆試,然后有幸栽在筆試,呵呵。廢話少說,抓出音響極深的一題重新研究研究。

題目大概是:寫出如下代碼的輸出結果并進行分析

復制代碼 代碼如下:

var tt = 'aa';
function test(){
alert(tt);
var tt = 'dd';
alert(tt);
}
test();

“太簡單了!”這是我當時看到這個題目是的第一想法,于是輕率答題竟成我的致命之傷。我的答案是――aa和dd,解析:第一次輸出全局變量的結果,然后局部變量tt覆蓋全局變量所引用的值,所以第二次輸出結果是dd。

任何人見我如此作答,都會認為我是在掃盲――想法及其幼稚(我也這么認為)!

網易啊,怎么可能會滿意于這種答案!

正確的答案應該是:undefined和dd

為什么第一次alert的結果是undefined呢?要解釋得清楚明白需要用到Javascript的詞法作用域。

Javascript中的函數“在定義它們的作用域里運行,而不是在執行它們的作用域里運行”,這是權威指南里抽象而精辟的總結。

Javascript的邏輯默認在一個全局作用域中執行,如以上程序段中的“var tt='aa';”就是定義一個全局作用域的全局變量(如果以上代碼段不是摘自某個函數鏈的話)。而test()函數內部的邏輯必須在原有的作用域(全局 作用域)鏈再添加test函數本身的作用域(局部性)――這些思想幾乎在每一種語言中都是如此定義的,然而Javascript作用域鏈的特別之處在于函 數內部能夠嵌套函數的定義(這是閉包的基礎。注:在JS中函數是唯一形式的代碼作用域)

嵌套的內部函數可以調用外部函數(被嵌套的函數)的變量和其他嵌套函數(函數是一種數據)。如果是在外部函數內調用嵌套函數,那么調用對象不變,當 外部函數執行完畢后所有數據(包括外部函數和嵌套的內部函數)都將被垃圾回收機制收集――這一點還不能體現出‘閉包'的精華。有一種情況,就是 Javascript允許外部調用嵌套的內部函數,即使被嵌套函數已經被‘垃圾收集'――最常見的就是在‘某個函數'中用其嵌套的內部函數定義某些元素的 響應事件,頁面載入的時候被嵌套函數(‘某個函數')已經執行完畢(被垃圾回收),但當事件觸發的時候仍然會有響應的動作,而且響應函數中還可能調用到在 被嵌套函數(‘某個函數')中定義的變量最終值(不是被垃圾回收了嗎?)。

關于閉包的知識和示例有很多資料可供查詢,我不想敘述。

本文的重點是以下非常重要的細節:

調用對象位于作用域鏈的前端,局部變量(在函數內部用var聲明的變量)、函數參數及Arguments對象都在函數內的作用域中――這意味著它們隱藏了作用域鏈更上層的任何同名的屬性。

即,在以上程序片段中,test函數內部的“var tt='dd'”將會致使“var tt='aa'”在test函數被調用時完全被隱藏。而且,tt是在第一個alert語句之后定義,所以在調用到第一個alert時,tt是還沒有被賦值 的。這樣說可能會清楚一點,即,在定義test函數時,當定義第一個alert(tt)時,這里會記錄tt是作用域鏈中的一個變量但不會記錄它(tt)的 值,函數定義完畢后tt就添加到作用域里,所以第一個alert語句能夠找到該作用域里的tt(即,相當于找到一個已經在函數內部聲明,但未被賦值的 tt)。

以上程序片段的執行結果與以下片段的結果相同:

復制代碼 代碼如下:

var tt = 'aa';
function test(){
var tt;
alert(tt);
tt = 'dd';
alert(tt);
}
test();

Javascript的作用域不可簡單的用C++等語言的思維來理解啊!C++在調用函數之前必須先聲明或定義,而Javascript沒必要。在 Javascript中可以先調用函數,后再定義(不用在調用之前作任何聲明)。因為在調用函數時,Javascript是向作用域鏈要函數的定義(函數在定義它們的作用域里運行,而不是在執行它們的作用域里運行)

如以上代碼寫成:
復制代碼 代碼如下:

var tt = 'aa';
test(); //先調用后再定義
function test(){
alert(tt); //undefined
var tt = 'dd';
alert(tt); //dd
}

以上代碼片段雖然能夠得到相同的結果,但最好不要那樣寫啦,習慣不好,代碼不好維護。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 措美县| 博白县| 丹寨县| 资兴市| 太康县| 江西省| 襄汾县| 房产| 蚌埠市| 额济纳旗| 樟树市| 台前县| 广水市| 吉安县| 嵊州市| 凤城市| 吉水县| 三台县| 利川市| 陕西省| 博兴县| 高平市| 察哈| 德保县| 昂仁县| 凉城县| 宁阳县| 象州县| 岚皋县| 晋宁县| 织金县| 泸水县| 高淳县| SHOW| 江口县| 江阴市| 高碑店市| 黔江区| 叙永县| 舞钢市| 晋中市|