2017前端面試題之Js篇(1)

1 . 請解釋事件代理 (event delegation)

當(dāng)需要對很多元素添加事件的時试读,可以通過將事件添加到它們的父節(jié)點(diǎn)通過委托來觸發(fā)處理函數(shù)。其中利用到了瀏覽器的事件冒泡機(jī)制蚕泽。

var delegate = function(client, clientMethod) {
  return function() {
      return clientMethod.apply(client, arguments);
  }
}

var agentMethod = delegate (client, clientMethod);
agentMethod();


// 獲取父節(jié)點(diǎn)杆故,并為它添加一個click事件
document.getElementById("parent-list").addEventListener("click",function(e) {
  // 檢查事件源e.targe是否為Li
  if(e.target && e.target.nodeName.toUpperCase == "LI") {
    // 真正的處理過程在這里
    console.log("List item ",e.target.id.replace("post-")," was clicked!");
  }
});


2 . 談?wù)劄g覽器的事件冒泡機(jī)制

對于事件的捕獲和處理伴逸,不同的瀏覽器廠商有不同的處理機(jī)制蜀踏,我們以W3C對DOM2.0定義的標(biāo)準(zhǔn)事件為例
DOM2.0模型將事件處理流程分為三個階段:一、事件捕獲階段儿倒,二版保、事件目標(biāo)階段,三夫否、事件起泡階段彻犁。

  • 事件捕獲:當(dāng)某個元素觸發(fā)某個事件(如onclick),頂層對象document就會發(fā)出一個事件流慷吊,隨著DOM樹的節(jié)點(diǎn)向目標(biāo)元素節(jié)點(diǎn)流去袖裕,直到到達(dá)事件真正發(fā)生的目標(biāo)元素曹抬。在這個過程中溉瓶,事件相應(yīng)的監(jiān)聽函數(shù)是不會被觸發(fā)的。

  • 事件目標(biāo):當(dāng)?shù)竭_(dá)目標(biāo)元素之后谤民,執(zhí)行目標(biāo)元素該事件相應(yīng)的處理函數(shù)。如果沒有綁定監(jiān)聽函數(shù),那就不執(zhí)行黍特。

  • 事件起泡:從目標(biāo)元素開始瘟滨,往頂層元素傳播。途中如果有節(jié)點(diǎn)綁定了相應(yīng)的事件處理函數(shù)为牍,這些函數(shù)都會被一次觸發(fā)哼绑。如果想阻止事件起泡,可以使用e.stopPropagation()(Firefox)或者e.cancelBubble=true(IE)來組織事件的冒泡傳播碉咆。


3 . JavaScript 中 this 是如何工作的抖韩。

  • 作為函數(shù)調(diào)用,this 綁定全局對象疫铜,瀏覽器環(huán)境全局對象為 window 茂浮。
  • 內(nèi)部函數(shù)的 this 也綁定全局對象,應(yīng)該綁定到其外層函數(shù)對應(yīng)的對象上,這是 JavaScript的缺陷席揽,用that替換顽馋。
  • 作為構(gòu)造函數(shù)使用,this 綁定到新創(chuàng)建的對象幌羞。
  • 作為對象方法使用寸谜,this 綁定到該對象。
  • 使用apply或call調(diào)用 this 將會被顯式設(shè)置為函數(shù)調(diào)用的第一個參數(shù)属桦。

4 . 談?wù)凜ommonJs 程帕、AMD 和CMD

CommonJS規(guī)范,一個單獨(dú)的文件就是一個模塊地啰。每一個模塊都是一個單獨(dú)的作用域 CommonJS的使用代表:NodeJS

AMD 即Asynchronous Module Definition 異步模塊定義 它是一個在瀏覽器端模塊化開發(fā)的規(guī)范 AMD 是 RequireJS 在推廣過程中對模塊定義的規(guī)范化的產(chǎn)出

CMD 即Common Module Definition 通用模塊定義 其代表為SeaJS

requireJS主要解決兩個問題

  • 多個js文件可能有依賴關(guān)系愁拭,被依賴的文件需要早于依賴它的文件加載到瀏覽器
  • js加載的時候瀏覽器會停止頁面渲染,加載文件越多亏吝,頁面失去響應(yīng)時間越長

CMD和AMD的區(qū)別

  • AMD推崇依賴前置岭埠,在定義模塊的時候就要聲明其依賴的模塊
  • CMD推崇就近依賴,只有在用到某個模塊的時候再去require

5 . 談?wù)剬IFE的理解

IIFE即Immediately-Invoked Function Expression 立即執(zhí)行函數(shù)表達(dá)式

不推薦

(function(){})();

推薦

(function(){}());

在javascript里蔚鸥,括號內(nèi)部不能包含語句惜论,當(dāng)解析器對代碼進(jìn)行解釋的時候,先碰到了()止喷,然后碰到function關(guān)鍵字就會自動將()里面的代碼識別為函數(shù)表達(dá)式而不是函數(shù)聲明馆类。

知識拓展:

function(){ /* code */ }();  解釋下該代碼能正確執(zhí)行嗎?

不行弹谁,在javascript代碼解釋時乾巧,當(dāng)遇到function關(guān)鍵字時,會默認(rèn)把它當(dāng)做是一個函數(shù)聲明预愤,而不是函數(shù)表達(dá)式沟于,如果沒有把它顯視地表達(dá)成函數(shù)表達(dá)式,就報錯了植康,因為函數(shù)聲明需要一個函數(shù)名旷太,而上面的代碼中函數(shù)沒有函數(shù)名。(以上代碼销睁,也正是在執(zhí)行到第一個左括號(時報錯供璧,因為(前理論上是應(yīng)該有個函數(shù)名的。)

function foo(){ /* code */ }();  解釋下該代碼能正確執(zhí)行嗎冻记?

在一個表達(dá)式后面加上括號睡毒,表示該表達(dá)式立即執(zhí)行;而如果是在一個語句后面加上括號檩赢,該括號完全和之前的語句無法匹配吕嘀,而只是一個分組操作符违寞,用來控制運(yùn)算中的優(yōu)先級(小括號里的先運(yùn)算)相當(dāng)于先聲明了一個叫foo的函數(shù),之后進(jìn)行()內(nèi)的表達(dá)式運(yùn)算偶房,但是()(分組操作符)內(nèi)的表達(dá)式不能為空趁曼,所以報錯。(以上代碼棕洋,也就是執(zhí)行到右括號時挡闰,發(fā)現(xiàn)表達(dá)式為空,所以報錯)掰盘。


6 . .call 和 .apply 的區(qū)別是什么摄悯?

foo.call(this, arg1,arg2,arg3) == foo.apply(this, arguments)==this.foo(arg1, arg2, arg3)

call, apply方法區(qū)別是,從第二個參數(shù)起, call方法參數(shù)將依次傳遞給借用的方法作參數(shù), 而apply直接將這些參數(shù)放到一個數(shù)組中再傳遞, 最后借用方法的參數(shù)列表是一樣的.


7 . 請解釋 Function.prototype.bind?

bind() 方法的主要作用就是將函數(shù)綁定至某個對象愧捕,bind() 方法會創(chuàng)建一個函數(shù)奢驯,函數(shù)體內(nèi)this對象的值會被綁定到傳入bind() 函數(shù)的值。

原理

Function.prototype.bind = function(context) {
 var self = this; // 保存原函數(shù)
 return function() { // 返回一個新函數(shù)
  return self.apply(context, arguments); // 執(zhí)行新函數(shù)時次绘,將傳入的上下文context作為新函數(shù)的this
 }
}

用法:

var paint = {
 color: "red",
 count: 0,
 updateCount: function() {
  this.count++;
  console.log(this.count);
 }
};

// 事件處理函數(shù)綁定的錯誤方法:
document.querySelector('button')
 .addEventListener('click', paint.updateCount); // paint.updateCount函數(shù)的this指向變成了該DOM對象

// 事件處理函數(shù)綁定的正確方法:
document.querySelector('button')
 .addEventListener('click', paint.updateCount.bind(paint)); // paint.updateCount函數(shù)的this指向變成了paint

8 . 請解釋原型繼承 (prototypal inheritance) 的原理瘪阁。

當(dāng)查找一個對象的屬性時,JavaScript 會向上遍歷原型鏈邮偎,直到找到給定名稱的屬性為止管跺。——出自JavaScript秘密花園

JavaScript中的每個對象禾进,都有一個內(nèi)置的 proto 屬性豁跑。這個屬性是編程不可見的(雖然ES6標(biāo)準(zhǔn)中開放了這個屬性,然而瀏覽器對這個屬性的可見性的支持不同)泻云,它實際上是對另一個對象或者 null 的引用艇拍。

當(dāng)一個對象需要引用一個屬性時,JavaScript引擎首先會從這個對象自身的屬性表中尋找這個屬性標(biāo)識壶愤,如果找到則進(jìn)行相應(yīng)讀寫操作淑倾,若沒有在自身的屬性表中找到馏鹤,則在 proto 屬性引用的對象的屬性表中查找征椒,如此往復(fù),直到找到這個屬性或者 proto 屬性指向 null 為止湃累。

以下代碼展示了JS引擎如何查找屬性:

//__proto__ 是一個不應(yīng)在你代碼中出現(xiàn)的非正規(guī)的用法勃救,這里僅僅用它來解釋JavaScript原型繼承的工作原理。
function getProperty(obj, prop) {
if (obj.hasOwnProperty(prop))
    return obj[prop]
else if (obj.__proto__ !== null)
    return getProperty(obj.__proto__, prop)
else
    return undefined
}

JS的ECMA規(guī)范只允許我們采用 new 運(yùn)算符來進(jìn)行原型繼承

原型繼承

function Point(x, y) {
this.x = x;
this.y = y;
}
Point.prototype = {
    print: function () { console.log(this.x, this.y); }
};

var p = new Point(10, 20);
p.print(); // 10 20

順便闡述下new 運(yùn)算符是如何工作的?

  • 創(chuàng)建類的實例治力。這步是把一個空的對象的 proto 屬性設(shè)置為 F.prototype 蒙秒。
  • 初始化實例。函數(shù) F 被傳入?yún)?shù)并調(diào)用宵统,關(guān)鍵字 this 被設(shè)定為該實例晕讲。
  • 返回實例
function New (f) {
    var n = { '__proto__': f.prototype }; /*第一步*/
    return function () {
        f.apply(n, arguments);            /*第二步*/
        return n;                         /*第三步*/
    };
}

JavaScript中真正的原型繼承

Object.create = function (parent) {
    function F() {}
    F.prototype = parent;
    return new F();
};

使用真正的原型繼承(如 Object.create 以及 proto)還是存在以下缺點(diǎn):

  • 標(biāo)準(zhǔn)性差:proto 不是一個標(biāo)準(zhǔn)用法,甚至是一個不贊成使用的用法瓢省。同時原生態(tài)的 Object.create 和道爺寫的原版也不盡相同弄息。
  • 優(yōu)化性差: 不論是原生的還是自定義的 Object.create ,其性能都遠(yuǎn)沒有 new 的優(yōu)化程度高勤婚,前者要比后者慢高達(dá)10倍摹量。

ES6 內(nèi)部實現(xiàn)類和類的繼承

class Parent {
    constructor(name) { //構(gòu)造函數(shù)
          this.name = name;
    }
    say() {
          console.log("Hello, " + this.name + "!");
    }
}

class Children extends Parent {
    constructor(name) { //構(gòu)造函數(shù)
        super(name);    //調(diào)用父類構(gòu)造函數(shù)
        // ...
    }
    say() {
          console.log("Hello, " + this.name + "! hoo~~");
    }
}

參考:


9 . 請盡可能詳盡的解釋 AJAX 的工作原理

Ajax 的原理簡單來說通過 XmlHttpRequest 對象來向服務(wù)器發(fā)異步請求,從服務(wù)器獲得數(shù)據(jù)馒胆,然后用 JavaScript來操作 DOM 而更新頁面缨称。 這其中最關(guān)鍵的一步就是從服務(wù)器獲得請求數(shù)據(jù)。

不使用ajax工作原理

不使用ajax瀏覽網(wǎng)頁的原理

使用ajax工作原理

使用ajax網(wǎng)頁的原理
使用ajax網(wǎng)頁的原理

10 . javascript中"attribute" 和 "property" 的區(qū)別是什么祝迂?

property 和 attribute非常容易混淆睦尽,兩個單詞的中文翻譯也都非常相近(property:屬性,attribute:特性)型雳,但實際上骂删,二者是不同的東西,屬于不同的范疇四啰。每一個DOM對象都會有它默認(rèn)的基本屬性宁玫,而在創(chuàng)建的時候,它只會創(chuàng)建這些基本屬性柑晒,我們在TAG標(biāo)簽中自定義的屬性是不會直接放到DOM中的欧瘪。

  • property是DOM中的屬性,是JavaScript里的對象匙赞;
  • attribute是HTML標(biāo)簽上的特性佛掖,它的值只能夠是字符串;
  • DOM有其默認(rèn)的基本屬性涌庭,而這些屬性就是所謂的“property”芥被,無論如何,它們都會在初始化的時候再DOM對象上創(chuàng)建坐榆。
  • 如果在TAG對這些屬性進(jìn)行賦值拴魄,那么這些值就會作為初始值賦給DOM的同名property。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末席镀,一起剝皮案震驚了整個濱河市匹中,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌豪诲,老刑警劉巖顶捷,帶你破解...
    沈念sama閱讀 206,311評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異屎篱,居然都是意外死亡服赎,警方通過查閱死者的電腦和手機(jī)葵蒂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來重虑,“玉大人刹勃,你說我怎么就攤上這事『坑龋” “怎么了荔仁?”我有些...
    開封第一講書人閱讀 152,671評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長芽死。 經(jīng)常有香客問我乏梁,道長,這世上最難降的妖魔是什么关贵? 我笑而不...
    開封第一講書人閱讀 55,252評論 1 279
  • 正文 為了忘掉前任遇骑,我火速辦了婚禮,結(jié)果婚禮上揖曾,老公的妹妹穿的比我還像新娘落萎。我一直安慰自己,他們只是感情好炭剪,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評論 5 371
  • 文/花漫 我一把揭開白布练链。 她就那樣靜靜地躺著,像睡著了一般奴拦。 火紅的嫁衣襯著肌膚如雪媒鼓。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,031評論 1 285
  • 那天错妖,我揣著相機(jī)與錄音绿鸣,去河邊找鬼。 笑死暂氯,一個胖子當(dāng)著我的面吹牛潮模,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播痴施,決...
    沈念sama閱讀 38,340評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼擎厢,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了晾剖?” 一聲冷哼從身側(cè)響起锉矢,我...
    開封第一講書人閱讀 36,973評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎齿尽,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體灯节,經(jīng)...
    沈念sama閱讀 43,466評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡循头,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評論 2 323
  • 正文 我和宋清朗相戀三年绵估,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片卡骂。...
    茶點(diǎn)故事閱讀 38,039評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡国裳,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出全跨,到底是詐尸還是另有隱情缝左,我是刑警寧澤,帶...
    沈念sama閱讀 33,701評論 4 323
  • 正文 年R本政府宣布浓若,位于F島的核電站渺杉,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏挪钓。R本人自食惡果不足惜是越,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望碌上。 院中可真熱鬧倚评,春花似錦、人聲如沸馏予。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽霞丧。三九已至腿倚,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間蚯妇,已是汗流浹背敷燎。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留箩言,地道東北人硬贯。 一個月前我還...
    沈念sama閱讀 45,497評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像陨收,于是被迫代替她去往敵國和親饭豹。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評論 2 345

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