日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

五个小例子教你搞懂 JavaScript 作用域问题

發布時間:2023/12/15 javascript 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 五个小例子教你搞懂 JavaScript 作用域问题 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
原文:五個小例子教你搞懂 JavaScript 作用域問題

眾所周知,JavaScript 的作用域和其他傳統語言(類C)差別比較大,掌握并熟練運用JavaScript 的作用域知識,不僅有利于我們閱讀理解別人的代碼,也有助于我們編寫自己的可靠代碼。

下面筆者將使用五個小例子來給大家分析下 JavaScript 的作用域要注意的問題。

感謝?例子的來源?(這5個例子我做錯了2個 [嘿嘿,盡情鄙視吧],筆者就是要?死磕自己,奉獻大家!)

先給出五個例子:

每個例子旁邊都會給出答案的鏈接,如果你全部都正確了,你可以忽略這篇短文,并深深的鄙視下筆者。

例一: 答案

if (!("a" in window)) {var a = 1; } alert (a);

?例二:答案

var a = 1,b = function a (x) {x && a (--x);}; alert (a);

?例三:答案

function a (x) {return x * 2; } var a; alert (a);

?例四:答案

function b (x, y, a) {arguments[2] = 10;alert (a); } b(1, 2, 3);

?例五:答案

function a () {alert (this); } a.call (null);

寫在答案前面的話:

頁面中JavaScript代碼在加載的時候,執行順序是按照腳本標簽<script>的順序一致的,但如果設置該標簽async或defer屬性的話,則不能保證執行順序(這點說起來慚愧,筆者沒有認真測試過)。

JS代碼在解釋執行前,會對進行一次“預編譯”:

在預編譯的過程中,用var聲明的變量被設置為活動對象(啥是活動對象?)的屬性,默認值為“undefined”,

以function定義的函數也被添加為活動對象的屬性,它們的值就是函數的定義,匿名函數將不被解析(這句話啥意思?)。

變量初始化過程即賦值過程發生在解釋執行期,而不是"預編譯期"。

例一答案:

有人大概會犯下面兩種情況的錯誤:

情況一:if 分支里聲明a變量(var a = 1;),在if 外訪問不到變量a,所以對話框彈出 'undefined'。

這說明你對JavaScript 中沒有塊級作用域不太理解。請翻翻基礎書籍。筆者也會在后續的博文中 深入淺出地介紹JavaScript 變量、作用域和內存問題。(到時候會給出鏈接的)

情況二:a 變量,不在window對象中,所以進入if 分支,聲明 a 并賦值為 1,又由于JS沒有塊作用域,所以對話框彈出 1。

這說明你大概了解塊作用域(可能只是知道,但并不知道原理)。這時候你可能需要了解下啥是作用域鏈,多問問為什么沒有塊作用域(后續博文會推出的,但筆者仍希望你通過讀書的方式了解下)。

但是你還是對JS代碼執行前的情況不太了解。

真正的情況是這樣的:

JS在預編譯的時候,var 聲明的變量 被設置為活動對象(本例為 window )的屬性,默認值是‘undefined’,

由于沒有塊作用域,所以if 塊中的 變量聲明被預編譯了,因此 a 是window的屬性 (a in window is true ) ,于是就能理解對話框彈出 'undefined'.

例二答案:

錯誤的情況我就不多做介紹了,無非是彈出函數b的定義,或者彈出1。

下面解釋下本例的情況,本例的代碼執行和下列代碼執行是一樣的:

var a = 1; var b = function a (x) {x && a (--x); }; alert (a);

第一行是一個變量的聲明。

第二行是函數字面量(函數表達式,詳細用法請參見:深入淺出 JavaScript 函數 v 0.5),只不過該表達式沒有省略函數名(a),為什么不省略呢? 因為該函數要遞歸啊,不然咋遞歸?

但是殘酷的是,函數名在函數外部是未定義的,所以對話框彈出的是 1 。

針對本例還有一種說法是 逗號操作符,不知道是順序的還是倒序的,但是針對本例,順序還是逆序,真沒什么關系。

例三答案:

本例錯誤的大部分情況都是彈出'undefined'.

錯誤的原因就是不太了解JS的預編譯過程。

本例中JS的預編譯過程是這樣的,首先聲明變量 a (并未初始化喲),然后再初始化為function, 后面 var a ; 只是聲明變量,但是并未給a 賦值,所以其值還是function。

拿下面一段代碼做比較,可以印證上面的解釋:

function a (x) {return x * 2; } var a = 10; alert (a);

誰最后對同一個變量初始化(可以理解成賦值),最后變量就保留誰的值。

例四答案:

理解本例的關鍵在于對參數對象的理解,arguments 的詳細介紹,在深入淺出 JavaScript 函數 v 0.5中有詳細的介紹。

arguments 是一個特殊的對象,有數組的特性,但不是數組,arguments 對象不是只讀的,arguments [2] = 10;?

這句話就把參數 a (其實可以理解成是函數的內部變量) 更改為10,所以彈出 10。

arguments [2] 和 a 指向的是同一個值。

例五答案:

a 作為一個函數,在JS中函數也是對象,對象當然有屬性和方法了。

JavaScript 就為函數對象提供了兩個間接調用函數的方法 call() 和apply(),這兩個內容的詳細解釋在深入淺出 JavaScript 函數 v 0.5中有詳細的介紹。

call () 方法的語法是這樣的:

call([thisObj[,arg1[, arg2[, [,.argN]]]]]) // thisObj 是this要綁定的對象,后面是逗號分隔開的參數

第一個參數是函數要執行的作用域,本例中傳入null ,就是說函數的執行沒有作用域的跳轉,還是在聲明函數的作用域中執行。

函數聲明的作用域對象為 window 對象,所以對話框彈出 [Object Window] 。

本例中涉及的 this 的用法,請參見深入淺出 JavaScript 函數 v 0.5?。

寫在后面的話:

什么是活動對象?

當函數被調用,活動對象(activation object) 就被創建了。它包含普通參數(formal parameters) 與特殊參數(arguments)對象(具有索引屬性的參數映射表)。

活動對象在函數上下文中作為變量對象使用。

預編譯階段,匿名函數將不會被解析。這句話的理解:

一句話,函數聲明在"預編譯階段"被解析,函數字面量(函數表達式) 在執行階段被解析。

例子:?

alert (add (2,3)); //5 function add(a,b) {return a+b; } // 函數聲明提升 //=====為了方便,筆者寫在了一起,在測試的時候,可不要在一個作用域中執行喲=============== alert (add (2,3)); //error var add = function (a,b) {return a+b; }; //函數字面量,注意結尾的分號喲(細節很重要)。

廣了個告::(祝大家勞動節快樂,為我們這些勞動者鼓掌)

更過關于函數的內容,盡在?深入淺出 JavaScript 函數 v 0.5

?

總結

以上是生活随笔為你收集整理的五个小例子教你搞懂 JavaScript 作用域问题的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。