【轉】javascript:with的用法以及延長做用域鏈

原文連接:https://www.cnblogs.com/zz334...javascript

《Javascript高級程序設計(第二版)》第66頁中提到:「因爲with語句的變量對象是隻讀的,結果url就成了函數執行環境的一部分,於是能夠做爲函數的值被返回。」,不知道誰看完以爲一頭霧水?html

第三版中75頁則更是難懂:「至於with語句內部,則定義了一個url的變量,所以url就成了函數執行環境的一部分,因此能夠做爲函數的值被返回」java

首先來看看他舉的例子:函數

function buildUrl(){  
     var qs="?debug=true";  
     with(location){  
          var url=href+qs;  
     }  
     return url;  
}  
var result=buildUrl();  
  
alert(result);

若是你沒讀過着本書,而且須要學習javascript,請思考並嘗試運行該例子。
最後彈出的不是undefined,而是你的靜態頁地址+qs的值。學習

來看一下with語句的做用:ui

通俗的說,就是引用對象,並對該對象上的屬性進行操做,其做用是能夠省略重複書寫該對象名稱,起到簡化書寫的做用。url

可是有幾個問題須要注意:debug

一、with代碼塊中,javascript引擎對變量的處理方式是:先查找是否是該對象的屬性,若是是,則中止。若是不是繼續查找是否是局部變量。(在《Javascript高級程序設計(第二版)》中提到的觀點,跟這一點剛好相反,可是實例可證實其是錯誤的,會在接下來介紹)設計

二、就算在with語句中使用 var 運算符從新定義變量(該變量是with引用對象的屬性),若是該屬性是可寫屬性,那麼也會給對象的屬性賦值。code

三、若是你想經過with語句,對引用對象添加多個屬性,併爲每一個屬性賦值,這是不可能的!也就是說,要賦值的只能是對象已經存在而且能夠寫入的屬性(不能是隻讀屬性)。

再來看看開頭提到的那句話

「因爲with語句的變量對象是隻讀的,結果url就成了函數執行環境的一部分,於是能夠做爲函數的值被返回。」

反過來:若是with語句的變量對象是可寫入的…… 剛纔第3點提過,不能給對象寫入原來不存在的屬性,先這樣理解,下面還有另外的含義。

那延長做用域鏈又是怎麼回事?

通常的,「因爲with語句塊中做用域的‘變量對象’是隻讀的,因此在他本層定義的標識符,不能存儲到本層,而是存儲到它的上一層做用域」。這裏又要理解有一層「只讀」的含義。

在Javascript的做用域中(做用域,想一想就是函數塊,每一個函數都會有個函數名,就算是匿名函數也有個空函數名),那麼建立做用域的時候,本層的標識符就能夠寄託在這個做用域下,而with語句塊中做用域的‘變量對象’是隻讀的,不能存儲標識符,只能存儲在其上一層,這就是延長做用域鏈。其實,這和上面說的不能給對象添加屬性有同工之處。

其實,徹底能夠這樣理解,在Javascript中,沒有塊級做用域,就是說除了函數,其餘的塊級代碼都沒有本身的做用域。

如今說一下以前提到的with代碼塊中變量處理方式的問題

用事實說話:

var o={href:"sssss"};  
var href="1111";  
function buildUrl(){  
     var qs="?debug=true";       
     with(o){  
          href="2222";  
          var url=href+qs;  
     }      
     return url;  
}  
var result=buildUrl();  
alert(result);  //2222?debug=true
alert(href);  //1111

很明顯,with語句中並無更改變量href的值,而是更改了 o 對象的 href 屬性。

就是說,with中首先查找的是相關對象的屬性,若是沒有,才改變變量的值。

將以上例子o對象的href屬性去掉

var o={};  
var href="1111";  
function buildUrl(){  
     var qs="?debug=true";       
     with(o){  
          href="2222";  
          var url=href+qs;  
     }      
     return url;  
}  
var result=buildUrl();  
alert(result);  //2222?debug=true
alert(href); //2222
相關文章
相關標籤/搜索