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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 前端技术 > javascript >内容正文

javascript

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

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

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

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

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

先給出五個(gè)例子:

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

例一: 答案

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);

寫在答案前面的話:

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

JS代碼在解釋執(zhí)行前,會(huì)對(duì)進(jìn)行一次“預(yù)編譯”:

在預(yù)編譯的過程中,用var聲明的變量被設(shè)置為活動(dòng)對(duì)象(啥是活動(dòng)對(duì)象?)的屬性,默認(rèn)值為“undefined”,

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

變量初始化過程即賦值過程發(fā)生在解釋執(zhí)行期,而不是"預(yù)編譯期"。

例一答案:

有人大概會(huì)犯下面兩種情況的錯(cuò)誤:

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

這說明你對(duì)JavaScript 中沒有塊級(jí)作用域不太理解。請(qǐng)翻翻基礎(chǔ)書籍。筆者也會(huì)在后續(xù)的博文中 深入淺出地介紹JavaScript 變量、作用域和內(nèi)存問題。(到時(shí)候會(huì)給出鏈接的)

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

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

但是你還是對(duì)JS代碼執(zhí)行前的情況不太了解。

真正的情況是這樣的:

JS在預(yù)編譯的時(shí)候,var 聲明的變量 被設(shè)置為活動(dòng)對(duì)象(本例為 window )的屬性,默認(rèn)值是‘undefined’,

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

例二答案:

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

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

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

第一行是一個(gè)變量的聲明。

第二行是函數(shù)字面量(函數(shù)表達(dá)式,詳細(xì)用法請(qǐng)參見:深入淺出 JavaScript 函數(shù) v 0.5),只不過該表達(dá)式?jīng)]有省略函數(shù)名(a),為什么不省略呢? 因?yàn)樵摵瘮?shù)要遞歸啊,不然咋遞歸?

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

針對(duì)本例還有一種說法是 逗號(hào)操作符,不知道是順序的還是倒序的,但是針對(duì)本例,順序還是逆序,真沒什么關(guān)系。

例三答案:

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

錯(cuò)誤的原因就是不太了解JS的預(yù)編譯過程。

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

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

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

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

例四答案:

理解本例的關(guān)鍵在于對(duì)參數(shù)對(duì)象的理解,arguments 的詳細(xì)介紹,在深入淺出 JavaScript 函數(shù) v 0.5中有詳細(xì)的介紹。

arguments 是一個(gè)特殊的對(duì)象,有數(shù)組的特性,但不是數(shù)組,arguments 對(duì)象不是只讀的,arguments [2] = 10;?

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

arguments [2] 和 a 指向的是同一個(gè)值。

例五答案:

a 作為一個(gè)函數(shù),在JS中函數(shù)也是對(duì)象,對(duì)象當(dāng)然有屬性和方法了。

JavaScript 就為函數(shù)對(duì)象提供了兩個(gè)間接調(diào)用函數(shù)的方法 call() 和apply(),這兩個(gè)內(nèi)容的詳細(xì)解釋在深入淺出 JavaScript 函數(shù) v 0.5中有詳細(xì)的介紹。

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

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

第一個(gè)參數(shù)是函數(shù)要執(zhí)行的作用域,本例中傳入null ,就是說函數(shù)的執(zhí)行沒有作用域的跳轉(zhuǎn),還是在聲明函數(shù)的作用域中執(zhí)行。

函數(shù)聲明的作用域?qū)ο鬄?window 對(duì)象,所以對(duì)話框彈出 [Object Window] 。

本例中涉及的 this 的用法,請(qǐng)參見深入淺出 JavaScript 函數(shù) v 0.5?。

寫在后面的話:

什么是活動(dòng)對(duì)象?

當(dāng)函數(shù)被調(diào)用,活動(dòng)對(duì)象(activation object) 就被創(chuàng)建了。它包含普通參數(shù)(formal parameters) 與特殊參數(shù)(arguments)對(duì)象(具有索引屬性的參數(shù)映射表)。

活動(dòng)對(duì)象在函數(shù)上下文中作為變量對(duì)象使用。

預(yù)編譯階段,匿名函數(shù)將不會(huì)被解析。這句話的理解:

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

例子:?

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

廣了個(gè)告::(祝大家勞動(dòng)節(jié)快樂,為我們這些勞動(dòng)者鼓掌)

更過關(guān)于函數(shù)的內(nèi)容,盡在?深入淺出 JavaScript 函數(shù) v 0.5

?

總結(jié)

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

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。