亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

javascript執(zhí)行機(jī)制<一>

codeKK / 476人閱讀

摘要:提示,很顯然,出了循環(huán)的的大括號對應(yīng)的作用域之后,就會(huì)被自動(dòng)銷毀。那么呢,也是這樣么我們來看個(gè)例子這段代碼執(zhí)行結(jié)果是估計(jì)有人也會(huì)比較奇怪。這邊我解釋下執(zhí)行這段代碼的過程。提出了用關(guān)鍵字來代替關(guān)鍵字,具體的話可以參考阮一峰的而教程。

從一道題說起

最近又有人問我下面這道題目,題目是這樣的,首先是一個(gè)DOM結(jié)構(gòu)如下:




    
1
2
3
4
5

非常easy的dom結(jié)構(gòu),在來一小段js,如下:

var nodes = document.getElementsByTagName("div");
for(var i = 0,len = nodes.length; i < len; i++){
    nodes[i].onclick = function(){
        console.log(i);
    }
}

好了,問題來了,依次點(diǎn)擊div,結(jié)果是多少?答案并不是1,2,3,4,5,而是點(diǎn)擊任何一個(gè)div都會(huì)輸出5.

分析

先來說下為什么最后執(zhí)行的結(jié)果都是5.首先我們要明白,js中沒有塊級作用域,講人話,就是js中不存在{}這種代碼塊的東西。各位估計(jì)會(huì)反駁我說,上面例子中不是明明白白的寫的for(){}這種代碼,怎么這邊就開始說js不存在{}這種東西呢?我先舉個(gè)C++的例子吧

int arr[] = {1,2,3,4,5};
vector v = vector(arr,arr+sizeof(arr)/sizeof(int));
for(int i = 0; i < v.size(); i++){
    std::cout << i << std::endl;
}

這么寫是沒有問題的,下面我再加點(diǎn)東西

int arr[] = {1,2,3,4,5};
vector v = vector(arr,arr+sizeof(arr)/sizeof(int));
for(int i = 0; i < v.size(); i++){
    std::cout << i << std::endl;
}
std::cout << i;

這么寫,編譯器直接就報(bào)錯(cuò)了。提示 error: use of undeclared identifier "i",很顯然,出了for循環(huán)的{}的大括號對應(yīng)的作用域之后,i就會(huì)被自動(dòng)銷毀。那么JS呢,也是這樣么?我們來看個(gè)例子

for(var i = 0;i< 5;i++){
    console.log(i);
}
console.log(i);

這段代碼執(zhí)行結(jié)果是0,1,2,3,4,5.估計(jì)有人也會(huì)比較奇怪。這邊我解釋下JS執(zhí)行這段代碼的過程。
首先是變量提升,js把var i = 0;分解成兩句話,var i;i =0;并且把var i;提到最近一個(gè)function的頂部,這個(gè)時(shí)候,這段代碼就變成了這樣

var i;
for(i=0;i<5;i++){
    console.log(i);
}
console.log(i);

這樣各位對于上面執(zhí)行出來的0,1,2,3,4,5估計(jì)就沒啥疑問了。
看完這個(gè)例子之后,我也希望各位注意下我前面說的js沒有塊級作用域,以及js會(huì)做變量提升,把變量的申明提升到最近的一個(gè)function的頂部
由于js會(huì)做變量提升,自動(dòng)將變量的申明提升到最近的一個(gè)function的頂部,所以{}根據(jù)不會(huì)構(gòu)成所謂的塊級作用域,對js里面的變量而言,只有function才會(huì)是其作用域。

好了,講完js的變量提升,我們再回頭來看最開始的這個(gè)問題。首先是變量提升,提升之后我們得到

var nodes = document.getElementsByTagName("div");
var i;
for(i = 0,len = nodes.length; i < len; i++){
    nodes[i].onclick = function(){
        console.log(i);
    }
}

執(zhí)行過程中,我們對每個(gè)node[i]節(jié)點(diǎn)都綁定了一個(gè)onclick事件,但是for循環(huán)執(zhí)行的過程中,我們并沒有出發(fā)這個(gè)click事件,for循環(huán)執(zhí)行結(jié)束之后,i變?yōu)?。當(dāng)用戶點(diǎn)擊div的時(shí)候,這個(gè)時(shí)候執(zhí)行對應(yīng)的onclick函數(shù),也就是console.log(i),這個(gè)時(shí)候,會(huì)自動(dòng)找到被js變量提升過的i,所以大家都會(huì)輸出5.

解決

總結(jié)下,上面的問題之所以會(huì)產(chǎn)生,就是因?yàn)樗械膐nclick事件都去引用被js變量提升的i,那么如果我們想要解決這個(gè)問題,應(yīng)該怎么辦呢。一個(gè)就是我們可以通過JS的IIFE(immediately-invoked-function-expression)來構(gòu)造一個(gè)作用域,讓onclick函數(shù)引用我們構(gòu)造出來作用域里面的i。ok,我們來解決下

var nodes = document.getElementsByTagName("div");
for(var i = 0,len = nodes.length; i < len; i++){
    (function(i){
        nodes[i].onclick = function(){
            console.log(i);
        }
    })(i)
    
}

這種做法把整個(gè)綁定事件的過程都給包起來了,由于IIFE會(huì)馬上執(zhí)行,for循環(huán)的i相當(dāng)于一個(gè)輸入?yún)?shù),在綁定完事件只有,也形成了一個(gè)作用域,并且這個(gè)作用域中存在一個(gè)i的值。

同樣的道理,我再給一種解法,如下:

var nodes = document.getElementsByTagName("div");
for(var i = 0,len = nodes.length; i < len; i++){
    nodes[i].onclick = (function(i){
        return function(){
            console.log(i);
        }
    })(i)
}

除此之外,我們可能會(huì)想到,如果js能夠有這種塊級作用于就好了,我們綁定的事件一定是在{}作用域下面,一定可以引用到for循環(huán)中的每個(gè)i,而不是應(yīng)用哪個(gè)被變量提升的i。ES6提出了用let關(guān)鍵字來代替var關(guān)鍵字,具體的話可以參考阮一峰的而ES6教程。上個(gè)代碼,這邊代碼用了一個(gè)inbrowser的es6轉(zhuǎn)碼器,可以測試用,如果想要生產(chǎn)環(huán)境中使用需要提前將es6代碼編譯成es5的代碼。






    
1
2
3
4
5
>

引用了一個(gè)inbrower級別的es6轉(zhuǎn)碼器。具體可以參考babel-standalone項(xiàng)目.改進(jìn)后的代碼與原來的代碼的區(qū)別在于,將var i = 0換成了let i = 0.
下面我在看下,通過轉(zhuǎn)碼之后,到底生成了什么樣的js代碼,通過es6轉(zhuǎn)碼器,我們最終生成了如下的代碼

var nodes = document.getElementsByTagName("div");

var _loop = function _loop(i, len) {
    nodes[i].onclick = function () {
        console.log(i);
    };
};

for (var i = 0, len = nodes.length; i < len; i++) {
    _loop(i, len);
}

原來ES6幫我們構(gòu)造了一個(gè)function的作用域報(bào)過了node[i].onclick的事件綁定過程,跟我們上面的解決方法其實(shí)是一樣的!

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/82225.html

相關(guān)文章

  • 詳細(xì)解說JavaScript內(nèi)存管理和GC算法

      JavaScript在創(chuàng)建變量(數(shù)組、字符串、對象等)是自動(dòng)進(jìn)行了分配內(nèi)存,而且當(dāng)它沒有被使用的狀態(tài)下,會(huì)自動(dòng)的釋放分配的內(nèi)容;其實(shí)這樣基層語言,如C語言,他們提供了內(nèi)存管理的接口,比如malloc()用于分配所需的內(nèi)存空間、free()釋放之前所分配的內(nèi)存空間?! ♂尫艃?nèi)存的過程稱為垃圾回收,例如avaScript這類高級語言可以提供了內(nèi)存自動(dòng)分配和自動(dòng)回收,其實(shí)這個(gè)自動(dòng)儲(chǔ)存不會(huì)占用太多空間...

    3403771864 評論0 收藏0
  • 解析關(guān)于JavaScript事件循環(huán)同步任務(wù)與異步任務(wù)

      學(xué)習(xí)一門知識,有些內(nèi)容必須要提前明白,比如在學(xué)習(xí)js中同步異步的問題前,需要明白,js是單線程的,為什么它得是單線程的呢?現(xiàn)在先從它應(yīng)用的場景來說,就是用來讓用戶與頁面進(jìn)行交互的吧。假如有js是多線程的,那在這個(gè)線程里面,用戶點(diǎn)擊某個(gè)按鈕會(huì)增加一個(gè)DOM節(jié)點(diǎn),在另一個(gè)線程里面,用戶點(diǎn)擊這個(gè)按鈕又會(huì)刪除一個(gè)DOM節(jié)點(diǎn),那么此時(shí)js就不知道該聽誰的了。這就是為什么會(huì)出現(xiàn)同步異步。假設(shè)沒有異步,那么...

    3403771864 評論0 收藏0
  • JavaScript數(shù)據(jù)結(jié)構(gòu)與算法

      學(xué)習(xí)JS,就應(yīng)該知道數(shù)據(jù)結(jié)構(gòu)與算法這個(gè)詞?,F(xiàn)在我們就說說:  數(shù)據(jù)結(jié)構(gòu)與算法在編程中是十分需要,主要是沒有很好的數(shù)據(jù)結(jié)構(gòu)與算法的功底,就影響后續(xù)學(xué)習(xí)和工作,這是為什么那?是因?yàn)殡S著項(xiàng)目的復(fù)雜,數(shù)據(jù)量也隨之變大,數(shù)據(jù)結(jié)構(gòu)與算法可以更優(yōu)雅的處理這些數(shù)據(jù)?! 〕绦?數(shù)據(jù)結(jié)構(gòu)+算法,是計(jì)算機(jī)科學(xué)界的一個(gè)經(jīng)典名句,這句話也體現(xiàn)了一個(gè)應(yīng)用程序是與數(shù)據(jù)結(jié)構(gòu)和算法密不可分的。  數(shù)據(jù)結(jié)構(gòu)  其實(shí)數(shù)據(jù)結(jié)構(gòu)簡單說...

    3403771864 評論0 收藏0
  • 同源策略

    一、瀏覽器安全無風(fēng)險(xiǎn)的世界不存在,包括瀏覽器,我們知道Web世界是開放的,包容的。但是開放和風(fēng)險(xiǎn)是對立的。Web 世界會(huì)是開放的,任何資源都可以接入其中,我們的網(wǎng)站可以加載并執(zhí)行別人網(wǎng)站的腳本文件、圖片、音頻 / 視頻等資源,甚至可以下載其他站點(diǎn)的可執(zhí)行文件。比如你打開了一個(gè)銀行站點(diǎn),然后又一不小心打開了一個(gè)惡意站點(diǎn),如果沒有安全措施,惡意站點(diǎn)就可以做很多事情:修改站點(diǎn)的 DOM、CSSOM 等信...

    社區(qū)管理員 評論0 收藏0
  • useEffect支持async及await如何運(yùn)用

    背景  在使用useEffect中用啦回調(diào)函數(shù)中使用 async...await... 這時(shí)候就會(huì)報(bào)錯(cuò)?! ∩厦娲a可以看到,在報(bào)錯(cuò),effect function 應(yīng)該返回一個(gè)銷毀函數(shù)(effect:是指return返回的cleanup函數(shù)),如果 useEffect 第一個(gè)參數(shù)傳入 async,返回值則變成了 Promise,結(jié)果就是會(huì)導(dǎo)致 react 在調(diào)用銷毀函數(shù)的時(shí)候報(bào)錯(cuò)。  React...

    3403771864 評論0 收藏0

發(fā)表評論

0條評論

最新活動(dòng)
閱讀需要支付1元查看
<