JavaScript代碼執(zhí)行的先后順序問題
一、js--->單線程
嚴(yán)格意義上來說,javascript沒有多線程的概念,所有的程序都是單線程依次執(zhí)行的。
1、什么是單線程?
通俗點(diǎn)說,就是代碼在執(zhí)行過程中,另一段代碼想要執(zhí)行就必須等當(dāng)前代碼執(zhí)行完成后才可以進(jìn)行。我們拿一段代碼來解釋一下吧
for(var i=1;i<=3;i++){ setTimeout(function(){ console.log(i); //輸出:4,4,4 },0) }
我們來看一下上面的這段代碼,既然延時(shí)器時(shí)間設(shè)置為0,那么應(yīng)該執(zhí)行一遍循環(huán)就應(yīng)該立即打印出一個(gè)i,但是最終的打印結(jié)果為:4,4,4。之所以會(huì)出現(xiàn)上面的結(jié)果,正是因?yàn)閖s代碼是單線程應(yīng)用。
在執(zhí)行過程中,先遇到for循環(huán),for循環(huán)先進(jìn)入線程。當(dāng)i=1時(shí),循環(huán)走到setTimeOut后,此時(shí)的for循環(huán)還沒有執(zhí)行完成,setTimeOut就會(huì)被放入一個(gè)地方(線程池)等待執(zhí)行。此時(shí)for循環(huán)繼續(xù)執(zhí)行,當(dāng)i=2時(shí),for循環(huán)仍沒有執(zhí)行完,這時(shí)的setTimeOut仍會(huì)被放在線程池中等待執(zhí)行……依次類推,直到for循環(huán)轉(zhuǎn)完3遍后,for循環(huán)執(zhí)行完了,此時(shí)線程空閑了,在線程池中等待執(zhí)行的setTimeOut依次執(zhí)行打印i,而for循環(huán)執(zhí)行完成后,i變成了4,所以打印出了三個(gè)4。
2、如果想要改變上面的狀況可以運(yùn)用以下代碼
//將var變?yōu)閘et for(let i=1; i<=3; i++){ setTimeOut(function(){ console.log(i); //輸出的結(jié)果為1,2,3 },0); } //用自執(zhí)行函數(shù)進(jìn)行包裹 for(var i=1; i<=3; i++){ !function(i){ setTimeOut(function(){ console.log(i); //輸出的結(jié)果為1,2,3 },0); }(i) }
二、js中的函數(shù)作用域和代碼的執(zhí)行
>>>函數(shù)作用域
我們先來了解一下以下幾個(gè)概念:
1、在js語言中,沒有類似于c語言這樣的塊級(jí)作用域。
2、js語言中的頂級(jí)作用域?yàn)閣indow對(duì)象范圍內(nèi),稱為全局作用域,在全局作用域中聲明的變量為全局變量。
3、js函數(shù)范圍內(nèi)的變量只能在函數(shù)內(nèi)部使用,函數(shù)外部無法使用,這樣的變量為局部變量。
4、js函數(shù)可以嵌套,多個(gè)函數(shù)的嵌套構(gòu)成了作用域的層層嵌套,這稱為js中的作用域鏈。
5、js作用域鏈變量訪問規(guī)則:
(1)、當(dāng)前作用域內(nèi)存在要訪問的變量時(shí),則使用當(dāng)前作用域中的變量。
(2)、當(dāng)前作用域中不存在要訪問的變量時(shí),則會(huì)到上一層作用域中尋找,直到全局作用域。
>>>執(zhí)行順序
js代碼執(zhí)行分為兩個(gè)部分:
1、代碼的檢查裝載階段(預(yù)編譯階段),此階段進(jìn)行變量和函數(shù)的聲明,但是不對(duì)變量進(jìn)行賦值,變量的默認(rèn)值為undefined。
2、代碼的執(zhí)行階段,此階段對(duì)變量進(jìn)行賦值和函數(shù)的聲明。
看了上面的一些具體的概念,我們拿一段代碼進(jìn)行舉例說明:
var a=1; //聲明了一個(gè)全局變量 function func(){ console.log(a); //輸出:undefined。打印a,而在func這個(gè)作用域中已經(jīng)聲明了a變量,按照js的執(zhí)行順序,此時(shí)的a并未被賦值。 var a=1; console.log(a); //輸出:1。 } func();
看上面的代碼:第一個(gè)a輸出undefined。原因:js作用域鏈的訪問規(guī)則,當(dāng)前作用域內(nèi)存在要訪問的變量a,所以使用當(dāng)前作用域中的變量。再根據(jù)js代碼的執(zhí)行順序,此時(shí)的a只是聲明了而并未被賦值,默認(rèn)為undefined,所以輸出undefined。
而第二個(gè)a,輸出1,正是因?yàn)榇藭r(shí)的a已經(jīng)被聲明且被賦值,所以a輸出1。
總結(jié)
以上所述是小編給大家介紹的JavaScript代碼執(zhí)行的先后順序問題,希望對(duì)大家有所幫助,如果大家有任何疑問歡迎給我留言,小編會(huì)及時(shí)回復(fù)大家的!
- vue.js element-ui validate中代碼不執(zhí)行問題解決方法
- JS動(dòng)態(tài)添加元素及綁定事件造成程序重復(fù)執(zhí)行解決
- Ajax 動(dòng)態(tài)載入html頁面后不能執(zhí)行其中的js快速解決方法
- Vue.js中輕松解決v-for執(zhí)行出錯(cuò)的三個(gè)方案
- Javascript中八種遍歷方法的執(zhí)行速度深度對(duì)比
- JavaScript實(shí)現(xiàn)父子dom同時(shí)綁定兩個(gè)點(diǎn)擊事件,一個(gè)用捕獲,一個(gè)用冒泡時(shí)執(zhí)行順序的方法
- 徹底弄懂 JavaScript 執(zhí)行機(jī)制
相關(guān)文章
Javascript表單特效之十大常用原理性樣例代碼大總結(jié)
開頭說這個(gè)常用原理性樣例,大家可能不太清楚,這篇文章主要是針對(duì)實(shí)際開發(fā)中常用的一些代碼分析,主要是針對(duì)表單處理方法的一些資料,推薦大家收藏2016-07-07Bootstrap CSS組件之面包屑導(dǎo)航(breadcrumb)
這篇文章主要為大家詳細(xì)介紹了Bootstrap CSS組件之面包屑導(dǎo)航(breadcrumb),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-12-12理清apply(),call()的區(qū)別和關(guān)系
如果沒接觸過動(dòng)態(tài)語言,以編譯型語言的思維方式去理解javaScript將會(huì)有種神奇而怪異的感覺,因?yàn)橐庾R(shí)上往往不可能的事偏偏就發(fā)生了,甚至覺得不可理喻.2011-08-08僅在IE6/7/8下cssText返回值少了分號(hào)的測(cè)試代碼
在IE6/7/8中少了分號(hào)。使用cssText屬性時(shí)需注意。2011-03-03