成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

日常筆記

myshell / 1709人閱讀

摘要:零延遲零延遲并不是意味著回調(diào)函數(shù)立刻執(zhí)行。異步編程的中方法包括回調(diào)函數(shù)事件監(jiān)聽(tīng)采用事件驅(qū)動(dòng)模式。執(zhí)行完成后,立即觸發(fā)事件,從而開(kāi)始執(zhí)行。所謂對(duì)象,就是代表了未來(lái)某個(gè)將要發(fā)生的事件通常是一個(gè)異步操作。

JavaScript單線程與瀏覽器多線程

Javascript是單線程的:因?yàn)镴S運(yùn)行在瀏覽器中,是單線程的,每個(gè)window一個(gè)JS線程。作為瀏覽器腳本語(yǔ)言,JavaScript的主要用途是與用戶互動(dòng),以及操作DOM。若以多線程的方式操作這些DOM,則可能出現(xiàn)操作的沖突。假設(shè)有兩個(gè)線程同時(shí)操作一個(gè)DOM元素,線程1要求瀏覽器刪除DOM,而線程2卻要求修改DOM樣式,這時(shí)瀏覽器就無(wú)法決定采用哪個(gè)線程的操作。

瀏覽器不是單線程的,引擎可能存在如下線程:

javascript引擎線程

界面渲染線程

瀏覽器事件觸發(fā)線程

Http請(qǐng)求線程等

Event Loop

事件循環(huán)機(jī)制:
主線程從"任務(wù)隊(duì)列"中讀取事件,這個(gè)過(guò)程是循環(huán)不斷的,所以整個(gè)的這種運(yùn)行機(jī)制又稱為Event Loop(事件循環(huán))。主線程運(yùn)行的時(shí)候,產(chǎn)生堆(heap)和棧(stack),棧中的代碼調(diào)用各種外部API,它們?cè)?任務(wù)隊(duì)列"中加入各種事件(click,load,done)。只要棧中的代碼執(zhí)行完畢,主線程就會(huì)去讀取"任務(wù)隊(duì)列",依次執(zhí)行那些事件所對(duì)應(yīng)的回調(diào)函數(shù)。

執(zhí)行棧:所有同步任務(wù)都在主線程上執(zhí)行,形成一個(gè)執(zhí)行棧;

任務(wù)隊(duì)列:主線程之外,還存在一個(gè)"任務(wù)隊(duì)列"(task queue)。只要異步任務(wù)有了運(yùn)行結(jié)果,就在"任務(wù)隊(duì)列"之中放置一個(gè)事件,當(dāng)棧為空時(shí),就會(huì)從任務(wù)隊(duì)列中取出一個(gè)任務(wù)并執(zhí)行。

定時(shí)器:
定時(shí)器包括setTimeout與setInterval兩個(gè)方法。它們的第二個(gè)參數(shù)是指定其回調(diào)函數(shù)推遲每隔多少毫秒數(shù)后執(zhí)行。
零延遲 setTimeout(func, 0):零延遲并不是意味著回調(diào)函數(shù)立刻執(zhí)行。它取決于主線程當(dāng)前是否空閑與“任務(wù)隊(duì)列”里其前面正在等待的任務(wù)。當(dāng)計(jì)時(shí)器時(shí)間規(guī)定的時(shí)候,回調(diào)函數(shù)會(huì)被添加到“任務(wù)隊(duì)列”中,等到執(zhí)行棧的任務(wù)執(zhí)行完畢,就會(huì)來(lái)執(zhí)行這里的任務(wù)。所以,有的時(shí)候即使計(jì)時(shí)器已經(jīng)到0了,也會(huì)不立即執(zhí)行計(jì)時(shí)器中的回調(diào)任務(wù)。

Ajax異步請(qǐng)求:
在發(fā)起ajax請(qǐng)求的時(shí)候,瀏覽器會(huì)開(kāi)一個(gè)線程去執(zhí)行這一步驟,發(fā)請(qǐng)求這一步是屬于執(zhí)行棧中的同步任務(wù),在請(qǐng)求發(fā)完之后就會(huì)執(zhí)行棧中的下一個(gè)任務(wù),而等到請(qǐng)求有了結(jié)果,就會(huì)把結(jié)果放入“任務(wù)隊(duì)列”中,等待執(zhí)行;

JavaScript異步編程

JavaScript是單線程的,所謂“單線程”,就是同一時(shí)間只能執(zhí)行一個(gè)任務(wù)。如果有多個(gè)任務(wù),就必須排隊(duì),直到前一個(gè)任務(wù)完成。這種模式的好處就是實(shí)現(xiàn)比較簡(jiǎn)單,尤其在瀏覽器環(huán)境中,可以避免很多不必要的麻煩。壞處就是如果一個(gè)任務(wù)耗時(shí)很長(zhǎng),那么該任務(wù)后面的任務(wù)就必須一直等待,導(dǎo)致整個(gè)頁(yè)面都卡住無(wú)法繼續(xù)往下執(zhí)行。

為了解決這個(gè)問(wèn)題,JavaScript將任務(wù)的執(zhí)行模式分為兩類,一個(gè)是同步模式,另一個(gè)是異步模式。

"同步模式"就是上一段的模式,后一個(gè)任務(wù)等待前一個(gè)任務(wù)結(jié)束,然后再執(zhí)行,程序的執(zhí)行順序與任務(wù)的排列順序是一致的、同步的;"異步模式"則完全不同,每一個(gè)任務(wù)有一個(gè)或多個(gè)回調(diào)函數(shù)(callback),前一個(gè)任務(wù)結(jié)束后,不是執(zhí)行后一個(gè)任務(wù),而是執(zhí)行回調(diào)函數(shù),后一個(gè)任務(wù)則是不等前一個(gè)任務(wù)結(jié)束就執(zhí)行,所以程序的執(zhí)行順序與任務(wù)的排列順序是不一致的、異步的。

JS異步編程的4中方法包括:

回調(diào)函數(shù):

f1();
f2();

function f1(callback){
    setTimeout(function(){
        callback();
    })
}

f1(f2);

事件監(jiān)聽(tīng):采用事件驅(qū)動(dòng)模式。任務(wù)的執(zhí)行不取決于代碼的順序,而取決于某個(gè)事件是否發(fā)生。

//jQuery
f1.on("done", f2);

function f1(){
   setTimeout(function () {
       //do something
     f1.trigger("done");//執(zhí)行完成后,立即觸發(fā)done事件,從而開(kāi)始執(zhí)行f2。
   }, 1000);
}

發(fā)布/訂閱:又稱觀察者模式

jQuery.subscribe("done", f2);//訂閱"done"這個(gè)信號(hào)

function f1(){
   setTimeout(function () {
     //do something
     jQuery.publish("done");//f1()執(zhí)行完之后,發(fā)出"done"這個(gè)信號(hào),f2開(kāi)始執(zhí)行
   }, 1000);
}

jQuery.unsubscribe("done", f2);//取消訂閱

Promises:ES6原生提供了Promise對(duì)象。所謂Promise對(duì)象,就是代表了未來(lái)某個(gè)將要發(fā)生的事件(通常是一個(gè)異步操作)。它的好處在于,有了Promise對(duì)象,就可以將異步操作以同步操作的流程表達(dá)出來(lái),避免了層層嵌套的回調(diào)函數(shù)。此外,Promise對(duì)象還提供了一整套完整的接口,使得可以更加容易地控制異步操作。

var promise = new Promise(function(resolve, reject) {
  if (/* 異步操作成功 */){
    resolve(value);
  } else {
    reject(error);
  }
});

promise.then(function(value) {
  // success
}, function(value) {
  // failure
});

ES6模塊管理

ECMAScript 6基于export和import,定義了模塊的導(dǎo)出和導(dǎo)入規(guī)范,在語(yǔ)言標(biāo)準(zhǔn)層面實(shí)現(xiàn)了模塊機(jī)制。該標(biāo)準(zhǔn)的目標(biāo)是創(chuàng)建一種能夠兼容CommoneJS和AMD兩標(biāo)準(zhǔn)的規(guī)范,即可以像CommoneJS一樣語(yǔ)法簡(jiǎn)潔、使用單一的接口且支持循環(huán)依賴,又可以像AMD支持異步加載和可配置的模塊加載。

大致來(lái)說(shuō),當(dāng) JS 引擎運(yùn)行一個(gè)模塊的時(shí)候,它的行為大致可歸納為以下四步:

解析:引擎實(shí)現(xiàn)會(huì)閱讀模塊的源碼,并且檢查是否有語(yǔ)法錯(cuò)誤。

加載:引擎實(shí)現(xiàn)會(huì)(遞歸地)加載所有被引入的模塊。

鏈接:引擎實(shí)現(xiàn)會(huì)為每個(gè)新加載的模塊創(chuàng)建一個(gè)作用域,并且將模塊中的聲明綁定填入其中,包括從其他模塊中引入的。

JS加載

動(dòng)態(tài)加載常用的4種方法:

document.write:document.write("");

動(dòng)態(tài)改變已有script的src屬性:js.src = "package.js";

動(dòng)態(tài)創(chuàng)建script元素:

var script = document.createElement("script");
script.src = "XXX";
script.type = "XXX";
document.head.appendChild(script);

用XMLHTTP取得要腳本的內(nèi)容,再創(chuàng)建 Script 對(duì)象。

項(xiàng)目中加載JS的方法:
在頁(yè)面底部寫一個(gè)自調(diào)用函數(shù),加載入口JS,然后入口中的方法執(zhí)行,加載需要的其他JS。

在VM平臺(tái)上,可以選擇將幾個(gè)模塊分組打包到一個(gè)入口文件中,然后在這個(gè)入口文件中,將每個(gè)組動(dòng)態(tài)生成一個(gè)script標(biāo)簽,插入head中。

異步加載:
瀏覽器在渲染一個(gè)頁(yè)面的時(shí)候,遇到一個(gè)

閱讀需要支付1元查看
<