原型鏈的理解
- 看一個(gè)實(shí)例
var animal = function() {};
var dog = function() {};
animal.prototype.price = 20;
animal.price = 1000;
dog.prototype = animal;
var cat = new animal();
var tidy = new dog();
// 下面兩行分別輸出什么僚纷?
console.log(cat.price);
console.log(tidy.price);
-
原型和原型鏈?zhǔn)紫纫缼讉€(gè)概念:
- 在js里嫂便,繼承機(jī)制是原型繼承楼熄。繼承的起點(diǎn)是 對(duì)象的原型(Object prototype)忆绰。
- 一切皆為對(duì)象,只要是對(duì)象可岂,就會(huì)有 proto屬性错敢,該屬性存儲(chǔ)了指向其構(gòu)造的指針。
- Object prototype也是對(duì)象缕粹,其 proto指向null稚茅。
- 對(duì)象分為兩種:函數(shù)對(duì)象和普通對(duì)象,只有函數(shù)對(duì)象擁有『原型』對(duì)象(prototype)平斩。
- prototype的本質(zhì)是普通對(duì)象亚享。
- Function prototype比較特殊,是沒有prototype的函數(shù)對(duì)象绘面。
- new操作得到的對(duì)象是普通對(duì)象欺税。
當(dāng)調(diào)取一個(gè)對(duì)象的屬性時(shí),會(huì)先在本身查找揭璃,若無晚凿,就根據(jù) proto找到構(gòu)造原型,若無瘦馍,繼續(xù)往上找歼秽。最后會(huì)到達(dá)頂層Object prototype,它的 proto指向null情组,均無結(jié)果則返回undefined燥筷,結(jié)束。
-
由 proto 串起的路徑就是『原型鏈』院崇。
image cat調(diào)用price
① 查看本身荆责,沒有price,根據(jù) proto找到 animal prototype對(duì)象亚脆。
② 在animal prototype對(duì)象中找到了price做院,所以 cat.price 結(jié)果為20。
③ 如果無 animal.prototype=20濒持,則會(huì)根據(jù)animal prototype對(duì)象的 proto 找到Object prototype键耕,Object prototype的proto指向null娜搂,若仍沒有找到price坠陈,結(jié)果則為undefined琳拨。tidy調(diào)用price
① 查看本身斋竞,沒有price吐辙,根據(jù) proto找到dog prototype派撕。
② dog prototype = animal关摇,這里可以這樣理解:prototype本質(zhì)也是一個(gè)對(duì)象屑埋,因此可以重新賦一個(gè)對(duì)象,無論是函數(shù)對(duì)象還是普通對(duì)象惋嚎。事實(shí)上杠氢,每個(gè) prototype 會(huì)有一個(gè)預(yù)定義的constructor屬性用來引用它的函數(shù)對(duì)象。
③ 在animal中找到了price另伍, 所以 tidy.price 結(jié)果為1000鼻百。
④ 如果無 animal.price = 1000,則會(huì)根據(jù)animal的proto找到下一個(gè)對(duì)象摆尝,最終都沒有找到 price温艇,結(jié)果就為undefined。-
深入
- 創(chuàng)建一個(gè)對(duì)象的方式
- {}堕汞、new Object()
- 構(gòu)造函數(shù)
- Object.create()
此方法將新對(duì)象的proto更改并指向create的入?yún)?duì)象勺爱。
- instance of VS constructor
- instance of 原理:檢查左邊對(duì)象與右邊對(duì)象是否在同一條原型鏈上。
- constructor原理:取對(duì)象的proto屬性指向的prototype對(duì)象上的constructor字段讯检。
- 創(chuàng)建一個(gè)對(duì)象的方式
cat instanceof animal === true
cat.__proto__ === animal.prototype
animal.prototype instanceof Object === true
animal.prototype.__proto__ === Object.prototype
cat instanceof Object === true
// but琐鲁,
cat.constructor === animal // true
cat.constructor === Object // false
- new運(yùn)算符的原理
- 創(chuàng)建一個(gè)空對(duì)象,它的proto等于構(gòu)造函數(shù)的原型對(duì)象(可以用Object.create()完成)
- 構(gòu)造函數(shù)以第1步創(chuàng)建的對(duì)象做為上下文视哑,是否會(huì)返回一個(gè)對(duì)象
- 若第2步返回了對(duì)象绣否,則使用該對(duì)象作為新實(shí)例,否則用第1步創(chuàng)建的對(duì)象作為新實(shí)例
var myNew = function (func) {
var o = Object.create(func.prototype)
var i = func.call(o)
return typeof i === 'object' ? i : o
}
-
繼承
- 類的聲明
- function
- class
- 類的聲明
生成實(shí)例:new
-
繼承的幾種方式:
- 借助構(gòu)造函數(shù)挡毅,父類的作用域指向子類
- Parent.call(this) // this是Child類的上下文
- 缺點(diǎn):不能繼承原型鏈屬性
- 借助原型鏈
- Child.prototype = new Parent()
- 缺點(diǎn):子類所有實(shí)例共享原型對(duì)象蒜撮;子類實(shí)例的constructor為Parent
-
組合方式
- Parent.call(this) // this是Child類的上下文
- Child.prototype = Object.create(Parent.prototype)
- Child.prototype.constructor = Child
.bind()、.live()跪呈、.delegate()和.on()之間的區(qū)別
- bind
.bind()方法將會(huì)把事件處理函數(shù)連接到所有匹配的標(biāo)簽段磨。這種方式并不好。這樣做的話耗绿,它不僅在所有匹配的元素中隱含地迭代附加事件處理函數(shù)苹支,而且這些操作非常浪費(fèi)(多余),因?yàn)檫@些相同的事件處理函數(shù)是被一遍一遍的重復(fù)的添加到所有匹配的標(biāo)簽上误阻。- 優(yōu)點(diǎn):
- 適用于各種瀏覽器
- 連接事件處理函數(shù)非常方便快捷
- 可以使用 .click() , .hover()等簡(jiǎn)寫方法來更方面地連接事件處理函數(shù)
- 對(duì)于一個(gè)簡(jiǎn)單的ID選擇器,使用.bind() 方法不僅可以很快地連接事件處理函數(shù),而且當(dāng)事件被觸發(fā)時(shí), 事件處理函數(shù)幾乎是馬上就被調(diào)用了
- 缺點(diǎn):
- 這樣方法會(huì)將所有的事件處理函數(shù)附加到所有匹配的元素
- 不可以動(dòng)態(tài)地匹配相同選擇器的元素
- 當(dāng)操作大量匹配的元素時(shí)會(huì)有性能方面的問題
- 附加操作是在前期完成的,這可能導(dǎo)致頁面加載時(shí)存在性能問題
- 優(yōu)點(diǎn):
- Live
.live()方法使用了事件委托的概念來實(shí)施其所謂的“魔法”债蜜。你調(diào)用live()方法的方式就像是調(diào)用bind()方法那樣方便。然而在這表面之下究反, .live()方法與前者的實(shí)現(xiàn)方式大不相同寻定。 .live()方法將與事件處理函數(shù)關(guān)聯(lián)的選擇器和事件信息一起附加到文檔的根級(jí)元素(即document)。通過將事件信息注冊(cè)到document上精耐,這個(gè)事件處理函數(shù)將允許所有冒泡到document的事件調(diào)用它(例如委托型狼速、傳播型事件)。一旦有一個(gè)事件冒泡到document元素上卦停,Jquery會(huì)根據(jù)選擇器或者事件的元數(shù)據(jù)來決定哪一個(gè)事件處理函數(shù)應(yīng)該被調(diào)用向胡,如果這個(gè)事件處理函數(shù)存在的話恼蓬。這個(gè)額外的工作將會(huì)在用戶交互時(shí)對(duì)性能方面造成一定的影響,但是初始化注冊(cè)事件的過程相當(dāng)?shù)乜臁?/li>
/* 方法將與事件處理函數(shù)關(guān)聯(lián)的選擇器和事件信息一起附加到文檔的根級(jí)元素(即document) ( "#members li a" & "click" ) */
$( "#members li a" ).live( "click", function( e ) {} );
.bind()這個(gè)例子與上面bind()方法的例子對(duì)比的話有一個(gè)優(yōu)點(diǎn)在于它僅僅把事件處理函數(shù)附加到document元素一次僵芹,而不是很多次处硬。這樣不僅更快,而且還減少了性能的浪費(fèi)淮捆。然而郁油,使用這個(gè)方法也會(huì)帶來很多問題本股,下面將一一列出攀痊。
-
優(yōu)點(diǎn):
- 所有的事件處理函數(shù)都只會(huì)被注冊(cè)一次,而不是像bind()那樣進(jìn)行多次注冊(cè)
- 將bind()方法升級(jí)到live()方法非常方便拄显,你僅需要將"bind"替代為"live"就可以了
- 那些被動(dòng)態(tài)添加到DOM的元素也將被神奇的匹配到苟径,因?yàn)檎鎸?shí)的事件信息是被注冊(cè)到document元素上的
你可以在文檔加載完之前連接事件處理函數(shù),這樣可以幫助你更好地利用你可能沒有用的時(shí)間
-
缺點(diǎn):
- 這個(gè)方法在Jquery 1.7以后的版本被棄用了躬审,你應(yīng)該在你的代碼里逐步放棄使用它
- 使用這個(gè)方法時(shí)鏈?zhǔn)讲僮鳑]有得到正確的支持棘街,可能會(huì)出現(xiàn)某些錯(cuò)誤
- 所做的匹配操作基本上沒用因?yàn)樗挥糜谠赿ocument元素上注冊(cè)事件處理函數(shù)
- 使用 event.stopPropogation() 方法將會(huì)沒用,因?yàn)槭录偸且呀?jīng)被委托到了document元素上
- 因?yàn)樗械倪x擇器或者事件信息都被附加到document元素上了承边,所以 一旦有一個(gè)事件要調(diào)用某個(gè)事件處理函數(shù)遭殉,Jquery會(huì)在一大堆儲(chǔ)存的元數(shù)據(jù)中使用matchesSelector方法來決定哪一個(gè)事件處理函數(shù)將會(huì)被調(diào)用,如果這個(gè)函數(shù)有的話博助。
- 因?yàn)槟闼B接的事件總是被委托到document上险污,所如果你的DOM的層級(jí)很深的話,這會(huì)導(dǎo)致一定的性能問題
Delegate
.delegate()方法與live()方式實(shí)現(xiàn)方式相類似富岳,它不是將選擇器或者事件信息附加到document蛔糯,而是讓你指定附加的元素。就像是live()方法一樣窖式,這個(gè)方法使用事件委托來正確地工作蚁飒。
如果你跳過了前面關(guān)于 .live() 方法的介紹,你可能要回去重新看看它萝喘,因?yàn)檫@里涉及到之前我所闡述的一些內(nèi)部邏輯
/* .delegate() 方法會(huì)將選擇器和事件信息 ( "li a" & "click" ) 附加到你指定的元素上 ( "#members" )淮逻。
*/
$( "#members" ).delegate( "li a", "click", function( e ) {} );
.delegate()方法十分強(qiáng)大。在上面這個(gè)例子中阁簸,與事件處理函數(shù)關(guān)聯(lián)的選擇器和事件信息將會(huì)被附加到( #members" )這個(gè)元素上爬早。這樣做比使用live()高效多了,因?yàn)閘ive()方法總是將與事件處理函數(shù)關(guān)聯(lián)的選擇器和事件信息附加到document元素上强窖。另外凸椿,使用.delegate()方法解決許多其他問題。請(qǐng)參閱下方列出的詳細(xì)信息翅溺。
-
優(yōu)點(diǎn):
- 你可以選擇將選擇器或者事件信息附加到指定的元素脑漫。
- 匹配操作實(shí)際上在前面并沒有執(zhí)行髓抑,而是用來注冊(cè)到指定的元素。
- 鏈?zhǔn)讲僮骺梢缘玫秸_的支持
- Jquery仍然需要迭代這些選擇器或者事件信息來匹配元素优幸,不過因?yàn)槟憧梢赃x擇哪一個(gè)元素作為根元素吨拍,所以篩選的量會(huì)大幅減少
因?yàn)檫@項(xiàng)技術(shù)使用了事件委托機(jī)制,它可以匹配到被動(dòng)態(tài)地添加到DOM的元素 - 你可以在文檔加載完之前連接事件處理函數(shù)
-
缺點(diǎn):
- 從.bind()方法不可以直接升級(jí)到.delegate()方法
- Jquery仍然需要使用marchesSelector方法在附加到指定根元素的選擇器或者事件信息中篩選決定哪一個(gè)事件處理函數(shù)會(huì)被調(diào)用网杆。然而羹饰,附加到指定根元素的元數(shù)據(jù)會(huì)比使用live()方法的時(shí)候要小得多。
當(dāng)操作大量匹配的元素時(shí)會(huì)有性能方面的問題 - 附加操作是在前期完成的,這可能導(dǎo)致頁面加載時(shí)存在性能問題
On
你知道嗎碳却,在Jquery 1.7版本中.bind() 队秩, .live() 和.delegate()方法只需要使用.on()方法一種方式來調(diào)用它們。當(dāng)然.unbind() 昼浦, .die() 和.undelegate()方法也一樣馍资。一下代碼片段是從Jquery 1.7版本的源碼中截取出來的
bind: function( types, data, fn ) {
return this.on( types, null, data, fn );
},
unbind: function( types, fn ) {
return this.off( types, null, fn );
},
live: function( types, data, fn ) {
jQuery( this.context ).on( types, this.selector, data, fn );
return this;
},
die: function( types, fn ) {
jQuery( this.context ).off( types, this.selector || "**", fn );
return this;
},
delegate: function( selector, types, data, fn ) {
return this.on( types, selector, data, fn );
},
undelegate: function( selector, types, fn ) {
return arguments.length == 1 ?
this.off( selector, "**" ) :
this.off( types, selector, fn );
}
//考慮到這一點(diǎn),使用.on()方法看起來像以下方式一樣...
/* Jquery的 .bind() , .live() 和 .delegate() 方法只需要使用`.on()`方法一種方式來調(diào)用它們 */
// Bind
$( "#members li a" ).on( "click", function( e ) {} );
$( "#members li a" ).bind( "click", function( e ) {} );
// Live
$( document ).on( "click", "#members li a", function( e ) {} );
$( "#members li a" ).live( "click", function( e ) {} );
// Delegate
$( "#members" ).on( "click", "li a", function( e ) {} );
$( "#members" ).delegate( "li a", "click", function( e ) {} );
你可能注意到了关噪,我如何使用.on()方法決定了它如何調(diào)用其他方法鸟蟹。你可以認(rèn)為.on()方法被具有不同簽名的方法”重載“了,而這些方法實(shí)現(xiàn)了不同的事件綁定的連接方式使兔。 .on()方法的出現(xiàn)為API帶來了很多方面的一致性建钥,并希望讓事情變得不那么混亂。
- 優(yōu)點(diǎn):
- 使各種事件綁定方法一致虐沥。
- 因?yàn)樵贘query源碼中.bind() 熊经, .live() 和.delegate()方法實(shí)際上是調(diào)用了此方法,因此簡(jiǎn)化了jQuery代碼庫并刪除了一級(jí)重定向置蜀。
- 這種方式仍然提供了使用.delegate()方法的優(yōu)點(diǎn)奈搜,并且仍然提供對(duì).bind()方法的支持,如果你需要的話盯荤。
- 缺點(diǎn):
- 給人帶來了一些疑惑馋吗,因?yàn)榉椒ǖ膶?shí)際執(zhí)行方式將根據(jù)你如何調(diào)用方法而改變。
- 總結(jié)
使用.bind()方法非常浪費(fèi)性能因?yàn)樗淹粋€(gè)事件處理函數(shù)附加到了每一個(gè)匹配的元素上
你應(yīng)該停止使用.live()方法因?yàn)樗粭売昧送瑫r(shí)也會(huì)帶來很多問題
使用.delegate()方法會(huì)給你帶來很多好處當(dāng)你需要解決一些性能上的問題和對(duì)動(dòng)態(tài)添加的元素作出處理
新的.on()方法其實(shí)就是模擬.bind() 秋秤, .live() 和.delegate()實(shí)現(xiàn)的語法糖宏粤,具體取決于你如何調(diào)用它
新的方向是使用新的.on()方法。先熟悉語法灼卢,并開始在你的所有的Jquery 1.7版本以上的項(xiàng)目使用它吧绍哎!
狀態(tài)碼說明
- 1**
信息,服務(wù)器收到請(qǐng)求鞋真,需要請(qǐng)求者繼續(xù)執(zhí)行操作 - 2**
成功崇堰,操作被成功接收并處理 - 3**
重定向,需要進(jìn)一步的操作以完成請(qǐng)求 - 4**
客戶端錯(cuò)誤,請(qǐng)求包含語法錯(cuò)誤或無法完成請(qǐng)求 - 5**
服務(wù)器錯(cuò)誤海诲,服務(wù)器在處理請(qǐng)求的過程中發(fā)生了錯(cuò)誤 - 100
繼續(xù) - 101
切換協(xié)議繁莹。服務(wù)器根據(jù)客戶端的請(qǐng)求切換協(xié)議。只能切換到更高級(jí)的協(xié)議特幔,例如咨演,切換到HTTP的新版本協(xié)議 - 200
OK 、請(qǐng)求成功蚯斯。一般用于GET與POST請(qǐng)求 - 201
已創(chuàng)建薄风。成功請(qǐng)求并創(chuàng)建了新的資源 - 202
已接受。已經(jīng)接受請(qǐng)求拍嵌,但未處理完成 - 203
非授權(quán)信息遭赂。請(qǐng)求成功。但返回的meta信息不在原始的服務(wù)器撰茎,而是一個(gè)副本 - 204
無內(nèi)容嵌牺。服務(wù)器成功處理打洼,但未返回內(nèi)容龄糊。在未更新網(wǎng)頁的情況下,可確保瀏覽器繼續(xù)顯示當(dāng)前文檔 - 205
重置內(nèi)容募疮。服務(wù)器處理成功炫惩,用戶終端(例如:瀏覽器)應(yīng)重置文檔視圖“⑴ǎ可通過此返回碼清除瀏覽器的表單域 - 206
部分內(nèi)容他嚷。服務(wù)器成功處理了部分GET請(qǐng)求 - 300
多種選擇。請(qǐng)求的資源可包括多個(gè)位置芭毙,相應(yīng)可返回一個(gè)資源特征與地址的列表用于用戶終端(例如:瀏覽器)選擇 - 301
永久移動(dòng)筋蓖。請(qǐng)求的資源已被永久的移動(dòng)到新URI,返回信息會(huì)包括新的URI退敦,瀏覽器會(huì)自動(dòng)定向到新URI粘咖。今后任何新的請(qǐng)求都應(yīng)使用新的URI代替 - 302
臨時(shí)移動(dòng)。與301類似侈百。但資源只是臨時(shí)被移動(dòng)瓮下。客戶端應(yīng)繼續(xù)使用原有URI - 303
查看其它地址钝域。與301類似讽坏。使用GET和POST請(qǐng)求查看 - 304
未修改。所請(qǐng)求的資源未修改例证,服務(wù)器返回此狀態(tài)碼時(shí)路呜,不會(huì)返回任何資源。客戶端通常會(huì)緩存訪問過的資源胀葱,通過提供一個(gè)頭信息指出客戶端希望只返回在指定日期之后修改的資源 - 305
使用代理党涕。所請(qǐng)求的資源必須通過代理訪問 - 306
已經(jīng)被廢棄的HTTP狀態(tài)碼 - 307
臨時(shí)重定向。與302類似巡社。使用GET請(qǐng)求重定向 - 400
客戶端請(qǐng)求的語法錯(cuò)誤膛堤,服務(wù)器無法理解 - 401
請(qǐng)求要求用戶的身份認(rèn)證 - 402
保留,將來使用 - 403
服務(wù)器理解請(qǐng)求客戶端的請(qǐng)求晌该,但是拒絕執(zhí)行此請(qǐng)求 - 404
服務(wù)器無法根據(jù)客戶端的請(qǐng)求找到資源(網(wǎng)頁)肥荔。通過此代碼,網(wǎng)站設(shè)計(jì)人員可設(shè)置"您所請(qǐng)求的資源無法找到"的個(gè)性頁面 - 405
客戶端請(qǐng)求中的方法被禁止 - 406
服務(wù)器無法根據(jù)客戶端請(qǐng)求的內(nèi)容特性完成請(qǐng)求 - 407
請(qǐng)求要求代理的身份認(rèn)證朝群,與401類似燕耿,但請(qǐng)求者應(yīng)當(dāng)使用代理進(jìn)行授權(quán) | - 408
服務(wù)器等待客戶端發(fā)送的請(qǐng)求時(shí)間過長(zhǎng),超時(shí) - 409
服務(wù)器完成客戶端的 PUT 請(qǐng)求時(shí)可能返回此代碼姜胖,服務(wù)器處理請(qǐng)求時(shí)發(fā)生了沖突 - 410
客戶端請(qǐng)求的資源已經(jīng)不存在誉帅。410不同于404,如果資源以前有現(xiàn)在被永久刪除了可使用410代碼右莱,網(wǎng)站設(shè)計(jì)人員可通過301代碼指定資源的新位置 - 411
服務(wù)器無法處理客戶端發(fā)送的不帶Content-Length的請(qǐng)求信息 - 412
客戶端請(qǐng)求信息的先決條件錯(cuò)誤 - 413
由于請(qǐng)求的實(shí)體過大蚜锨,服務(wù)器無法處理,因此拒絕請(qǐng)求慢蜓。為防止客戶端的連續(xù)請(qǐng)求亚再,服務(wù)器可能會(huì)關(guān)閉連接。如果只是服務(wù)器暫時(shí)無法處理晨抡,則會(huì)包含一個(gè)Retry-After的響應(yīng)信息 - 414
請(qǐng)求的URI過長(zhǎng)(URI通常為網(wǎng)址)氛悬,服務(wù)器無法處理 - 415
服務(wù)器無法處理請(qǐng)求附帶的媒體格式 - 416
客戶端請(qǐng)求的范圍無效 - 417
服務(wù)器無法滿足Expect的請(qǐng)求頭信息 - 500
服務(wù)器內(nèi)部錯(cuò)誤,無法完成請(qǐng)求 - 501
服務(wù)器不支持請(qǐng)求的功能耘柱,無法完成請(qǐng)求 - 502
作為網(wǎng)關(guān)或者代理工作的服務(wù)器嘗試執(zhí)行請(qǐng)求時(shí)如捅,從遠(yuǎn)程服務(wù)器接收到了一個(gè)無效的響應(yīng) - 503
由于超載或系統(tǒng)維護(hù),服務(wù)器暫時(shí)的無法處理客戶端的請(qǐng)求调煎。延時(shí)的長(zhǎng)度可包含在服務(wù)器的Retry-After頭信息中 - 504
充當(dāng)網(wǎng)關(guān)或代理的服務(wù)器镜遣,未及時(shí)從遠(yuǎn)端服務(wù)器獲取請(qǐng)求 - 505
服務(wù)器不支持請(qǐng)求的HTTP協(xié)議的版本,無法完成處理
promise汛蝙、generator烈涮、async/await怎么使用,有什么區(qū)別
-
異步編程的方法有下面四種
- 回調(diào)函數(shù)
- 事件監(jiān)聽
- 發(fā)布/訂閱
- Promise對(duì)象
- async/await
回調(diào)函數(shù)
所謂回調(diào)函數(shù)(callback)窖剑,就是把任務(wù)分成兩步完成坚洽,第二步單獨(dú)寫在一個(gè)函數(shù)里面,等到重新執(zhí)行這個(gè)任務(wù)時(shí)西土,就直接調(diào)用這個(gè)函數(shù)讶舰。
// 例如Node.js中讀取文件
fs.readFile('a,txt', (err,data) = >{
if(err) throw err;
console.log(data);
})
上面代碼中readFile的第二個(gè)參數(shù)就是回調(diào)函數(shù),等到讀取完a.txt文件時(shí),這個(gè)函數(shù)才會(huì)執(zhí)行跳昼。
- Promise
使用回調(diào)函數(shù)本身沒有問題般甲,但有“回調(diào)地獄”的問題。
假定我們有一個(gè)需求鹅颊,讀取完A文件之后讀取B文件敷存,再讀取C文件,代碼如下
fs.readFile(fileA, (err, data) => {
fs.readFile(fileB, (err, data) => {
fs.readFile(fileC, (err,data)=>{
//do something
})
});
});
//這時(shí)候Promise出現(xiàn)了堪伍!它不是新的功能锚烦,而是一種新的寫法,用來解決“回調(diào)地獄”的問題帝雇。
/**
* 傳入?yún)?shù) n涮俄,表示這個(gè)函數(shù)執(zhí)行的時(shí)間(毫秒)
* 執(zhí)行的結(jié)果是 n + 200,這個(gè)值將用于下一步驟
*/
function A(n) {
return new Promise(resolve => {
setTimeout(() => resolve(n + 200), n);
});
}
function step1(n) {
console.log(`step1 with ${n}`);
return A(n);
}
function step2(n) {
console.log(`step2 with ${n}`);
return A(n);
}
function step3(n) {
console.log(`step3 with ${n}`);
return A(n);
}
上面代碼中有4個(gè)函數(shù)尸闸,A()返回一個(gè)Promise對(duì)象彻亲,接收參數(shù)n,n秒后執(zhí)行resolve(n+200)吮廉。step1苞尝、 step2、step3對(duì)應(yīng)三個(gè)步驟
現(xiàn)在用Promise實(shí)現(xiàn)這三個(gè)步驟:
function doIt() {
console.time('do it now')
const time1 = 300;
step1(time1)
.then( time2 =>step2(time2))
.then( time3 => step3(time3))
.then( result => {
console.log(`result is ${result}`)
});
}
doIt();
// 輸出結(jié)果如下
step1 with 300
step2 with 500
step3 with 700
result is 900
result是step3()的參數(shù)700+200 = 900茧痕。
可見野来,Promise的寫法只是回調(diào)函數(shù)的改進(jìn),用then()方法免去了嵌套踪旷,更為直觀。
但這樣寫絕不是最好的豁辉,代碼變得十分冗余令野,一堆的then。
所以徽级,最優(yōu)秀的解決方案是什么呢气破?
開頭暴露了,就是async/await
講async前我們先講講協(xié)程與Generator
- 協(xié)程
協(xié)程(coroutine)餐抢,意思是多個(gè)線程相互協(xié)作现使,完成異步任務(wù)。
它的運(yùn)行流程如下
協(xié)程A開始執(zhí)行
協(xié)程A執(zhí)行到一半旷痕,暫停執(zhí)行碳锈,執(zhí)行的權(quán)利轉(zhuǎn)交給協(xié)程B。
一段時(shí)間后B交還執(zhí)行權(quán)
協(xié)程A重得執(zhí)行權(quán)欺抗,繼續(xù)執(zhí)行
上面的協(xié)程A就是一個(gè)異步任務(wù)售碳,因?yàn)樵趫?zhí)行過程中執(zhí)行權(quán)被B搶了,被迫分成兩步完成。
讀取文件的協(xié)程代碼如下:
function task() {
// 其他代碼
var f = yield readFile('a.txt')
// 其他代碼
}
task()函數(shù)就是一個(gè)協(xié)程贸人,函數(shù)內(nèi)部有個(gè)新單詞yield间景,yield中文意思為退讓,
顧名思義艺智,它表示執(zhí)行到此處倘要,task協(xié)程該交出它的執(zhí)行權(quán)了。也可以把yield命令理解為異步兩個(gè)階段的分界線十拣。
協(xié)程遇到y(tǒng)ield命令就會(huì)暫停碗誉,把執(zhí)行權(quán)交給其他協(xié)程,等到執(zhí)行權(quán)返回繼續(xù)往后執(zhí)行父晶。最大的優(yōu)點(diǎn)就是代碼寫法和同步操作幾乎沒有差別哮缺,只是多了yield命令。
這也是異步編程追求的甲喝,讓它更像同步編程
- Generator函數(shù)
Generator是協(xié)程在ES6的實(shí)現(xiàn)尝苇,最大的特點(diǎn)就是可以交出函數(shù)的執(zhí)行權(quán),懂得退讓埠胖。
function* gen(x) {
var y = yield x +2;
return y;
}
var g = gen(1);
console.log( g.next()) // { value: 3, done: false }
console.log( g.next()) // { value: undefined, done: true }
上面代碼中糠溜,函數(shù)多了*號(hào),用來表示這是一個(gè)Generator函數(shù)直撤,和普通函數(shù)不一樣非竿,不同之處在于執(zhí)行它不會(huì)返回結(jié)果,
返回的是指針對(duì)象g谋竖,這個(gè)指針g有個(gè)next方法红柱,調(diào)用它會(huì)執(zhí)行異步任務(wù)的第一步。
對(duì)象中有兩個(gè)值蓖乘,value和done锤悄,value 屬性是 yield 語句后面表達(dá)式的值,表示當(dāng)前階段的值嘉抒,done表示是否Generator函數(shù)是否執(zhí)行完畢零聚。
下面看看Generator函數(shù)如何執(zhí)行一個(gè)真實(shí)的異步任務(wù)
var fetch = require('node-fetch');
function gen(){
var url = 'https://api.github.com/users/github';
var result = yield fetch(url);
console.log(result.bio);
}
var g = gen();
var result = g.next();
result.value.then( data => return data.json)
.then (data => g.next(data))
上面代碼中,首先執(zhí)行Generator函數(shù)些侍,得到對(duì)象g隶症,調(diào)用next方法,此時(shí)
result ={ value: Promise { <pending> }, done: false }
因?yàn)閒etch返回的是一個(gè)Promise對(duì)象岗宣,(即value是一個(gè)Promise對(duì)象)所以要用then才能調(diào)用下一個(gè)next方法蚂会。
雖然Generator將異步操作表示得很簡(jiǎn)潔,但是管理麻煩狈定,何時(shí)執(zhí)行第一階段颂龙,又何時(shí)執(zhí)行第二階段习蓬?
是的,這時(shí)候到Async/await出現(xiàn)了措嵌!
- Async/await
從回調(diào)函數(shù)躲叼,到Promise對(duì)象,再到Generator函數(shù)企巢,JavaScript異步編程解決方案歷程可謂辛酸枫慷,終于到了Async/await。很多人認(rèn)為它是異步操作的最終解決方案(謝天謝地浪规,這下不用再學(xué)新的解決方案了吧)
其實(shí)async函數(shù)就是Generator函數(shù)的語法糖或听,例如下面兩個(gè)代碼:
var gen = function* (){
var f1 = yield readFile('./a.txt');
var f2 = yield readFile('./b.txt');
console.log(f1.toString());
console.log(f2.toString());
};
var asyncReadFile = async function (){
var f1 = await readFile('./a.txt');
var f2 = await readFile('./b.txt');
console.log(f1.toString());
console.log(f2.toString());
};
上面的為Generator函數(shù)讀取兩個(gè)文件,下面為async/await讀取笋婿,比較可發(fā)現(xiàn)誉裆,兩個(gè)函數(shù)其實(shí)是一樣的,async不過是把Generator函數(shù)的*號(hào)換成async缸濒,yield換成await足丢。
1.async函數(shù)用法
上面說了async不過是Generator函數(shù)的語法糖,那為什么要取這個(gè)名字呢庇配?自然是有理由的斩跌。
async是“異步”,而await是async wait的簡(jiǎn)寫捞慌,即異步等待耀鸦。所以應(yīng)該很好理解async用于聲明一個(gè)function是異步的,await用于等待一個(gè)異步方法執(zhí)行完成
下面來看一個(gè)例子理解async命令的作用
async function test() {
return "async 有什么用啸澡?";
}
const result = test();
console.log(result)
輸出:
Promise { 'async 有什么用袖订?' }
可以看到,輸出的是一個(gè)Promise對(duì)象锻霎!
所以著角,async函數(shù)返回的是一個(gè)Promise對(duì)象,如果直接return 一個(gè)直接量旋恼,async會(huì)把這個(gè)直接量通過PromIse.resolve()封裝成Promise對(duì)象
注意點(diǎn)
一般來說,都認(rèn)為await是在等待一個(gè)async函數(shù)完成奄容,確切的說等待的是一個(gè)表示式冰更,這個(gè)表達(dá)式的計(jì)算結(jié)果是Promise對(duì)象或者是其他值(沒有限定是什么)
即await后面不僅可以接Promise,還可以接普通函數(shù)或者直接量昂勒。
同時(shí)蜀细,我們可以把a(bǔ)sync理解為一個(gè)運(yùn)算符,用于組成表達(dá)式戈盈,表達(dá)式的結(jié)果取決于它等到的東西
等到非Promise對(duì)象 表達(dá)式結(jié)果為它等到的東西
等到Promise對(duì)象 await就會(huì)阻塞后面的代碼奠衔,等待Promise對(duì)象resolve谆刨,取得resolve的值,作為表達(dá)式的結(jié)果
還是那個(gè)業(yè)務(wù)归斤,分多個(gè)步驟完成,每個(gè)步驟依賴于上一個(gè)步驟的結(jié)果,用setTimeout模擬異步操作液南。
/**
* 傳入?yún)?shù) n球切,表示這個(gè)函數(shù)執(zhí)行的時(shí)間(毫秒)
* 執(zhí)行的結(jié)果是 n + 200,這個(gè)值將用于下一步驟
*/
function takeLongTime(n) {
return new Promise(resolve => {
setTimeout(() => resolve(n + 200), n);
});
}
function step1(n) {
console.log(`step1 with ${n}`);
return takeLongTime(n);
}
function step2(n) {
console.log(`step2 with ${n}`);
return takeLongTime(n);
}
function step3(n) {
console.log(`step3 with ${n}`);
return takeLongTime(n);
}
async實(shí)現(xiàn)方法
async function doIt() {
console.time("doIt");
const time1 = 300;
const time2 = await step1(time1);
const time3 = await step2(time2);
const result = await step3(time3);
console.log(`result is ${result}`);
console.timeEnd("doIt");
}
doIt();
輸出結(jié)果和上面用Promise實(shí)現(xiàn)是一樣的迫横,但這個(gè)代碼結(jié)構(gòu)看起來清晰得多番舆,幾乎跟同步寫法一樣。
- async函數(shù)的優(yōu)點(diǎn)
(1)內(nèi)置執(zhí)行器
Generator 函數(shù)的執(zhí)行必須靠執(zhí)行器矾踱,所以才有了 co 函數(shù)庫恨狈,而 async 函數(shù)自帶執(zhí)行器。也就是說呛讲,async 函數(shù)的執(zhí)行禾怠,與普通函數(shù)一模一樣,只要一行圣蝎。
(2) 語義化更好
async 和 await刃宵,比起星號(hào)和 yield,語義更清楚了徘公。async 是“異步”的簡(jiǎn)寫牲证,而 await 可以認(rèn)為是 async wait 的簡(jiǎn)寫。所以應(yīng)該很好理解 async 用于申明一個(gè) function 是異步的关面,而 await 用于等待一個(gè)異步方法執(zhí)行完成坦袍。
(3)更廣的適用性
yield 命令后面只能是 Thunk 函數(shù)或 Promise 對(duì)象,而 async 函數(shù)的 await 命令后面等太,可以跟 Promise 對(duì)象和原始類型的值(數(shù)值捂齐、字符串和布爾值,但這時(shí)等同于同步操作
js中的繼承?
- 原型鏈繼承 JavaScript實(shí)現(xiàn)繼承的基本思想:通過原型將一個(gè)引用類型繼承另一個(gè)引用類型的屬性和方法缩抡。
- 借用構(gòu)造函數(shù)繼承(偽造對(duì)象或經(jīng)典繼承) JavaScript實(shí)現(xiàn)繼承的基本思想:在子類構(gòu)造函數(shù)內(nèi)部調(diào)用超類型構(gòu)造函數(shù)奠宜。 通過使用apply()和call()方法可以在新創(chuàng)建的子類對(duì)象上執(zhí)行構(gòu)造函數(shù)。
- 組合繼承(原型+借用構(gòu)造)(偽經(jīng)典繼承) JavaScript實(shí)現(xiàn)繼承的基本思想:將原型鏈和借用構(gòu)造函數(shù)的技術(shù)組合在一塊瞻想,從而發(fā)揮兩者之長(zhǎng)的一種繼承模式压真。
- 將原型鏈和借用構(gòu)造函數(shù)的技術(shù)組合到一起,從而取長(zhǎng)補(bǔ)短發(fā)揮兩者長(zhǎng)處的一種繼承模式蘑险。
- 原型式繼承 JavaScript實(shí)現(xiàn)繼承的基本思想:借助原型可以基于已有的對(duì)象創(chuàng)建新對(duì)象滴肿,同時(shí)還不必須因此創(chuàng)建自定義的類型。
- 寄生式繼承 JavaScript實(shí)現(xiàn)繼承的基本思想:創(chuàng)建一個(gè)僅用于封裝繼承過程的函數(shù)佃迄,該函數(shù)在內(nèi)部以某種方式來增強(qiáng)對(duì)象泼差,最后再像真正是它做了所有工作一樣返回對(duì)象贵少。
- 寄生式繼承是原型式繼承的加強(qiáng)版。
- 寄生組合式繼承 JavaScript實(shí)現(xiàn)繼承的基本思想:通過借用函數(shù)來繼承屬性堆缘,通過原型鏈的混成形式來繼承方法滔灶。
常用的js數(shù)組操作方法有哪些?
Array.shift()
刪除并返回第一個(gè)元素 作用:從數(shù)組中刪除第一個(gè)元素(即下標(biāo)為0的元素)套啤,并返回該元素宽气。
注意:
1、刪除元素之后潜沦,數(shù)組的長(zhǎng)度-1萄涯。
2、如果數(shù)組是空的唆鸡,那么 shift() 方法將不進(jìn)行任何操作涝影,返回 undefined 值。Array.pop()
刪除并返回最后一個(gè)元素 作用:從數(shù)組中刪除最后一個(gè)元素(即下標(biāo)為length-1的元素)争占,并返回該元素燃逻。
注意:
1、刪除元素之后臂痕,數(shù)組的長(zhǎng)度-1伯襟。
2、如果數(shù)組是空的握童,那么 shift() 方法將不進(jìn)行任何操作姆怪,返回 undefined 值。Array.push(param1[,param2,...paramN])
尾部添加元素 作用:在數(shù)組的尾部添加一個(gè)元素澡绩,并返回新數(shù)組的長(zhǎng)度稽揭。
注意
1、它是直接修改該數(shù)組肥卡,而不是重新創(chuàng)建一個(gè)數(shù)組溪掀。
2、它和pop是一對(duì)相反的先進(jìn)后出的棧功能方法步鉴。
3揪胃、它可以同時(shí)給一個(gè)數(shù)組添加多個(gè)元素。Array.unshift(newElement1[,newElement2,...newElementN]
頭部添加元素 作用:在數(shù)組的頭部添加一個(gè)或多個(gè)元素氛琢,并返回新數(shù)組的長(zhǎng)度只嚣。
注意:
1、它是直接修改該數(shù)組艺沼,而不是重新創(chuàng)建一個(gè)數(shù)組。
2蕴掏、IE瀏覽器不支持該方法障般。Array.join([separator])
轉(zhuǎn)換成字符串 作用:把數(shù)組的所有元素放入到一個(gè)字符串中调鲸。
注意:
1、參數(shù)separator表示字符串中元素的分隔符挽荡,可以為空藐石,默認(rèn)為半角逗號(hào)。
2定拟、該方法并不修改數(shù)組于微。Array.contact(array1[,array2,...arrayN])
連接數(shù)組 作用:將兩個(gè)或兩個(gè)以上的數(shù)組連接成一個(gè)數(shù)組,并返回連接后的數(shù)組青自。
注意:
1株依、該方法并不會(huì)改變現(xiàn)有的數(shù)組,而是返回被連接的多個(gè)數(shù)組的一個(gè)副本延窜。
2恋腕、如果多個(gè)數(shù)組里有值相同的元素,那也不會(huì)重復(fù)出現(xiàn)逆瑞,而不會(huì)把重復(fù)的元素過濾掉荠藤。Array.reverse()
反轉(zhuǎn)數(shù)組 作用:把數(shù)組的所有元素順序反轉(zhuǎn)。
注意:
1获高、該方法會(huì)直接修改數(shù)組哈肖,而不會(huì)創(chuàng)建新的數(shù)組。Array.slice(start[, end])
截取數(shù)組 作用:截取數(shù)組中指定位置的元素念秧,并返回一個(gè)新的子數(shù)組淤井。
注意:
1、該方法并不會(huì)改變現(xiàn)有的數(shù)組出爹,而是原數(shù)組的一個(gè)子數(shù)組庄吼。
2、參數(shù)start是必選严就,表示開始下標(biāo)总寻,如果start為負(fù)數(shù),表示從末尾開始梢为,-1表示最后一個(gè)元素渐行,依次類推。
3铸董、end是可選表示結(jié)束下標(biāo)祟印,如果沒有指定,表示到結(jié)尾元素粟害。Array.splice()
刪除指定元素 作用:從數(shù)組指定位置刪除指定數(shù)量的元素蕴忆,并返回被刪除的元素。
注意:
1悲幅、該方法會(huì)直接修改數(shù)組套鹅。
2站蝠、splice() 方法與 slice() 方法的作用是不同的,splice() 方法會(huì)直接對(duì)數(shù)組進(jìn)行修改卓鹿,而slice只是截取原數(shù)組的一部分后返回一個(gè)子數(shù)組菱魔,并不會(huì)修改原數(shù)組。Array.toString()
轉(zhuǎn)換成字符串 作用:數(shù)組轉(zhuǎn)換為字符串吟孙,并返回該字符串澜倦。
注意:
1、該方法和不帶參數(shù)的join()方法效果一樣杰妓。
js數(shù)組去重
-
使用es6 set方法 [...new Set(arr)]
let arr = [1,2,3,4,3,2,3,4,6,7,6]; let unique = (arr)=> [...new Set(arr)]; unique(arr); //[1, 2, 3, 4, 6, 7]
利用新數(shù)組indexOf查找 indexOf() 方法可返回某個(gè)指定的元素在數(shù)組中首次出現(xiàn)的位置藻治。如果沒有就返回-1。
-
for 雙重循環(huán) 通過判斷第二層循環(huán)稚失,去重的數(shù)組中是否含有該元素栋艳,如果有就退出第二層循環(huán),如果沒有j==result.length就相等句各,然后把對(duì)應(yīng)的元素添加到最后的數(shù)組里面吸占。
let arr = [1,2,3,4,3,2,3,4,6,7,6]; let result = []; for(var i = 0 ; i< arr.length; i++) { for(var j = 0 ; j < result.length ; j++) { if( arr[i] === result[j]){ break; }; }; if(j == result.length){ result.push(arr[i]); }; }; console.log(result);
-
利用for嵌套for,然后splice去重
functionunique(arr){ for(vari=0; i<arr.length; i++){ for(varj=i+1; j<arr.length; j++){ if(arr[i]==arr[j]){ //第一個(gè)等同于第二個(gè)凿宾,splice方法刪除第二個(gè) arr.splice(j,1); j--; } } } returnarr; }
-
利用filter
let arr = [1,2,3,4,3,2,3,4,6,7,6]; let unique = (arr) => { return arr.filter((item,index) => { return arr.indexOf(item) === index; }) }; unique(arr); let arr = [1,2,3,4,3,2,3,4,6,7,6]; let unique = (arr) => { return arr.filter((item,index) => { return arr.indexOf(item) === index; }) }; unique(arr);
-
利用Map數(shù)據(jù)結(jié)構(gòu)去重
let arr = [1,2,3,4,3,2,3,4,6,7,6]; let unique = (arr)=> { let seen = new Map(); return arr.filter((item) => { return !seen.has(item) && seen.set(item,1); }); }; unique(arr);
數(shù)組中的forEach和map的區(qū)別矾屯?
- 相同點(diǎn)
- 都是循環(huán)遍歷數(shù)組中的每一項(xiàng)
- forEach和map方法里每次執(zhí)行匿名函數(shù)都支持3個(gè)參數(shù),參數(shù)分別是item(當(dāng)前每一項(xiàng))初厚,index(索引值)件蚕,arr(原數(shù)組)
- 匿名函數(shù)中的this都是指向window 只能遍歷數(shù)組 都不會(huì)改變?cè)瓟?shù)組
- 區(qū)別
- map方法返回一個(gè)新的數(shù)組,數(shù)組中的元素為原始數(shù)組調(diào)用函數(shù)處理后的值产禾。
- map方法不會(huì)對(duì)空數(shù)組進(jìn)行檢測(cè)排作,map方法不會(huì)改變?cè)紨?shù)組。
- 瀏覽器支持:chrome亚情、Safari1.5+妄痪、opera都支持,IE9+, 若arr為空數(shù)組楞件,則map方法返回的也是一個(gè)空數(shù)組衫生。
- forEach方法用來調(diào)用數(shù)組的每個(gè)元素,將元素傳給回調(diào)函數(shù)
- forEach對(duì)于空數(shù)組是不會(huì)調(diào)用回調(diào)函數(shù)的土浸。 無論arr是不是空數(shù)組罪针,forEach返回的都是undefined。這個(gè)方法只是將數(shù)組中的每一項(xiàng)作為callback的參數(shù)執(zhí)行一次黄伊。
js事件循環(huán) event loop泪酱?
- 主線程從"任務(wù)隊(duì)列"中讀取事件,這個(gè)過程是循環(huán)不斷的,所以整個(gè)的這種運(yùn)行機(jī)制又稱為Event Loop(事件循環(huán))西篓。
Math.min()和Math.max()大小比較愈腾?
- Math.max() Math.min() Math.min()如果沒有參數(shù),則返回 Infinity岂津。
- Infinity 是javascript 中全局對(duì)象的一個(gè)屬性,在瀏覽器環(huán)境中就是 window 對(duì)象的一個(gè)屬性悦即,表示無窮大吮成。
- Math.max()沒有傳遞參數(shù)時(shí)返回的是 -Infinity。 因此 Math.min() 要比 Math.max() 大辜梳。
怎么實(shí)現(xiàn)對(duì)象的深淺拷貝粱甫?
- 淺拷貝很容易,只需要使用賦值運(yùn)算符(=)即可
文件上傳如何做斷點(diǎn)續(xù)傳?
- 文件斷點(diǎn)續(xù)傳是HTML5引入的新特性作瞄,HTML5的FILE api茶宵,有一個(gè)slice方法,可以將BLOB對(duì)象進(jìn)行分割宗挥。前端通過FileList對(duì)象獲取到相應(yīng)的文件乌庶,按照指定的分割方式將大文件分段,然后一段一段地傳給后端契耿,后端再按順序一段段將文件進(jìn)行拼接瞒大。
- 斷點(diǎn)續(xù)傳原理,目前比較常用的斷點(diǎn)續(xù)傳的方法有兩種搪桂,
- 一種是通過websocket接口進(jìn)行文件上傳透敌,
- 另一種是通過ajax,兩種方法各有千秋踢械,雖然websocket聽起來比較高端些酗电,但是除了用了不同的協(xié)議外其他的算法基本上都是很相似的,并且服務(wù)端要開啟ws接口内列,這里用相對(duì)方便的ajax來說明斷點(diǎn)上傳的思路撵术。
- 首先是文件的識(shí)別,一個(gè)文件被分成了若干份之后如何告訴服務(wù)器你切了多少塊德绿,以及最終服務(wù)器應(yīng)該如何把你上傳上去的文件進(jìn)行合并荷荤?
- 因此在文件開始上傳之前,我們和服務(wù)器要有一個(gè)“握手”的過程移稳,告訴服務(wù)器文件信息蕴纳,然后和服務(wù)器約定切片的大小,當(dāng)和服務(wù)器達(dá)成共識(shí)之后就可以開始后續(xù)的文件傳輸了个粱。
- 前臺(tái)要把每一塊的文件傳給后臺(tái)古毛,成功之后前端和后端都要標(biāo)識(shí)一下,以便后續(xù)的斷點(diǎn)。
- 當(dāng)文件傳輸中斷之后用戶再次選擇文件就可以通過標(biāo)識(shí)來判斷文件是否已經(jīng)上傳了一部分稻薇,如果是的話嫂冻,那么我們可以接著上次的進(jìn)度繼續(xù)傳文件,以達(dá)到續(xù)傳的功能塞椎。
js如何處理防抖和節(jié)流桨仿?
- 在進(jìn)行窗口的resize、scroll案狠,輸入框內(nèi)容校驗(yàn)等操作時(shí)服傍,如果事件處理函數(shù)調(diào)用的頻率無限制,會(huì)加重瀏覽器的負(fù)擔(dān)骂铁,導(dǎo)致用戶體驗(yàn)非常糟糕吹零。
- 此時(shí)我們可以采用debounce(防抖)和throttle(節(jié)流)的方式來減少調(diào)用頻率,同時(shí)又不影響實(shí)際效果拉庵。 函數(shù)防抖
- 函數(shù)防抖(debounce):當(dāng)持續(xù)觸發(fā)事件時(shí)灿椅,一定時(shí)間段內(nèi)沒有再觸發(fā)事件,事件處理函數(shù)才會(huì)執(zhí)行一次钞支,如果設(shè)定的時(shí)間到來之前茫蛹,又一次觸發(fā)了事件,就重新開始延時(shí)伸辟。
- 如下麻惶,持續(xù)觸發(fā)scroll事件時(shí),并不執(zhí)行handle函數(shù)信夫,當(dāng)1000毫秒內(nèi)沒有觸發(fā)scroll事件時(shí)窃蹋,才會(huì)延時(shí)觸發(fā)scroll事件。
function debounce(fn, wait) {
var timeout = null;
return function() {
if(timeout !== null)
clearTimeout(timeout);
timeout = setTimeout(fn, wait);
}
}
// 處理函數(shù) function handle() {
console.log(Math.random()); } // 滾動(dòng)事件
window.addEventListener('scroll', debounce(handle, 1000));
// 函數(shù)節(jié)流
- 函數(shù)節(jié)流(throttle):當(dāng)持續(xù)觸發(fā)事件時(shí)静稻,保證一定時(shí)間段內(nèi)只調(diào)用一次事件處理函數(shù)警没。
- 節(jié)流通俗解釋就比如我們水龍頭放水,閥門一打開振湾,水嘩嘩的往下流杀迹,秉著勤儉節(jié)約的優(yōu)良傳統(tǒng)美德,我們要把水龍頭關(guān)小點(diǎn)押搪,最好是如我們心意按照一定規(guī)律在某個(gè)時(shí)間間隔內(nèi)一滴一滴的往下滴树酪。
- 如下,持續(xù)觸發(fā)scroll事件時(shí)大州,并不立即執(zhí)行handle函數(shù)续语,每隔1000毫秒才會(huì)執(zhí)行一次handle函數(shù)。
var throttle = function(func, delay) {
var prev = Date.now();
return function() {
var context = this;
var args = arguments;
var now = Date.now();
if (now - prev >= delay) {
func.apply(context, args);
prev = Date.now();
}
}
}
function handle() {
console.log(Math.random());
}
window.addEventListener('scroll', throttle(handle, 1000));
//總結(jié)
- 函數(shù)防抖:將幾次操作合并為一此操作進(jìn)行厦画。原理是維護(hù)一個(gè)計(jì)時(shí)器疮茄,規(guī)定在delay時(shí)間后觸發(fā)函數(shù)滥朱,但是在delay時(shí)間內(nèi)再次觸發(fā)的話,就會(huì)取消之前的計(jì)時(shí)器而重新設(shè)置力试。這樣一來徙邻,只有最后一次操作能被觸發(fā)。
- 函數(shù)節(jié)流:使得一定時(shí)間內(nèi)只觸發(fā)一次函數(shù)畸裳。原理是通過判斷是否到達(dá)一定時(shí)間來觸發(fā)函數(shù)缰犁。 區(qū)別:
- 函數(shù)節(jié)流不管事件觸發(fā)有多頻繁,都會(huì)保證在規(guī)定時(shí)間內(nèi)一定會(huì)執(zhí)行一次真正的事件處理函數(shù)躯畴,而函數(shù)防抖只是在最后一次事件后才觸發(fā)一次函數(shù)民鼓。比如在頁面的無限加載場(chǎng)景下,我們需要用戶在滾動(dòng)頁面時(shí)蓬抄,每隔一段時(shí)間發(fā)一次
- Ajax 請(qǐng)求,而不是在用戶停下滾動(dòng)頁面操作時(shí)才去請(qǐng)求數(shù)據(jù)夯到。這樣的場(chǎng)景嚷缭,就適合用節(jié)流技術(shù)來實(shí)現(xiàn)。
事件委托以及優(yōu)缺點(diǎn)?
- 優(yōu)點(diǎn):
- 減少事件注冊(cè)耍贾,節(jié)省內(nèi)存阅爽。比如,
- 在table上代理所有td的click事件荐开。
- 在ul上代理所有l(wèi)i的click事件付翁。
- 簡(jiǎn)化了dom節(jié)點(diǎn)更新時(shí),相應(yīng)事件的更新晃听。比如
- 不用在新添加的li上綁定click事件百侧。
- 當(dāng)刪除某個(gè)li時(shí),不用移解綁上面的click事件能扒。 缺點(diǎn):
- 事件委托基于冒泡佣渴,對(duì)于不冒泡的事件不支持。
- 層級(jí)過多初斑,冒泡過程中辛润,可能會(huì)被某層阻止掉。
- 理論上委托會(huì)導(dǎo)致瀏覽器頻繁調(diào)用處理函數(shù)见秤,雖然很可能不需要處理砂竖。所以建議就近委托,比如在table上代理td鹃答,而不是在document上代理td乎澄。
- 把所有事件都用代理就可能會(huì)出現(xiàn)事件誤判。比如挣跋,在document中代理了所有button的click事件三圆,另外的人在引用改js時(shí),可能不知道,造成單擊button觸發(fā)了兩個(gè)click事件舟肉。
介紹this各種情況?
- this的情況:
- 以函數(shù)形式調(diào)用時(shí)修噪,this永遠(yuǎn)都是window
- 以方法的形式調(diào)用時(shí),this是調(diào)用方法的對(duì)象
- 以構(gòu)造函數(shù)的形式調(diào)用時(shí)路媚,this是新創(chuàng)建的那個(gè)對(duì)象
- 使用call和apply調(diào)用時(shí)黄琼,this是指定的那個(gè)對(duì)象
- 箭頭函數(shù):箭頭函數(shù)的this看外層是否有函數(shù)
- 如果有,外層函數(shù)的this就是內(nèi)部箭頭函數(shù)的this
- 如果沒有整慎,就是window
- 特殊情況:通常意義上this指針指向?yàn)樽詈笳{(diào)用它的對(duì)象脏款。這里需要注意的一點(diǎn)就是如果返回值是一個(gè)對(duì)象,那么this指向的就是那個(gè)返回的對(duì)象裤园,如果返回值不是一個(gè)對(duì)象那么this還是指向函數(shù)的實(shí)例
== 和 ===的區(qū)別撤师,什么情況下用相等==?
- ==
運(yùn)算符稱作相等,用來檢測(cè)兩個(gè)操作數(shù)是否相等拧揽,這里的相等定義的非常寬松剃盾,可以允許進(jìn)行類型轉(zhuǎn)換 - ===
用來檢測(cè)兩個(gè)操作數(shù)是否嚴(yán)格相等- 對(duì)于string,number等基礎(chǔ)類型,==和===是有區(qū)別的 不同類型間比較淤袜,==之比較“轉(zhuǎn)化成同一類型后的值”看“值”是否相等痒谴,===如果類型不同,其結(jié)果就是不等
- 同類型比較铡羡,直接進(jìn)行“值”比較积蔚,兩者結(jié)果一樣
- 對(duì)于Array,Object等高級(jí)類型,==和===是沒有區(qū)別的
- 基礎(chǔ)類型與高級(jí)類型烦周,==和===是有區(qū)別的 對(duì)于==尽爆,將高級(jí)轉(zhuǎn)化為基礎(chǔ)類型,進(jìn)行“值”比較论矾,因?yàn)轭愋筒煌?==結(jié)果為false
介紹下原型鏈(解決的是繼承問題嗎)
- JavaScript原型: 每個(gè)對(duì)象都會(huì)在其內(nèi)部初始化一個(gè)屬性教翩,就是prototype(原型)。 原型鏈:
- 當(dāng)我們?cè)L問一個(gè)對(duì)象的屬性時(shí)贪壳,如果這個(gè)對(duì)象內(nèi)部不存在這個(gè)屬性饱亿,那么他就會(huì)去prototype里找這個(gè)屬性,這個(gè)prototype又會(huì)有自己的prototype闰靴,于是就這樣一直找下去彪笼,也就是我們平時(shí)所說的原型鏈的概念。
- 特點(diǎn):
- JavaScript對(duì)象是通過引用來傳遞的蚂且,我們創(chuàng)建的每個(gè)新對(duì)象實(shí)體中并沒有一份屬于自己的原型副本配猫。當(dāng)我們修改原型時(shí),與之相關(guān)的對(duì)象也會(huì)繼承這一改變杏死。
JS里垃圾回收機(jī)制是什么泵肄,常用的是哪種捆交,怎么處理的?
JS的垃圾回收機(jī)制是為了以防內(nèi)存泄漏腐巢,內(nèi)存泄漏的含義就是當(dāng)已經(jīng)不需要某塊內(nèi)存時(shí)這塊內(nèi)存還存在著品追,垃圾回收機(jī)制就是間歇的不定期的尋找到不再使用的變量,并釋放掉它們所指向的內(nèi)存冯丙。
JS中最常見的垃圾回收方式是標(biāo)記清除肉瓦。
工作原理:是當(dāng)變量進(jìn)入環(huán)境時(shí),將這個(gè)變量標(biāo)記為“進(jìn)入環(huán)境”胃惜。當(dāng)變量離開環(huán)境時(shí)泞莉,則將其標(biāo)記為“離開環(huán)境”。標(biāo)記“離開環(huán)境”的就回收內(nèi)存船殉。
-
工作流程
- 垃圾回收器鲫趁,在運(yùn)行的時(shí)候會(huì)給存儲(chǔ)在內(nèi)存中的所有變量都加上標(biāo)記。
- 去掉環(huán)境中的變量以及被環(huán)境中的變量引用的變量的標(biāo)記利虫。
- 再被加上標(biāo)記的會(huì)被視為準(zhǔn)備刪除的變量饮寞。
- 垃圾回收器完成內(nèi)存清除工作,銷毀那些帶標(biāo)記的值并回收他們所占用的內(nèi)存空間列吼。
27.Promise和setTimeout的區(qū)別?
- 回顧JavaScript事件循環(huán)并發(fā)模型苦始,我們了解了setTimeout和Promise調(diào)用的都是異步任務(wù)寞钥,這一點(diǎn)是它們共同之處,也即都是通過任務(wù)隊(duì)列進(jìn)行管理/調(diào)度陌选。那么它們有什么區(qū)別嗎理郑?
- 任務(wù)隊(duì)列
- 前文已經(jīng)介紹了任務(wù)隊(duì)列的基礎(chǔ)內(nèi)容和機(jī)制,可選擇查看咨油,本文對(duì)任務(wù)隊(duì)列進(jìn)行拓展介紹您炉。JavaScript通過任務(wù)隊(duì)列管理所有異步任務(wù),而任務(wù)隊(duì)列還可以細(xì)分為MacroTask
- Queue和MicoTask Queue兩類役电。 MacroTask Queue MacroTask
- Queue(宏任務(wù)隊(duì)列)主要包括setTimeout,setInterval, setImmediate,
- requestAnimationFrame, NodeJS中的`I/O等赚爵。 MicroTask Queue MicroTask
- Queue(微任務(wù)隊(duì)列)主要包括兩類: 獨(dú)立回調(diào)microTask:如Promise,其成功/失敗回調(diào)函數(shù)相互獨(dú)立法瑟;
- 復(fù)合回調(diào)microTask:如 Object.observe, MutationObserver 和NodeJs中的
- process.nextTick 冀膝,不同狀態(tài)回調(diào)在同一函數(shù)體; MacroTask和MicroTask
- JavaScript將異步任務(wù)分為MacroTask和MicroTask霎挟,那么它們區(qū)別何在呢窝剖? 依次執(zhí)行同步代碼直至執(zhí)行完畢;
- 檢查MacroTask 隊(duì)列酥夭,若有觸發(fā)的異步任務(wù)赐纱,則取第一個(gè)并調(diào)用其事件處理函數(shù)脊奋,然后跳至第三步,若沒有需處理的異步任務(wù)疙描,則直接跳至第三步诚隙;
- 檢查MicroTask隊(duì)列,然后執(zhí)行所有已觸發(fā)的異步任務(wù)淫痰,依次執(zhí)行事件處理函數(shù)最楷,直至執(zhí)行完畢,然后跳至第二步待错,若沒有需處理的異步任務(wù)中籽孙,則直接返回第二步,依次執(zhí)行后續(xù)步驟火俄;
- 最后返回第二步犯建,繼續(xù)檢查MacroTask隊(duì)列,依次執(zhí)行后續(xù)步驟瓜客; 如此往復(fù)适瓦,若所有異步任務(wù)處理完成,則結(jié)束谱仪;
介紹下廣度優(yōu)先遍歷(BFS)和深度優(yōu)先遍歷(DFS)玻熙?
廣度優(yōu)先遍歷 英文縮寫為BFS即Breadth FirstSearch。其過程檢驗(yàn)來說是對(duì)每一層節(jié)點(diǎn)依次訪問疯攒,訪問完一層進(jìn)入下一層斯入,而且每個(gè)節(jié)點(diǎn)只能訪問一次玄坦。對(duì)于上面的例子來說籽御,廣度優(yōu)先遍歷的
結(jié)果是:A,B,C,D,E,F,G,H,I(假設(shè)每層節(jié)點(diǎn)從左到右訪問)留搔。 先往隊(duì)列中插入左節(jié)點(diǎn),再插右節(jié)點(diǎn)砂吞,這樣出隊(duì)就是先左節(jié)點(diǎn)后右節(jié)點(diǎn)了署恍。
廣度優(yōu)先遍歷樹,需要用到隊(duì)列(Queue)來存儲(chǔ)節(jié)點(diǎn)對(duì)象,隊(duì)列的特點(diǎn)就是先進(jìn)先出蜻直。例如盯质,上面這顆樹的訪問如下:
首先將A節(jié)點(diǎn)插入隊(duì)列中,隊(duì)列中有元素(A);
將A節(jié)點(diǎn)彈出袭蝗,同時(shí)將A節(jié)點(diǎn)的左唤殴、右節(jié)點(diǎn)依次插入隊(duì)列,B在隊(duì)首到腥,C在隊(duì)尾朵逝,(B,C)乡范,此時(shí)得到A節(jié)點(diǎn)配名;
繼續(xù)彈出隊(duì)首元素啤咽,即彈出B,并將B的左渠脉、右節(jié)點(diǎn)插入隊(duì)列宇整,C在隊(duì)首,E在隊(duì)尾(C,D芋膘,E)鳞青,此時(shí)得到B節(jié)點(diǎn);
繼續(xù)彈出为朋,即彈出C臂拓,并將C節(jié)點(diǎn)的左、中习寸、右節(jié)點(diǎn)依次插入隊(duì)列胶惰,(D,E,F,G,H),此時(shí)得到C節(jié)點(diǎn)霞溪;
將D彈出孵滞,此時(shí)D沒有子節(jié)點(diǎn),隊(duì)列中元素為(E,F,G,H)鸯匹,得到D節(jié)點(diǎn)坊饶; 。殴蓬。幼东。以此類推。科雳。
2.深度優(yōu)先遍歷 英文縮寫為DFS即Depth First Search.其過程簡(jiǎn)要來說是對(duì)每一個(gè)可能的分支路徑深入到不能再深入為止,而且每個(gè)節(jié)點(diǎn)只能訪問一次脓杉。對(duì)于上面的例子來說深度優(yōu)先遍歷的結(jié)果就是:A,B,D,E,I,C,F,G,H.(假設(shè)先走子節(jié)點(diǎn)的的左側(cè))糟秘。
深度優(yōu)先遍歷各個(gè)節(jié)點(diǎn),需要使用到棧(Stack)這種數(shù)據(jù)結(jié)構(gòu)球散。stack的特點(diǎn)是是先進(jìn)后出尿赚。整個(gè)遍歷過程如下:
先往棧中壓入右節(jié)點(diǎn),再壓左節(jié)點(diǎn)蕉堰,這樣出棧就是先左節(jié)點(diǎn)后右節(jié)點(diǎn)了凌净。 首先將A節(jié)點(diǎn)壓入棧中,stack(A);
將A節(jié)點(diǎn)彈出屋讶,同時(shí)將A的子節(jié)點(diǎn)C冰寻,B壓入棧中,此時(shí)B在棧的頂部皿渗,stack(B,C)斩芭;
將B節(jié)點(diǎn)彈出轻腺,同時(shí)將B的子節(jié)點(diǎn)E,D壓入棧中划乖,此時(shí)D在棧的頂部贬养,stack(D,E,C);
將D節(jié)點(diǎn)彈出琴庵,沒有子節(jié)點(diǎn)壓入,此時(shí)E在棧的頂部误算,stack(E,C)迷殿; 將E節(jié)點(diǎn)彈出儿礼,同時(shí)將E的子節(jié)點(diǎn)I壓入,stack(I,C)贪庙;
…依次往下蜘犁,最終遍歷完成。 代碼:也是以二叉樹為例止邮。
29.for in和for of的區(qū)別
- 推薦在循環(huán)對(duì)象屬性的時(shí)候这橙,使用for...in,在遍歷數(shù)組的時(shí)候的時(shí)候使用for...of
- for...in循環(huán)出的是key,for...of循環(huán)出的是value
- 注意导披,for...of是ES6新引入的特性屈扎。修復(fù)了ES5引入的for...in的不足
- for...of不能循環(huán)普通的對(duì)象,需要通過和Object.keys()搭配使用
typeof和instanceof 區(qū)別撩匕?
- 在javascript中鹰晨,判斷一個(gè)變量的類型可以用typeof
- 數(shù)字類型、typeof返回的值是number止毕。比如說:typeof(1)模蜡,返回值是number
- 字符串類型,typeof返回的值是string扁凛。比如typeof(“123”返回值時(shí)string)
- 布爾類型忍疾,typeof返回的值是boolean。比如typeof(true)返回值時(shí)boolean
- 對(duì)象谨朝、數(shù)組卤妒、null返回的值是object。比如typeof(window)字币,typeof(document)则披,typeof(null)返回的值都是object
- 函數(shù)類型,返回的值是function洗出。比如:typeof(eval)士复,typeof(Date)返回的值都是function。
- 不存在的變量翩活、函數(shù)或者undefined判没,將返回undefined蜓萄。比如:typeof(abc)、typeof(undefined)都返回undefined
- 在javascript中澄峰,instanceof用于判斷某個(gè)對(duì)象是否被另一個(gè)函數(shù)構(gòu)造嫉沽。
- 使用typeof運(yùn)算符時(shí)采用引用類型存儲(chǔ)值會(huì)出現(xiàn)一個(gè)問題,無論引用的是什么類型的對(duì)象俏竞,它都返回”object”绸硕。ECMAScript引入了另一個(gè)Java運(yùn)算符instanceof來解決這個(gè)問題。Instanceof運(yùn)算符與typeof運(yùn)算符相似魂毁,用于識(shí)別正在處理的對(duì)象的類型玻佩。與typeof方法不同的是,instanceof方法要求開發(fā)者明確地確認(rèn)對(duì)象為某特定類型
常見的繼承有幾種方法?
- 原型鏈繼承
- 構(gòu)造函數(shù)繼承(經(jīng)典繼承)
- 組合方式繼承(構(gòu)造函數(shù) + 原型鏈)
- es6方法繼承
什么是事件冒泡席楚,它是如何工作的咬崔?如何阻止事件冒泡?
在一個(gè)對(duì)象上觸發(fā)某類事件(比如單擊onclick事件),如果此對(duì)象定義了此事件的處理程序烦秩,那么此事件就會(huì)調(diào)用這個(gè)處理程序垮斯,如果沒有定義此事件處理程序或者事件返回true,那么這個(gè)事件會(huì)向這個(gè)對(duì)象的父級(jí)對(duì)象傳播只祠,從里到外兜蠕,直至它被處理(父級(jí)對(duì)象所有同類事件都將被激活),或者它到達(dá)了對(duì)象層次的最頂層抛寝,即document對(duì)象(有些瀏覽器是window)
//阻止事件冒泡的幾種方法
//第一種
event.stopPropagation();
//第二種
return false;
//第三種
event.preventDefault();
什么是Promise對(duì)象熊杨,有哪些用法、通過Promise對(duì)象實(shí)現(xiàn)ajax
Promise是異步編程的一種解決方案盗舰,它是一個(gè)容器晶府,里面保存著某個(gè)未來才會(huì)結(jié)束的事件(通常是一個(gè)異步操作)的結(jié)果。 Promise 提供統(tǒng)一的API钻趋,各種異步操作都可以用同樣的方法進(jìn)行處理郊霎。promise對(duì)象是一個(gè)構(gòu)造函數(shù),用來生成Promise實(shí)例爷绘;
-
Promise對(duì)象的特點(diǎn)
- 對(duì)象的狀態(tài)不受外界影響,promise對(duì)象代表一個(gè)異步操作进倍,有三種狀態(tài)土至,pending(進(jìn)行中)、fulfilled(已成功)猾昆、rejected(已失斕找颉)。只有異步操作的結(jié)果垂蜗,可以決定當(dāng)前是哪一種狀態(tài)楷扬,任何其他操作都無法改變這個(gè)狀態(tài)解幽。
- 一旦狀態(tài)改變就不會(huì)再變,任何時(shí)候都可以得到這個(gè)結(jié)果烘苹,promise對(duì)象的狀態(tài)改變躲株,只有兩種可能:從pending變?yōu)閒ulfilled,從pending變?yōu)閞ejected镣衡。
-
Promise缺點(diǎn)霜定。
- 無法取消Promise,一旦新建它就會(huì)立即執(zhí)行廊鸥,無法中途取消望浩。
- 如果不設(shè)置回調(diào)函數(shù),Promise內(nèi)部拋出的錯(cuò)誤惰说,不會(huì)反應(yīng)到外部磨德。
- 當(dāng)處于pending狀態(tài)時(shí),無法得知目前進(jìn)展到哪一個(gè)階段
-
Promise對(duì)象的用法
-
是一個(gè)構(gòu)造函數(shù)吆视,這個(gè)構(gòu)造函數(shù)里有兩個(gè)參數(shù)典挑,分別是:resolve(成功之后的回調(diào)函數(shù))、reject(失敗之后的回調(diào)函數(shù))揩环。
2374931195-5d883df9072f6_articlex.png
promise實(shí)例生成以后搔弄,可以用then方法分別指定resolved狀態(tài)和rejected狀態(tài)的回調(diào)函數(shù)
3033114998-5d883e02ec354_articlex.png
then方法可以接受連個(gè)回調(diào)函數(shù)作為參數(shù),第一個(gè)回調(diào)函數(shù)是promise對(duì)象的狀態(tài)變?yōu)閞esolved時(shí)調(diào)用丰滑,第二個(gè)回調(diào)函數(shù)是promise對(duì)象的狀態(tài)變?yōu)閞ejected時(shí)調(diào)用顾犹,其中,第二個(gè)函數(shù)是可選的褒墨,不一定要提供炫刷,這兩個(gè)函數(shù)都接受promise對(duì)象傳出的值作為參數(shù);then指定回調(diào)函數(shù)的時(shí)候郁妈,成功的回調(diào)函數(shù)必須傳浑玛,失敗的回調(diào)函數(shù)可以勝利。 如果前面的promise執(zhí)行失敗噩咪,不詳影響后續(xù)操作終止顾彰,捕獲異常的兩種方式:
①可以為每個(gè)promise指定失敗回調(diào);
function(err){ console.log(……) })
②最后加catch(function(err){console.log(……) })//表示如前面有任意一個(gè)有報(bào)錯(cuò)胃碾,立即報(bào)錯(cuò)涨享,并終止后面的;如果前面無報(bào)錯(cuò)仆百,前面正常執(zhí)行厕隧。
-
-
Promise對(duì)象實(shí)現(xiàn)ajax
591937307-5d883e11d8774_articlex.png
什么是閉包,舉個(gè)例子說明一下?
閉包就是能夠讀取其他函數(shù)內(nèi)部變量的函數(shù)。例如在javascript中吁讨,只有函數(shù)內(nèi)部的子函數(shù)才能讀取局部變量髓迎,所以閉包可以理解成“定義在一個(gè)函數(shù)內(nèi)部的函數(shù)“。在本質(zhì)上建丧,閉包是將函數(shù)內(nèi)部和函數(shù)外部連接起來的橋梁排龄。
創(chuàng)建閉包最常見方式,就是在一個(gè)函數(shù)內(nèi)部創(chuàng)建另一個(gè)函數(shù)茶鹃。下面例子中的 closure 就是一個(gè)閉包涣雕,
function func(){
va ra =1 ,b = 2;
funciton closure(){
return a+b;
}
return closure;
}
let、var闭翩、const區(qū)別
- var聲明的變量會(huì)掛載在window上挣郭,而let和const聲明的變量不會(huì)
- var聲明變量存在變量提升,let和const不存在變量提升
- let和const聲明形成塊作用域疗韵,var變量提升不會(huì)形成作用域
- 同一作用域下let和const不能聲明同名變量兑障,而var可以
- var和let可以可以修改聲明的變量,const不可以
- const定義的變量時(shí)必須初始化
- let蕉汪、const 存在暫時(shí)性死區(qū)
apply流译、call、bind 什么區(qū)別者疤?
這三者的作用就是改變函數(shù)運(yùn)行時(shí)this的指向福澡。
call和apply都是對(duì)函數(shù)的直接調(diào)用,而bind方法返回的仍然是一個(gè)函數(shù)驹马,因此后面還需要()來進(jìn)行調(diào)用才可以革砸。
call后面的參數(shù)與say方法中是一一對(duì)應(yīng)的,而apply的第二個(gè)參數(shù)是一個(gè)數(shù)組糯累,數(shù)組中的元素是和方法中一一對(duì)應(yīng)的算利。
-
bind傳參
xw.say.bind(xh,"實(shí)驗(yàn)小學(xué)","六年級(jí)")(); xw.say.bind(xh)("實(shí)驗(yàn)小學(xué)","六年級(jí)");
-
call
語法:call([thisObj[,arg1[, arg2[, [,.argN]]]]])
- 定義:調(diào)用一個(gè)對(duì)象的一個(gè)方法,以另一個(gè)對(duì)象替換當(dāng)前對(duì)象泳姐。
- 說明:call方法可以用來代替另一個(gè)對(duì)象調(diào)用一個(gè)方法效拭。call 方法可將一個(gè)函數(shù)的對(duì)象上下文從初始的上下文改變?yōu)橛?thisObj 指定的新對(duì)象。如果沒有提供 thisObj 參數(shù)胖秒,那么 Global 對(duì)象被用作 thisObj缎患。
-
apply
語法:apply([thisObj[,argArray]])
- 定義:應(yīng)用某一對(duì)象的一個(gè)方法,用另一個(gè)對(duì)象替換當(dāng)前對(duì)象阎肝。
- 說明:如果argArray 不是一個(gè)有效的數(shù)組或者不是 arguments 對(duì)象挤渔,那么將導(dǎo)致一個(gè) TypeError。如果沒有提供 argArray 和 thisObj 任何一個(gè)參數(shù)盗痒,那么 Global 對(duì)象將被用作 thisObj, 并且無法被傳遞任何參數(shù)。
-
bind
語法:bind(thisArg[, arg1[, arg2[, ...]]])
- 定義:將接受多個(gè)參數(shù)的函數(shù)變換成接受一個(gè)單一參數(shù)俯邓。
- 說明:bind()方法所返回的函數(shù)的length(形參數(shù)量)等于原函數(shù)的形參數(shù)量減去傳入bind()方法中的實(shí)參數(shù)量(第一個(gè)參數(shù)以后的所有參數(shù))骡楼,因?yàn)閭魅隻ind中的實(shí)參都會(huì)綁定到原函數(shù)的形參。