成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

技術人員求職必看之Javascript詞法作用域

開發 前端
本文的作者前不久參加了網易互動的招聘會,因為一道看似簡單的筆試題而不幸被刷。下面就給大家講講他的經驗教訓。

每個人都會犯錯——有時候‘孰能無過,過而能改,善莫大焉’,有時候知道自己錯了卻沒有機會更改。其實,錯了并不僅僅是錯了,做錯了,除了及時改正和彌補之外,最重要的是為自己犯的錯承擔所有責任。

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

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

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}

以上代碼片段雖然能夠得到相同的結果,但***不要那樣寫啦,習慣不好,代碼不好維護。

重申一下本文的重點:

函數在定義它們的作用域里運行,而不是在執行它們的作用域里運行。

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

【編輯推薦】

  1. 淺談Javascript中的eval與with
  2. 詳解Javascript trim()函數實現
  3. 應用最廣的十大Javascript框架
責任編輯:彭凡 來源: 軟件園
相關推薦

2014-01-23 11:11:31

2012-09-20 09:31:41

技術技術人員技術開發

2017-09-14 17:12:58

2013-09-05 10:07:34

javaScript變量

2009-04-17 10:13:05

技術人員晉升職場

2009-10-14 10:18:53

薪酬

2009-12-25 14:17:36

ADO錯誤

2012-01-13 15:48:21

IT技術人員

2013-08-06 15:16:27

技術人創業開發者創業移動互聯網創業

2012-05-10 10:23:10

技術人員開發

2020-09-22 15:30:19

技術研發思維

2013-06-20 09:28:24

2013-08-06 09:42:59

技術人員面試

2018-10-09 10:57:48

技術KPI考核

2009-12-24 17:11:09

ADO與RDO

2010-08-09 17:08:13

IT技術人

2013-09-30 10:16:32

博客技術人員

2011-05-07 15:08:21

2010-01-13 16:54:29

C++測試

2009-12-25 13:37:09

退出Vi返回到shel
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产成人精品一区二区三区网站观看 | 91精品国产欧美一区二区 | 亚洲成人99 | 免费成人高清在线视频 | 91视频在线网站 | 久久精品国产一区二区电影 | 久久一| 精品欧美一区二区三区免费观看 | 一区二区欧美在线 | 一区二区av | 日韩在线小视频 | 日韩中文字幕免费在线 | 久久午夜国产精品www忘忧草 | 日本爱爱视频 | 久久成人一区 | 精品久久久久久亚洲精品 | 国产视频中文字幕 | 在线看亚洲 | 欧美精品区 | 欧美大片久久久 | 国产黄色av电影 | 国产精品美女一区二区三区 | 国产高清精品一区 | 欧美v在线 | 国产美女在线播放 | a亚洲精品 | 国产精品欧美一区二区三区不卡 | 欧美一区二区三区国产 | 亚洲激情网站 | 久久久久久久久久一区二区 | 91一区二区 | 亚洲国产欧美日韩 | 色综合久 | 午夜精品久久久久久久久久久久久 | 成人国内精品久久久久一区 | 亚洲狠狠| 亚洲永久精品国产 | 亚洲欧美一区二区三区在线 | 91中文字幕在线 | 天天操天天干天天透 | 亚洲国产成人av好男人在线观看 |