前端知識體系總結(jié)

數(shù)據(jù)結(jié)構(gòu)與算法


棧和隊(duì)列的區(qū)別

網(wǎng)絡(luò)基礎(chǔ)


HTTP 無狀態(tài)怎么理解

可以從REST的角度來理解這個(gè)問題熙含。我們知道REST風(fēng)格是無狀態(tài)的蚂蕴。而REST是基于HTTP協(xié)議的衬浑,所以REST的無狀態(tài)基本就可以解釋HTTP的無狀態(tài)亏狰。

TCP三次握手與四次揮手

三次握手
為了準(zhǔn)確無誤地將數(shù)據(jù)送到目標(biāo)處,TCP采用三次握手策略蟀瞧,過程中使用了TCP的標(biāo)志:SYN和ACK.
三次握手
Client --> 置SYN標(biāo)志 序列號 = J,確認(rèn)號 = 0 ----> Server
Client <-- 置SYN標(biāo)志 置ACK標(biāo)志 序列號 = K, 確認(rèn)號 = J + 1 <-- Server
Clinet --> 置ACK標(biāo)志 序列號 = J + 1条摸,確認(rèn)號 = K + 1 --> Server
四次揮手
Client -> 發(fā)送FIN 序列號 = J悦污,確認(rèn)號 = 0 --> Server
Server -> 發(fā)送ACK 確認(rèn)號 = J + 1
Server -> 發(fā)送FIN 序列號 = K, 確認(rèn)號 = 0 -> Client
Client -> 發(fā)送ACK 確認(rèn)號 = K+1

HTTPS

HTTPS是在HTTP與TCP之間添加一個(gè)安全協(xié)議層(SSL或TSL).
網(wǎng)絡(luò)請求中往往中間需要很多服務(wù)器或者路由器的轉(zhuǎn)發(fā),中間的節(jié)點(diǎn)都可能篡改信息钉蒲,而如果使用HTTPS切端,密鑰在請求客戶端和終點(diǎn)站才有,所以相對于HTTP會更安全顷啼,就是因?yàn)镠TTPs利用SSL/TSL協(xié)議傳輸踏枣,它包含證書等安全信息,保證了傳輸過程的安全性钙蒙。

前端其他問題


前端工程價(jià)值

  • 解放前后端互相在開發(fā)進(jìn)度上的依賴問題茵瀑,前后端可以同時(shí)進(jìn)行
  • 為簡化用戶使用,提高交互體驗(yàn)/用戶體驗(yàn)
  • 解決瀏覽器兼容問題
  • 提高瀏覽速度(性能)
  • 跨平臺應(yīng)用的支持
  • 展現(xiàn)數(shù)據(jù)躬厌,數(shù)據(jù)處理
  • 降低后端壓力

瀏覽器緩存技術(shù)

** Etag **

當(dāng)發(fā)送一個(gè)服務(wù)器的請求時(shí)马昨,瀏覽器會首先進(jìn)行緩存過期的判斷,瀏覽器根據(jù)緩存過期的時(shí)間判斷緩存文件是否過期烤咧。

  • 若沒有過期偏陪,則不向服務(wù)器發(fā)送請求,直接使用緩存中的結(jié)果

Session Cookie LocalStorage

全局環(huán)境與局部環(huán)境

JS對象 BOM DOM

http://www.runoob.com/jsref/dom-obj-event.html

瀏覽器的基本組成與頁面渲染原理

為什么不能頻繁操作DOM

重排與重繪

前端模塊化


https://segmentfault.com/p/1210000007731421?from=singlemessage&isappinstalled=1
CommonJs規(guī)范 - NodeJs實(shí)現(xiàn) 同步
分支 異步
AMD RequireJs
CMD SeaJs
UMD 前后端整合
ES6 - I import export

前端優(yōu)化


前端兼容性


漸進(jìn)增強(qiáng)和優(yōu)雅降級

** 漸進(jìn)增強(qiáng) ** :針對低版本瀏覽器進(jìn)行構(gòu)建頁面煮嫌,保證最基本的功能笛谦,然后再針對高級瀏覽器進(jìn)行效果、交互等改進(jìn)和追加功能達(dá)到更好的用戶體驗(yàn)昌阿。
** 優(yōu)雅降級 ** :一開始就構(gòu)建完整的功能饥脑,然后再針對低版本瀏覽器進(jìn)行兼容。

前端安全性


常見的幾種安全攻擊

SQL 注入
XSS
CSRF

前端工具


模塊打包工具

** Webpack **

  1. 模塊打包工具
  1. 管理依賴模塊間依賴懦冰,生成優(yōu)化并且合并后的靜態(tài)資源文件
  2. 編譯輸出靜態(tài)文件灶轰,將代碼分割成不同的chunk,實(shí)現(xiàn)按需加載刷钢,降低初始化時(shí)間
  3. 所有文件都是模塊, html, js, css笋颤, 圖片等
  4. 模塊加載器, 支持串聯(lián)操作
  5. 以commonJs的形式書寫,但對AMD/CMD的支持也比較全面伴澄,方便舊項(xiàng)目進(jìn)行代碼遷移

HTML5


Webworker

Js中的多線程實(shí)現(xiàn)

Websocket

SVG

Canvas

CSS


position的值赋除, relative和absolute分別是相對于誰進(jìn)行定位的?

盒模型

IE盒模型與其他瀏覽器的盒模型

CSS選擇器的優(yōu)先級

JavaScript


ES6

參考:http://es6.ruanyifeng.com/

Js運(yùn)行機(jī)制

http://www.ruanyifeng.com/blog/2014/10/event-loop.html

  • Javascript 是單線程
    Javascript 的單線程與它的用途有關(guān)
  • 任務(wù)隊(duì)列
    任務(wù)可分為兩種非凌,一種是同步任務(wù)举农,一種是異步任務(wù)。
    ** 同步任務(wù) :在主線程上排隊(duì)執(zhí)行的任務(wù)敞嗡,只有前一個(gè)任務(wù)執(zhí)行完畢后颁糟,才能執(zhí)行后一個(gè)任務(wù);
    ** 異步任務(wù) :不進(jìn)入主線程喉悴,而進(jìn)入任務(wù)隊(duì)列(task queue)的任務(wù)棱貌,只有任務(wù)隊(duì)列通知主線程,某個(gè)異步任務(wù)要以執(zhí)行了粥惧,該任務(wù)才會進(jìn)入主線程執(zhí)行键畴。
    ** 異步任務(wù)運(yùn)行機(jī)制如下:

    Paste_Image.png

    1)所有同步任務(wù)都在主線程上執(zhí)行,形成一個(gè)執(zhí)行棧(execution context stack)突雪。
    2)主線程之外起惕,還存在一個(gè)"任務(wù)隊(duì)列"(task queue)。只要異步任務(wù)有了運(yùn)行結(jié)果咏删,就在"任務(wù)隊(duì)列"之中放置一個(gè)事件惹想。
    3)一旦"執(zhí)行棧"中的所有同步任務(wù)執(zhí)行完畢,系統(tǒng)就會讀取"任務(wù)隊(duì)列"督函,看看里面有哪些事件嘀粱。那些對應(yīng)的異步任務(wù),于是結(jié)束等待狀態(tài)辰狡,進(jìn)入執(zhí)行棧锋叨,開始執(zhí)行。
    4)主線程不斷重復(fù)上面的第三步宛篇。
    ** 只要主線程空了娃磺,就會去讀取"任務(wù)隊(duì)列"叫倍,這就是JavaScript的運(yùn)行機(jī)制偷卧。這個(gè)過程會不斷重復(fù)。
  • 事件和任務(wù)隊(duì)列
    ** 任務(wù)隊(duì)列 **
  1. 是一個(gè)事件的隊(duì)列吆倦,也可以理解成是消息隊(duì)列。主線程讀取任務(wù)隊(duì)列就是讀取里面有哪些事件仔蝌。
  2. 任務(wù)隊(duì)列里面不止有IO設(shè)備的事件砸逊,也有用戶操作產(chǎn)生的事件。只要指定過回調(diào)函數(shù)掌逛,這些事件發(fā)生時(shí)就會進(jìn)入任務(wù)隊(duì)列中,等待主線程讀取司倚。主線程執(zhí)行異步任務(wù)豆混,就是執(zhí)行對應(yīng)的回調(diào)函數(shù)。
  3. 主線程會首先檢查執(zhí)行時(shí)間动知,某些事件只有到了規(guī)定的時(shí)間皿伺,才能返回主線程。如setTimeout().
    ** Event Loop **
    主線程從事件隊(duì)列中讀取事件的過程是不斷循環(huán)的盒粮,所以整個(gè)的運(yùn)行機(jī)制就是一個(gè)Event Loop鸵鸥,也叫事件循環(huán)。


    Paste_Image.png
  4. 定時(shí)器
    除了放置異步任務(wù)的事件丹皱,"任務(wù)隊(duì)列"還可以放置定時(shí)事件妒穴,即指定某些代碼在多少時(shí)間之后執(zhí)行。這叫做"定時(shí)器"(timer)功能摊崭,也就是定時(shí)執(zhí)行的代碼讼油。
    setTimeout()
    setInterval()
    HTML5標(biāo)準(zhǔn)規(guī)定了setTimeout()的第二個(gè)參數(shù)的最小值(最短間隔),不得低于4毫秒呢簸,如果低于這個(gè)值矮台,就會自動增加。在此之前根时,老版本的瀏覽器都將最短間隔設(shè)為10毫秒瘦赫。另外,對于那些DOM的變動(尤其是涉及頁面重新渲染的部分)蛤迎,通常不會立即執(zhí)行确虱,而是每16毫秒執(zhí)行一次。這時(shí)使用requestAnimationFrame()的效果要好于setTimeout()忘苛。
    需要注意的是蝉娜,setTimeout()只是將事件插入了"任務(wù)隊(duì)列",必須等到當(dāng)前代碼(執(zhí)行棧)執(zhí)行完扎唾,主線程才會去執(zhí)行它指定的回調(diào)函數(shù)召川。要是當(dāng)前代碼耗時(shí)很長,有可能要等很久胸遇,所以并沒有辦法保證荧呐,回調(diào)函數(shù)一定會在setTimeout()指定的時(shí)間執(zhí)行。

Js事件模型

參考:https://segmentfault.com/a/1190000006934031?from=singlemessage&isappinstalled=1
DOM事件探秘

  • ** 發(fā)布訂閱模式(觀察者模式)**
    Javascript的事件模型基于發(fā)布請閱模式,可以讓多個(gè)觀察者對象同時(shí)監(jiān)聽某一個(gè)主題對象倍阐,這個(gè)主題對象的狀態(tài)變化會通知所有的訂閱者概疆,使得它們能夠做出反應(yīng)。
    以下是用js實(shí)現(xiàn)的一個(gè)發(fā)布訂閱模式
var events = (function () {
    var topics = {};
    return {
        publish: function (topic, info) {
            console.log("publish a topic:" + topic);
            if (topics.hasOwnProperty(topic)) {
                topics[topic].forEach(function(handler) {
                    handler(info ? info : {});
                });
            }
        },
        subscribe: function(topic, handler) {
            console.log("subscribe an topic" + topic);
            if (!topics.hasOwnProperty(topic)) {
                topics[topic] = [];
            }
            topics[topic].push(handler);
        },
        remove: function(topic, handler) {
            if (!topics.hasOwnProperty(topics)) {
                return;
            }
            var handlerIndex = -1;
            topics[topic].forEach(function (element, index) {
                if (element === handler) {
                    handlerIndex = index;
                }
            });
            if (handlerIndex >= 0) {
                topics[topic].splice(handlerIndex, 1);
            }
        }
    };
})();
var handler = function (info) {
    console.log(info);
}
events.subscribe("hello", handler);
events.publish("hello", "hello world");
  • ** 事件與事件流 **
    事件是與瀏覽器或文檔交互的瞬間峰搪,如點(diǎn)擊按鈕岔冀,填寫表格等,它是JS與HTML之間交互的橋梁概耻。DOM是樹形結(jié)構(gòu)使套,如果同時(shí)給父子節(jié)點(diǎn)都綁定事件時(shí),當(dāng)觸發(fā)子節(jié)點(diǎn)的時(shí)候鞠柄,這兩個(gè)事件的發(fā)生順序如何決定?這就涉及到事件流的概念侦高,它描述的是頁面中接受事件的順序。
    事件流有兩種:
    ** 事件冒泡(Event Capturing): ** 是一種從下往上的傳播方式厌杜。事件最開始由最具體的元素(文檔中嵌套層次最深的那個(gè)節(jié)點(diǎn)接受, 也就是DOM最低層的子節(jié)點(diǎn)), 然后逐漸向上傳播到最不具體的那個(gè)節(jié)點(diǎn)奉呛,也就是DOM中最高層的父節(jié)點(diǎn)。
    ** 事件捕獲(Event Bubbling): **與事件冒泡相反夯尽。事件最開始由不太具體的節(jié)點(diǎn)最早接受事件, 而最具體的節(jié)點(diǎn)最后接受事件瞧壮。
  • ** 事件模型 **
    ** DOM 0級模型 **
    HTML代碼中直接綁定:
<input type="button" onclick="fun()">

通過JS代碼指定屬性值:

var btn = document.getElementById('.btn');btn.onclick = fun;

移除監(jiān)聽函數(shù):

btn.onclick = null;

這種方式所有瀏覽器都兼容,但是邏輯與顯示并沒有分離匙握。
** IE事件模型 **
IE事件模型共有兩個(gè)過程:
事件處理階段(target phase)馁痴。事件到達(dá)目標(biāo)元素, 觸發(fā)目標(biāo)元素的監(jiān)聽函數(shù)。
事件冒泡階段(bubbling phase)肺孤。事件從目標(biāo)元素冒泡到document, 依次檢查經(jīng)過的節(jié)點(diǎn)是否綁定了事件監(jiān)聽函數(shù)罗晕,如果有則執(zhí)行。
事件綁定監(jiān)聽函數(shù)的方式如下:

attachEvent(eventType, handler)

事件移除監(jiān)聽函數(shù)的方式如下:

detachEvent(eventType, handler)

參數(shù)說明:
eventType指定事件類型(注意加on)
handler是事件處理函數(shù)
Example:

var btn = document.getElementById('.btn');
btn.attachEvent(‘onclick’, showMessage);
btn.detachEvent(‘onclick’, showMessage);

** DOM 2級模型 **
屬于W3C標(biāo)準(zhǔn)模型赠堵,現(xiàn)代瀏覽器(除IE6-8之外的瀏覽器)都支持該模型小渊。在該事件模型中,一次事件共有三個(gè)過程:
事件捕獲階段(capturing phase)茫叭。事件從document一直向下傳播到目標(biāo)元素, 依次檢查經(jīng)過的節(jié)點(diǎn)是否綁定了事件監(jiān)聽函數(shù)酬屉,如果有則執(zhí)行。
事件處理階段(target phase)揍愁。事件到達(dá)目標(biāo)元素, 觸發(fā)目標(biāo)元素的監(jiān)聽函數(shù)呐萨。
事件冒泡階段(bubbling phase)。事件從目標(biāo)元素冒泡到document, 依次檢查經(jīng)過的節(jié)點(diǎn)是否綁定了事件監(jiān)聽函數(shù)莽囤,如果有則執(zhí)行谬擦。
事件綁定監(jiān)聽函數(shù)的方式如下:

addEventListener(eventType, handler, useCapture)

事件移除監(jiān)聽函數(shù)的方式如下:

removeEventListener(eventType, handler, useCapture)

Example:

var btn = document.getElementById('.btn');
btn.addEventListener(‘click’, showMessage, false);
btn.removeEventListener(‘click’, showMessage, false);

參數(shù)說明:
eventType指定事件類型(不要加on)
handler是事件處理函數(shù)
useCapture是一個(gè)boolean用于指定是否在捕獲階段進(jìn)行處理,一般設(shè)置為false與IE瀏覽器保持一致朽缎。
DOM事件模型中的事件對象常用屬性:

  • type用于獲取事件類型
  • target獲取事件目標(biāo)
  • stopPropagation()阻止事件冒泡
  • preventDefault()阻止事件默認(rèn)行為
    IE事件模型中的事件對象常用屬性:
  • type用于獲取事件類型
  • srcElement獲取事件目標(biāo)
  • cancelBubble阻止事件冒泡
  • returnValue阻止事件默認(rèn)行為

Javascript垃圾回收機(jī)制

** 標(biāo)記清除 ** -> 最常見的垃圾回收方式
這是JavaScript最常見的垃圾回收方式惨远,當(dāng)變量進(jìn)入執(zhí)行環(huán)境的時(shí)候谜悟,比如函數(shù)中聲明一個(gè)變量,垃圾回收器將其標(biāo)記為“進(jìn)入環(huán)境”北秽,當(dāng)變量離開環(huán)境的時(shí)候(函數(shù)執(zhí)行結(jié)束)將其標(biāo)記為“離開環(huán)境”葡幸。垃圾回收器會在運(yùn)行的時(shí)候給存儲在內(nèi)存中的所有變量加上標(biāo)記,然后去掉環(huán)境中的變量以及被環(huán)境中變量所引用的變量(閉包)贺氓,在這些完成之后仍存在標(biāo)記的就是要刪除的變量了
** 引用計(jì)數(shù) ** -> 會出現(xiàn)因?yàn)檠h(huán)引用而出現(xiàn)的無法回收而導(dǎo)致的內(nèi)存泄漏
參考: http://www.reibang.com/p/80ed3805edc3

創(chuàng)建對象的幾種方式

  • ** 使用{}
var bar = {
  color: "blue"
};
  • ** 使用new關(guān)鍵字 **
var bar = new Object();
bar.color = "blue";
  • ** 使用構(gòu)造函數(shù) **
var Fun = function (color) {
  this.color = color;
}
var bar = new Fun();

面向?qū)ο笈c繼承的幾種方式

** 原型編程泛型基本規(guī)則 **

  • 所有的數(shù)據(jù)都是對象
  • 要得到一個(gè)對象蔚叨,不是通過 實(shí)例化類,而是找到一個(gè)對象作為原型并克隆它
  • 對象會記住它的原型
  • 如果對象本身無法響應(yīng)某個(gè)請求辙培,它會把這個(gè)請求委托給它自己的原型
    ** 實(shí)現(xiàn)方式 **
    http://www.jb51.net/article/81766.htm

解決跨域問題

Jsonp
Cors
Document.domain
Document.name
HTML5 postMessage

AJAX

創(chuàng)建過程
(1)創(chuàng)建XMLHttpRequest對象,也就是創(chuàng)建一個(gè)異步調(diào)用對象.
(2)創(chuàng)建一個(gè)新的HTTP請求,并指定該HTTP請求的方法缅叠、URL及驗(yàn)證信息.
(3)設(shè)置響應(yīng)HTTP請求狀態(tài)變化的函數(shù).
(4)發(fā)送HTTP請求.
(5)獲取異步調(diào)用返回的數(shù)據(jù).(6)使用JavaScript和DOM實(shí)現(xiàn)局部刷新.
參考:https://segmentfault.com/a/1190000004322487

說說你對作用域鏈的理解

作用域鏈的作用是保證執(zhí)行環(huán)境里有權(quán)訪問的變量和函數(shù)是有序的,作用域鏈的變量只能向上訪問虏冻,變量訪問到window對象即被終止,作用域鏈向下訪問變量是不被允許的弹囚。

閉包

實(shí)現(xiàn)延遲打印1-5

for (var i = 0; i < 5; i++) {
  (function (i) {
    setTimeout(function () {
      console.log(i)
    }, i * 1000)
  })(i);
}
for (var i = 0; i < 5; i++) {
  setTimeout(function (i) {
    return function() { console.log(i); };
  }(i), i * 1000)
}
[1,2,3,4,5,6].forEach(i => {
    setTimeout(function () {
      console.log(i)
    }, i * 1000);
});

嚴(yán)格模式 (use strict)

  • 非嚴(yán)格模式下有些錯(cuò)誤會在運(yùn)行時(shí)被悄悄地忽略掉厨相,而在嚴(yán)格模式下,這些錯(cuò)誤會被拋出來鸥鹉,從而方便debug蛮穿,通常來說,這是一種很好的實(shí)踐毁渗。
  • 防止給未聲明的變量賦值
  • 非嚴(yán)格模式下如果引用的this是null或者undefined的話會自動將this指向global對象践磅,這種情況會造成一些比較難發(fā)現(xiàn)且頭疼的bug。而在嚴(yán)格模式下灸异,則會拋出錯(cuò)誤府适。
  • 防止在一個(gè)對象內(nèi)重復(fù)定義屬性。
  • 安全使用eval()
  • delete操作符

如何判讀一個(gè)變量是個(gè)整數(shù) (實(shí)現(xiàn) isInteger(x))

在ES6中肺樟,Number.isInteger() 可以用來判斷是否為整數(shù)檐春。
在ES6之前的版本中這個(gè)問題則比較復(fù)雜,因?yàn)閚umberic的值通常是作為一個(gè)浮點(diǎn)數(shù)來存儲的么伯,只能用比較取巧的方式來實(shí)現(xiàn)這樣的判斷邏輯疟暖。

function isInteger(x) { return (x^0) === x; }
function isInteger(x) { return Math.round(x) === x; }
function isInteger(x) { 
  return  (typeof x === "number") && (x % 1 === 0;;
}

此外也可以使用parseInt來實(shí)現(xiàn)

function isInteger(x) { return parseInt(x, 10) === x;}

數(shù)組操作 (split, reverse, push, slice, concat)

What will the code below output to the console and why?

var arr1 = "john".split('');
var arr2 = arr1.reverse();
var arr3 = "jones".split('');
arr2.push(arr3);
console.log("array 1: length=" + arr1.length + " last=" + arr1.slice(-1));
console.log("array 2: length=" + arr2.length + " last=" + arr2.slice(-1));

JavaScript 設(shè)計(jì)模式


Angular


雙向綁定如何實(shí)現(xiàn)

臟檢查機(jī)制

React


虛擬DOM 實(shí)現(xiàn)機(jī)制

JQuery


Jquery 綁定事件的方法

target.on("click");
target.click(function() {
});
target.live("click", function () {
});
target.bind("click", function () {
});

#### Jquery的鏈?zhǔn)讲僮魅绾螌?shí)現(xiàn)

# 正則表達(dá)式
****
#### 語法
> https://msdn.microsoft.com/zh-cn/library/ae5bf541(VS.80).aspx

#### 驗(yàn)證身份證
> ```
var reg=/^[1-9]{1}[0-9]{14}$|^[1-9]{1}[0-9]{16}([0-9]|[xX])$/;

面試題


更多面試題: https://www.toptal.com/javascript/interview-questions

鼠標(biāo)點(diǎn)擊頁面中的任意標(biāo)簽,alert標(biāo)簽名稱 (兼容性)

<script type="text/javascript" >
document.onClick() = function(event) {
    var e = event || window.event;
    var src = event.target || event.srcElement;
    alert(src.tagName.toLowercase());
}
</script>

異步加載js方案田柔,不少于兩種

** 同步加載 **

就是我們平時(shí)使用的最多的方式俐巴,在頁面中使用script標(biāo)簽
這種模式也叫阻塞模式,會阻止瀏覽器的后續(xù)處理硬爆,停止后續(xù)的解析欣舵,只有當(dāng)加載完成,才能進(jìn)行下一步的操作缀磕,所以默認(rèn)同步執(zhí)行才是比較安全的邻遏。但是這種方式會造成頁面的阻塞糠亩,所以一般建議把<script>標(biāo)簽放在<body>結(jié)尾,這樣盡可能減少頁面阻塞准验。

** 異步加載 **

異步加載 又叫非阻塞加載赎线,瀏覽器在下載執(zhí)行js的同時(shí),還會繼續(xù)進(jìn)行后續(xù)頁面的處理糊饱。主要有以下幾中方式:

  • ** Script Dom Element **
(function() {
    var scriptEle = document.createElement("script");
    scriptEle.type = "text/javascript";
    scriptEle.async = true;
    scriptEle.src="http://xxx/jquery.js";
    var x = document.getElementByTagName("head")[0];
    x.insertBefore(scriptEle, x.firstChild);
})();

google的使用方式

(function(){;
    var ga = document.createElement('script'); 
    ga.type = 'text/javascript'; 
    ga.async = true; 
    ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; 
    var s = document.getElementsByTagName('script')[0]; 
    s.parentNode.insertBefore(ga, s); 
})();

缺點(diǎn): 執(zhí)行完成之前會阻止onLoad事件的觸發(fā)垂寥,而現(xiàn)在很多頁面的代碼都會在onLoad的時(shí)候做一些額外的渲染動作,所以還是會阻塞部分頁面的初始化的處理另锋。

  • ** onload時(shí)的異步加載 **
;(function () {
  if (window.attachEvent) {
    window.attachEvent('load', asyncLoad)
  } else {
    window.addEventListener('load', asyncLoad)
  }
  var asyncLoad = function () {
    var scriptEle = document.createElement('script')
    scriptEle.type = 'text/javascript'
    scriptEle.async = true
    scriptEle.src = 'http://xxx/jquery.js'
    var x = document.getElementByTagName('head')[0]
    x.insertBefore(scriptEle, x.firstChild)
  }
})()

注:DOMContentLoaded與load區(qū)別
前者是在document 已經(jīng)解析完成滞项,頁面中的dom元素可用,但是頁面中的圖片夭坪,視頻文判,音頻等資源還未加載完,作用同jquery的ready. 后者的區(qū)別在于頁面中所有資源包括js都加載完成室梅。

  • ** 其他方法**
    ** XHR Injection **
    通過XMLHttpRequest來獲取javascript戏仓,然后創(chuàng)建一個(gè)script元素插入到DOM結(jié)構(gòu)中。ajax請求成功后設(shè)置script.text為請求成功后返回的responseText
var getXmlHttp = function () {
  var obj
  if (window.XMLHttpRequest)
    obj = new XMLHttpRequest()
  else
    obj = new ActiveXObject('Microsoft.XMLHTTP')
  return obj
}
var xhr = getXmlHttp()
xhr.open('GET', 'http://xxx.com/jquery.js', true)
xhr.send()
xhr.onReadyStateChange = function () {
  if (xhr.readyState == 4 && xhr.status == 200) {
    var script = document.createElement('script')
    script.text = xhr.response.text
    document.getElementsByTagName('head')[0].appendChild(script)
  }
}

** XHR Eval **
與XHR Injection對responseText的執(zhí)行方式不同亡鼠,直接把responseText放在eval()函數(shù)里面執(zhí)行赏殃。
** Script In IFrame **
在父窗口插入一個(gè)iframe元素,然后再iframe中執(zhí)行加載JS的操作间涵。

var insertJS = function(){alert(2)};
    var iframe = document.createElement("iframe");
    document.body.appendChild(iframe);
    var doc = iframe.contentWindow.document;//獲取iframe中的window要用contentWindow屬性仁热。
    doc.open();
    doc.write("<script>var insertJS = function(){};<\/script><body onload='insertJS()'></body>");
    doc.close();
  • ** HTML5新屬性:async和defer屬性 **
    ** defer屬性 **:IE4.0就出現(xiàn)。defer屬聲明腳本中將不會有document.write和dom修改勾哩。瀏覽器會并行下載其他有defer屬性的script抗蠢。而不會阻塞頁面后續(xù)處理。注:所有的defer腳本必須保證按順序執(zhí)行的思劳。
<script type="text/javascript" defer></script>

** async屬性 **:HTML5新屬性物蝙。腳本將在下載后盡快執(zhí)行,作用同defer敢艰,但是不能保證腳本按順序執(zhí)行诬乞。他們將在onload事件之前完成。

<script type="text/javascript" defer></script>

Firefox 3.6钠导、Opera 10.5震嫉、IE 9和最新的Chrome和Safari都支持async屬性∧凳簦可以同時(shí)使用async和defer票堵,這樣IE 4之后的所有IE都支持異步加載。
沒有async屬性逮栅,script將立即獲茹彩啤(下載)并執(zhí)行窗宇,期間阻塞了瀏覽器的后續(xù)處理。如果有async屬性特纤,那么script將被異步下載并執(zhí)行军俊,同時(shí)瀏覽器繼續(xù)后續(xù)的處理。


** 總結(jié) **: 對于支持HTML5的瀏覽器捧存,實(shí)現(xiàn)JS的異步加載只需要在script元素中加上async屬性粪躬,為了兼容老版本的IE還需加上defer屬性;對于不支持HTML5的瀏覽器(IE可以用defer實(shí)現(xiàn))昔穴,可以采用以上幾種方法實(shí)現(xiàn)镰官。原理基本上都是向DOM中寫入script或者通過eval函數(shù)執(zhí)行JS代碼,你可以把它放在匿名函數(shù)中執(zhí)行吗货,也可以在onload中執(zhí)行泳唠,也可以通過XHR注入實(shí)現(xiàn),也可以創(chuàng)建一個(gè)iframe元素宙搬,然后在iframe中執(zhí)行插入JS代碼笨腥。

設(shè)計(jì)一種方案,確保頁面中所有js加載完全

function loadScript (url, callback) {
var script = document.createElement('script')
script.type = 'text/javascript'
if (script.readyState) {
script.onreadystatechange = function () {
if (script.readyState == 'loaded' || script.readyState == 'complete') {
script.onreadystatechange = null
callback()
}
}
} else {
script.onload = function () {
callback()
}
}
script.src = url
document.getElementsByName('head')[0].appendChild(script)
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末害淤,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子拓售,更是在濱河造成了極大的恐慌窥摄,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,695評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件础淤,死亡現(xiàn)場離奇詭異崭放,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)鸽凶,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評論 3 399
  • 文/潘曉璐 我一進(jìn)店門币砂,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人玻侥,你說我怎么就攤上這事决摧。” “怎么了凑兰?”我有些...
    開封第一講書人閱讀 168,130評論 0 360
  • 文/不壞的土叔 我叫張陵掌桩,是天一觀的道長。 經(jīng)常有香客問我姑食,道長波岛,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,648評論 1 297
  • 正文 為了忘掉前任音半,我火速辦了婚禮则拷,結(jié)果婚禮上贡蓖,老公的妹妹穿的比我還像新娘。我一直安慰自己煌茬,他們只是感情好斥铺,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,655評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著宣旱,像睡著了一般仅父。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上浑吟,一...
    開封第一講書人閱讀 52,268評論 1 309
  • 那天笙纤,我揣著相機(jī)與錄音,去河邊找鬼组力。 笑死省容,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的燎字。 我是一名探鬼主播腥椒,決...
    沈念sama閱讀 40,835評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼候衍!你這毒婦竟也來了笼蛛?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,740評論 0 276
  • 序言:老撾萬榮一對情侶失蹤蛉鹿,失蹤者是張志新(化名)和其女友劉穎滨砍,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體妖异,經(jīng)...
    沈念sama閱讀 46,286評論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡惋戏,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,375評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了他膳。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片响逢。...
    茶點(diǎn)故事閱讀 40,505評論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖棕孙,靈堂內(nèi)的尸體忽然破棺而出舔亭,到底是詐尸還是另有隱情,我是刑警寧澤蟀俊,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布分歇,位于F島的核電站,受9級特大地震影響欧漱,放射性物質(zhì)發(fā)生泄漏职抡。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,873評論 3 333
  • 文/蒙蒙 一误甚、第九天 我趴在偏房一處隱蔽的房頂上張望缚甩。 院中可真熱鬧谱净,春花似錦、人聲如沸擅威。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽郊丛。三九已至李请,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間厉熟,已是汗流浹背导盅。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留揍瑟,地道東北人白翻。 一個(gè)月前我還...
    沈念sama閱讀 48,921評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像绢片,于是被迫代替她去往敵國和親滤馍。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,515評論 2 359

推薦閱讀更多精彩內(nèi)容