1. JS 有哪些數(shù)據(jù)類型病毡?
根據(jù) JavaScript 中的變量類型傳遞方式克胳,分為基本數(shù)據(jù)類型和引用數(shù)據(jù)類型兩大類七種。
基本數(shù)據(jù)類型包括Undefined臼勉、Null、Boolean餐弱、Number宴霸、String镜盯、Symbol (ES6新增)六種。
引用數(shù)據(jù)類型只有Object一種猖败,主要包括對(duì)象速缆、數(shù)組和函數(shù)。
判斷數(shù)據(jù)類型采用typeof操作符恩闻,有兩種語(yǔ)法:
typeof123;//語(yǔ)法一constFG =123;typeofFG;//語(yǔ)法二typeof(null)//返回 object;null==undefined//返回true艺糜,因?yàn)閡ndefined派生自null;null===undefined//返回false。復(fù)制代碼
2. 基本數(shù)據(jù)類型和引用數(shù)據(jù)類型有什么區(qū)別幢尚?
(1)兩者作為函數(shù)的參數(shù)進(jìn)行傳遞時(shí):
基本數(shù)據(jù)類型傳入的是數(shù)據(jù)的副本破停,原數(shù)據(jù)的更改不會(huì)影響傳入后的數(shù)據(jù)。
引用數(shù)據(jù)類型傳入的是數(shù)據(jù)的引用地址尉剩,原數(shù)據(jù)的更改會(huì)影響傳入后的數(shù)據(jù)真慢。
(2)兩者在內(nèi)存中的存儲(chǔ)位置:
基本數(shù)據(jù)類型存儲(chǔ)在棧中。
引用數(shù)據(jù)類型在棧中存儲(chǔ)了指針理茎,該指針指向的數(shù)據(jù)實(shí)體存儲(chǔ)在堆中黑界。
3. 判斷數(shù)據(jù)類型的方法有哪些?
(1)利用typeof可以判斷數(shù)據(jù)的類型皂林;
(2)A instanceofB可以用來判斷A是否為B的實(shí)例朗鸠,但它不能檢測(cè) null 和 undefined;
(3)B.constructor == A可以判斷A是否為B的原型础倍,但constructor檢測(cè) Object與instanceof不一樣烛占,還可以處理基本數(shù)據(jù)類型的檢測(cè)。
不過函數(shù)的 constructor 是不穩(wěn)定的沟启,這個(gè)主要體現(xiàn)在把類的原型進(jìn)行重寫忆家,在重寫的過程中很有可能出現(xiàn)把之前的constructor給覆蓋了,這樣檢測(cè)出來的結(jié)果就是不準(zhǔn)確的德迹。
(4)Object.prototype.toString.call()
Object.prototype.toString.call()是最準(zhǔn)確最常用的方式芽卿。
4. 與深拷貝有何區(qū)別?如何實(shí)現(xiàn)浦辨?
淺拷貝只復(fù)制指向某個(gè)對(duì)象的指針蹬竖,而不復(fù)制對(duì)象本身。淺拷貝的實(shí)現(xiàn)方式有:
(1)Object.assign():需注意的是目標(biāo)對(duì)象只有一層的時(shí)候流酬,是深拷貝币厕;
(2)擴(kuò)展運(yùn)算符;
深拷貝就是在拷貝數(shù)據(jù)的時(shí)候芽腾,將數(shù)據(jù)的所有引用結(jié)構(gòu)都拷貝一份旦装。深拷貝的實(shí)現(xiàn)方式有:
(1)手寫遍歷遞歸賦值;
(2)結(jié)合使用JSON.parse()和JSON.stringify()方法摊滔。
5. let阴绢、const的區(qū)別是什么店乐?
var、let呻袭、const都是用于聲明變量或函數(shù)的關(guān)鍵字眨八。其區(qū)別在于:
varletconst
作用域函數(shù)作用域塊級(jí)作用域塊級(jí)作用域
作用域內(nèi)聲明提升有無(暫時(shí)性死區(qū))無
是否可重復(fù)聲明是否否
是否可重復(fù)賦值是是否(常量)
初始化時(shí)是否必需賦值否否是
6. 什么是執(zhí)行上下文和執(zhí)行棧?
變量或函數(shù)的執(zhí)行上下文左电,決定了它們的行為以及可以訪問哪些數(shù)據(jù)廉侧。每個(gè)上下文都有一個(gè)關(guān)聯(lián)的變量對(duì)象,而這個(gè)上下文中定義的所有變量和函數(shù)都存在于這個(gè)對(duì)象上(如DOM中全局上下文關(guān)聯(lián)的便是window對(duì)象)篓足。
每個(gè)函數(shù)調(diào)用都有自己的上下文段誊。當(dāng)代碼執(zhí)行流進(jìn)入函數(shù)時(shí),函數(shù)的上下文被推到一個(gè)執(zhí)行棧中栈拖。在函數(shù)執(zhí)行完之后连舍,執(zhí)行棧會(huì)彈出該函數(shù)上下文,在其上的所有變量和函數(shù)都會(huì)被銷毀涩哟,并將控制權(quán)返還給之前的執(zhí)行上下文索赏。JS的執(zhí)行流就是通過這個(gè)執(zhí)行棧進(jìn)行控制的。
7. 什么是作用域和作用域鏈染簇?
作用域可以理解為一個(gè)獨(dú)立的地盤参滴,可以理解為標(biāo)識(shí)符所能生效的范圍强岸。作用域最大的用處就是隔離變量锻弓,不同作用域下同名變量不會(huì)有沖突。ES6中有全局作用域蝌箍、函數(shù)作用域和塊級(jí)作用域三層概念青灼。
當(dāng)一個(gè)變量在當(dāng)前塊級(jí)作用域中未被定義時(shí),會(huì)向父級(jí)作用域(創(chuàng)建該函數(shù)的那個(gè)父級(jí)作用域)尋找妓盲。如果父級(jí)仍未找到杂拨,就會(huì)再一層一層向上尋找,直到找到全局作用域?yàn)橹姑醭摹_@種一層一層的關(guān)系弹沽,就是作用域鏈。
8. 作用域和執(zhí)行上下文的區(qū)別是什么筋粗?
(1)函數(shù)的執(zhí)行上下文只在函數(shù)被調(diào)用時(shí)生成策橘,而其作用域在創(chuàng)建時(shí)已經(jīng)生成;
(2)函數(shù)的作用域會(huì)包含若干個(gè)執(zhí)行上下文(有可能是零個(gè)娜亿,當(dāng)函數(shù)未被調(diào)用時(shí))丽已。
9. this指向的各種情況都有什么?
this的指向只有在調(diào)用時(shí)才能被確定买决,因?yàn)閠his是執(zhí)行上下文的一部分沛婴。
(1)全局作用域中的函數(shù):其內(nèi)部this指向window:
vara =1;functionfn(){console.log(this.a)}fn()//輸出1復(fù)制代碼
(2)對(duì)象內(nèi)部的函數(shù):其內(nèi)部this指向?qū)ο蟊旧恚?/p>
vara =1;varobj = {a:2,fn:function(){console.log(this.a)}}obj.fn()//輸出2復(fù)制代碼
(3)構(gòu)造函數(shù):其內(nèi)部this指向生成的實(shí)例:
functioncreateP(name,age){this.name = name//this.name指向Pthis.age = age//this.age指向P}varp =newcreateP("老李",46)復(fù)制代碼
(4)由apply吼畏、call、bind改造的函數(shù):其this指向第一個(gè)參數(shù):
functionadd(c,d){returnthis.a +this.b + c + d}varo = {a:1,b:2)add.call(o,5,7)//輸出15復(fù)制代碼
(5)箭頭函數(shù):箭頭函數(shù)沒有自己的this嘁灯,看其外層的是否有函數(shù)泻蚊,如果有,外層函數(shù)的this就是內(nèi)部箭頭函數(shù)的this丑婿,如果沒有藕夫,則this是window。
10.如何改變this指針的指向枯冈?
可以使用apply毅贮、call、bind方法改變this指向(并不會(huì)改變函數(shù)的作用域)尘奏。比較如下:
(1)三者第一個(gè)參數(shù)都是this要指向的對(duì)象滩褥,也就是想指定的上下文,上下文就是指調(diào)用函數(shù)的那個(gè)對(duì)象(沒有就指向全局window)炫加;
(2)bind和call的第二個(gè)參數(shù)都是數(shù)組瑰煎,apply接收多個(gè)參數(shù)并用逗號(hào)隔開;
(3)apply和call只對(duì)原函數(shù)做改動(dòng)俗孝,bind會(huì)返回新的函數(shù)(要生效還得再調(diào)用一次)酒甸。
11.什么是閉包?
閉包就是引用了其他函數(shù)作用域中變量的函數(shù)赋铝,這種模式通常在函數(shù)嵌套結(jié)構(gòu)中實(shí)現(xiàn)插勤。里面的函數(shù)可以訪問外面函數(shù)的變量,外面的變量的是這個(gè)內(nèi)部函數(shù)的一部分革骨。閉包有如下作用:
(1)加強(qiáng)封裝农尖,模擬實(shí)現(xiàn)私有變量;
(2)實(shí)現(xiàn)常駐內(nèi)存的變量良哲。
閉包不能濫用盛卡,否則會(huì)導(dǎo)致內(nèi)存泄露,影響網(wǎng)頁(yè)的性能筑凫。閉包使用完了后滑沧,要立即釋放資源,將引用變量指向null巍实。
12. 什么是原型滓技、原型鏈?
原型:JS聲明構(gòu)造函數(shù)(用來實(shí)例化對(duì)象的函數(shù))時(shí)蔫浆,會(huì)在內(nèi)存中創(chuàng)建一個(gè)對(duì)應(yīng)的對(duì)象殖属,這個(gè)對(duì)象就是原函數(shù)的原型。構(gòu)造函數(shù)默認(rèn)有一個(gè)prototype屬性瓦盛,prototype的值指向函數(shù)的原型洗显。同時(shí)原型中也有一個(gè)constructor屬性外潜,constructor的值指向原函數(shù)。
通過構(gòu)造函數(shù)實(shí)例化出來的對(duì)象挠唆,并不具有prototype屬性处窥,其默認(rèn)有一個(gè)__proto__屬性,__proto__的值指向構(gòu)造函數(shù)的原型對(duì)象玄组。在原型對(duì)象上添加或修改的屬性滔驾,在所有實(shí)例化出的對(duì)象上都可共享。
當(dāng)在實(shí)例化的對(duì)象中訪問一個(gè)屬性時(shí)俄讹,首先會(huì)在該對(duì)象內(nèi)部尋找哆致,如找不到,則會(huì)向其__proto__指向的原型中尋找患膛,如仍找不到摊阀,則繼續(xù)向原型中__proto__指向的上級(jí)原型中尋找,直至找到或Object.prototype為止踪蹬,這種鏈狀過程即為原型鏈胞此。
13. 何為防抖和節(jié)流?如何實(shí)現(xiàn)跃捣?
防抖和節(jié)流都是防止短時(shí)間內(nèi)高頻觸發(fā)事件的方案漱牵。
防抖的原理是:如果一定時(shí)間內(nèi)多次執(zhí)行了某事件,則只執(zhí)行其中的最后一次疚漆。
節(jié)流的原理是:要執(zhí)行的事件每隔一段時(shí)間會(huì)被冷卻酣胀,無法執(zhí)行。
應(yīng)用場(chǎng)景有:搜索框?qū)崟r(shí)搜索愿卸,滾動(dòng)改變相關(guān)的事件灵临。
//@fn: 要執(zhí)行的函數(shù)//@delay: 設(shè)定的時(shí)限//防抖函數(shù)functiondebunce(fn,delay){letflag =null;returnfunction(){if(flag)clearTimeout(flag)//利用apply改變函數(shù)指向,使得封裝后的函數(shù)可以接收event本身flag =setTimeout(()=>fn.apply(this,arguments),delay)? }}//節(jié)流函數(shù)functionthrottle(fn,delay){letflag =true;returnfunction(){if(!flag)returnfalse;? ? flag =false;setTimeout(()=>{? ? ? fn.apply(this,arguments)? ? ? flag=true},delay)? }}復(fù)制代碼
14. 如何理解同步和異步趴荸?
同步:按照代碼書寫順序一一執(zhí)行處理指令的一種模式,上一段代碼執(zhí)行完才能執(zhí)行下一段代碼宦焦。
異步:可以理解為一種并行處理的方式发钝,不必等待一個(gè)程序執(zhí)行完,可以執(zhí)行其它的任務(wù)波闹。
JS之所以需要異步的原因在于JS是單線程運(yùn)行的酝豪。常用的異步場(chǎng)景有:定時(shí)器、ajax請(qǐng)求精堕、事件綁定孵淘。
15. JS是如何實(shí)現(xiàn)異步的?
JS引擎是單線程的歹篓,但又能實(shí)現(xiàn)異步的原因在于事件循環(huán)和任務(wù)隊(duì)列體系瘫证。
事件循環(huán):
JS 會(huì)創(chuàng)建一個(gè)類似于while (true)的循環(huán)揉阎,每執(zhí)行一次循環(huán)體的過程稱之為Tick。每次Tick的過程就是查看是否有待處理事件背捌,如果有則取出相關(guān)事件及回調(diào)函數(shù)放入執(zhí)行棧中由主線程執(zhí)行毙籽。待處理的事件會(huì)存儲(chǔ)在一個(gè)任務(wù)隊(duì)列中,也就是每次Tick會(huì)查看任務(wù)隊(duì)列中是否有需要執(zhí)行的任務(wù)毡庆。
任務(wù)隊(duì)列:
異步操作會(huì)將相關(guān)回調(diào)添加到任務(wù)隊(duì)列中坑赡。而不同的異步操作添加到任務(wù)隊(duì)列的時(shí)機(jī)也不同,如onclick,setTimeout,ajax處理的方式都不同么抗,這些異步操作是由瀏覽器內(nèi)核的webcore來執(zhí)行的毅否,瀏覽器內(nèi)核包含3種 webAPI,分別是DOM Binding蝇刀、network搀突、timer模塊。
onclick 由DOM Binding模塊來處理熊泵,當(dāng)事件觸發(fā)的時(shí)候仰迁,回調(diào)函數(shù)會(huì)立即添加到任務(wù)隊(duì)列中。setTimeout由timer模塊來進(jìn)行延時(shí)處理顽分,當(dāng)時(shí)間到達(dá)的時(shí)候徐许,才會(huì)將回調(diào)函數(shù)添加到任務(wù)隊(duì)列中。ajax由network模塊來處理卒蘸,在網(wǎng)絡(luò)請(qǐng)求完成返回之后雌隅,才將回調(diào)添加到任務(wù)隊(duì)列中。
主線程:
JS 只有一個(gè)線程缸沃,稱之為主線程恰起。而事件循環(huán)是主線程中執(zhí)行棧里的代碼執(zhí)行完畢之后,才開始執(zhí)行的趾牧。所以检盼,主線程中要執(zhí)行的代碼時(shí)間過長(zhǎng),會(huì)阻塞事件循環(huán)的執(zhí)行翘单,也就會(huì)阻塞異步操作的執(zhí)行吨枉。
只有當(dāng)主線程中執(zhí)行棧為空的時(shí)候(即同步代碼執(zhí)行完后),才會(huì)進(jìn)行事件循環(huán)來觀察要執(zhí)行的事件回調(diào)哄芜,當(dāng)事件循環(huán)檢測(cè)到任務(wù)隊(duì)列中有事件就取出相關(guān)回調(diào)放入執(zhí)行棧中由主線程執(zhí)行貌亭。
16. 什么是AJAX?如何實(shí)現(xiàn)认臊?
ajax是一種能夠?qū)崿F(xiàn)局部網(wǎng)頁(yè)刷新的技術(shù)圃庭,可以使網(wǎng)頁(yè)異步刷新。
ajax的實(shí)現(xiàn)主要包括四個(gè)步驟:
(1)創(chuàng)建核心對(duì)象XMLhttpRequest;
(2)利用open方法打開與服務(wù)器的連接剧腻;
(3)利用send方法發(fā)送請(qǐng)求拘央;("POST"請(qǐng)求時(shí),還需額外設(shè)置請(qǐng)求頭)
(4)監(jiān)聽服務(wù)器響應(yīng)恕酸,接收返回值堪滨。
//1-創(chuàng)建核心對(duì)象//該對(duì)象有兼容問題,低版本瀏覽器應(yīng)使用ActiveXObjectconstxthhp =newXMLHttpRequest();//2-連接服務(wù)器//open(method,url,async)xhttp.open("POST","http://localhost:3000",true)//設(shè)置請(qǐng)求頭xmlHttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded")蕊温;//3-發(fā)送請(qǐng)求//send方法發(fā)送請(qǐng)求參數(shù)袱箱,如為GET方法,則在open中url后拼接xhttp.send({_id:123})//4-接收服務(wù)器響應(yīng)//onreadystatechange事件义矛,會(huì)在xhttp的狀態(tài)發(fā)生變化時(shí)自動(dòng)調(diào)用xhttp.onreadystatechange =function(){//狀態(tài)碼共5種:0-未open? 1-已open? 2-已send? 3-讀取響應(yīng)? 4-響應(yīng)讀取結(jié)束if(xhttp.readyState ==4&& xhttp.status ==200){? alert("ajax請(qǐng)求已完成")? }}復(fù)制代碼
17. 實(shí)現(xiàn)異步的方式有哪些发笔?
(1)回調(diào)函數(shù)模式:將需要異步執(zhí)行的函數(shù)作為回調(diào)函數(shù)執(zhí)行,其缺點(diǎn)在于處理復(fù)雜邏輯異步邏輯時(shí)凉翻,會(huì)造成回調(diào)地獄(回調(diào)嵌套層數(shù)太多了讨,代碼結(jié)構(gòu)混亂);
(2)事件監(jiān)聽模式:采用事件驅(qū)動(dòng)的思想制轰,當(dāng)某一事件發(fā)生時(shí)觸發(fā)執(zhí)行異步函數(shù)前计,其缺點(diǎn)在于整個(gè)代碼全部得變?yōu)槭录?qū)動(dòng)模式,難以分辨主流程垃杖;
(3)發(fā)布訂閱模式:當(dāng)異步任務(wù)執(zhí)行完成時(shí)發(fā)布消息給信號(hào)中心男杈,其他任務(wù)通過在信號(hào)中心中訂閱消息來確定自己是否開始執(zhí)行;
(4)Promise(ES6):Promise對(duì)象共有三種狀態(tài)pending(初始化狀態(tài))调俘、fulfilled(成功狀態(tài))伶棒、rejected(失敗狀態(tài))。
(5)async/await(ES7):基于Promise實(shí)現(xiàn)的異步函數(shù)彩库;????(6)利用生成器實(shí)現(xiàn)肤无。
18. 怎么理解Promise對(duì)象?
Promise對(duì)象有如下兩個(gè)特點(diǎn):
(1)對(duì)象的狀態(tài)不受外界影響骇钦。Promise對(duì)象共有三種狀態(tài)pending宛渐、fulfilled、rejected司忱。狀態(tài)值只會(huì)被異步結(jié)果決定皇忿,其他任何操作無法改變。
(2)狀態(tài)一旦成型坦仍,就不會(huì)再變,且任何時(shí)候都可得到這個(gè)結(jié)果叨襟。狀態(tài)值會(huì)由pending變?yōu)閒ulfilled或rejected繁扎,這時(shí)即為resolved。
Promise的缺點(diǎn)有如下三個(gè)缺點(diǎn):
(1)Promise一旦執(zhí)行便無法被取消;
(2)不可設(shè)置回調(diào)函數(shù)梳玫,其內(nèi)部發(fā)生的錯(cuò)誤無法捕獲爹梁;
(3)當(dāng)處于pending狀態(tài)時(shí),無法得知其具體發(fā)展到了哪個(gè)階段提澎。
Pomise中常用的方法有:
(1)Promise.prototype.then():Promise實(shí)例的狀態(tài)發(fā)生改變時(shí)姚垃,會(huì)調(diào)用then內(nèi)部的回調(diào)函數(shù)。then方法接受兩個(gè)參數(shù)(第一個(gè)為resolved狀態(tài)時(shí)時(shí)執(zhí)行的回調(diào)盼忌,第一個(gè)為rejected狀態(tài)時(shí)時(shí)執(zhí)行的回調(diào))
(2)Promise.prototype.catch():.then(null, rejection)或.then(undefined, rejection)的別名积糯,用于指定發(fā)生錯(cuò)誤時(shí)的回調(diào)函數(shù)。
19. 怎么理解宏任務(wù)谦纱,微任務(wù)看成??跨嘉?
宏任務(wù)有:script(整體代碼)川慌、setTimeout、setInterval祠乃、I/O梦重、頁(yè)面渲染;
微任務(wù)有:Promise.then亮瓷、Object.observe琴拧、MutationObserver。
執(zhí)行順序大致如下:
主線程任務(wù)——>宏任務(wù)——>微任務(wù)——>微任務(wù)里的宏任務(wù)——>.......——>直到任務(wù)全部完成
20. 什么是跨域寺庄?怎么解決跨域問題艾蓝?
跨域問題實(shí)際是由同源策略衍生出的一個(gè)問題,當(dāng)傳輸協(xié)議斗塘、域名赢织、端口任一部分不一致時(shí),便會(huì)產(chǎn)生跨域問題馍盟,從而拒絕請(qǐng)求于置,但<img src=XXX> <link href=XXX><script src=XXX>;天然允許跨域加載資源。解決方案有:
(1)JSONP
原理:利用<script>;標(biāo)簽沒有跨域限制的漏洞贞岭,使得網(wǎng)頁(yè)可以得到從其他來源動(dòng)態(tài)產(chǎn)生的JSON數(shù)據(jù)(前提是服務(wù)器支持)八毯。
優(yōu)點(diǎn):實(shí)現(xiàn)簡(jiǎn)單,兼容性好瞄桨。
缺點(diǎn):僅支持get方法话速,容易受到XSS攻擊。
(2)CORS
原理:服務(wù)器端設(shè)置Access-Control-Allow-Origin以開啟CORS芯侥。該屬性表示哪些域名可以訪問資源泊交,如設(shè)置通配符則表示所有網(wǎng)站均可訪問固耘。
實(shí)現(xiàn)實(shí)例(express):
//app.js中設(shè)置varapp = express();//CORS跨域-------------------------------------------------------------------------------------// CORS:設(shè)置允許跨域中間件varallowCrossDomain =function(req, res, next){// 設(shè)置允許跨域訪問的 URL(* 表示允許任意 URL 訪問)res.header("Access-Control-Allow-Origin","*");// 設(shè)置允許跨域訪問的請(qǐng)求頭res.header("Access-Control-Allow-Headers","X-Requested-With,Origin,Content-Type,Accept,Authorization");// 設(shè)置允許跨域訪問的請(qǐng)求類型res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");// 設(shè)置允許服務(wù)器接收 cookieres.header('Access-Control-Allow-Credentials','true');? next();};app.use(allowCrossDomain);//------------------------------------------------------------------------------------復(fù)制代碼
(3)Node中間件代理
原理:同源策略僅是瀏覽器需要遵循的策略颜及,故搭建中間件服務(wù)器轉(zhuǎn)發(fā)請(qǐng)求與響應(yīng)辱志,達(dá)到跨域目的比庄。
/* server1.js 代理服務(wù)器(http://localhost:3000)*/consthttp =require('http')// 第一步:接受客戶端請(qǐng)求constserver = http.createServer((request, response) =>{// 代理服務(wù)器,直接和瀏覽器直接交互研乒,需要設(shè)置CORS 的首部字段response.writeHead(200,{'Access-Control-Allow-Origin':'*','Access-Control-Allow-Methods':'*','Access-Control-Allow-Headers':'Content-Type'})// 第二步:將請(qǐng)求轉(zhuǎn)發(fā)給服務(wù)器constproxyRequest = http.request({host:'127.0.0.1',port:4000,url:'/',method:request.method,headers:request.headers? ? ? },serverResponse=>{// 第三步:收到服務(wù)器的響應(yīng)varbody =''serverResponse.on('data',chunk=>{? ? ? ? ? body += chunk? ? ? ? })? ? ? ? serverResponse.on('end',()=>{console.log('The data is '+ body)// 第四步:將響應(yīng)結(jié)果轉(zhuǎn)發(fā)給瀏覽器response.end(body)? ? ? })? ? })? .end()? })server.listen(3000,()=>{console.log('中間件服務(wù)器地址: http://localhost:3000')})// server2.js(http://localhost:4000)consthttp =require("http");constdata = {title:"fontend",password:"123456"};constserver = http.createServer((request, response) =>{if(request.url ==="/") {? ? ? ? response.end(JSON.stringify(data));? ? }});server.listen(4000,() =>{console.log("The server is running at http://localhost:4000");});復(fù)制代碼
(4)nginx反向代理
原理:類似Node中間件服務(wù)器汹忠,通過nginx代理服務(wù)器實(shí)現(xiàn)。
實(shí)現(xiàn)方法:下載安裝nginx雹熬,修改配置宽菜。
21. 實(shí)現(xiàn)繼承的方法有哪些?橄唬?赋焕?
實(shí)現(xiàn)繼承的方法有:
(1)class+extends繼承(ES6)
//類模板classAnimal{constructor(name){this.name = name? }}//繼承類classCatextendsAnimal{//重點(diǎn)。extends方法仰楚,內(nèi)部用constructor+superconstructor(name){super(name);//super作為函數(shù)調(diào)用時(shí)隆判,代表父類的構(gòu)造函數(shù)}//constructor可省略eat(){console.log("eating")? }}復(fù)制代碼
(2)原型繼承
//類模板functionAnimal(name){this.name = name; }//添加原型方法Animal.prototype.eat =function(){console.log("eating")}functionCat(furColor){this.color = color ;};//繼承類Cat.prototype =newAnimal()//重點(diǎn):子實(shí)例的原型等于父類的實(shí)例復(fù)制代碼
(3)借用構(gòu)造函數(shù)繼承
functionAnimal(name){this.name = name}functionCat(){Animal.call(this,"CatName")//重點(diǎn),調(diào)用父類的call方法}復(fù)制代碼
(4)寄生組合式繼承(重點(diǎn))
22. DOM事件模型和事件流僧界?
DOM事件模型包括事件捕獲(自上而下觸發(fā))與事件冒泡(自下而上觸發(fā)侨嘀,ie用的就是冒泡)機(jī)制∥娼螅基于事件冒泡機(jī)制可以完成事件代理咬腕。
事件捕獲
事件冒泡
DOM事件流包括三個(gè)階段事件捕獲階段、處于目標(biāo)階段葬荷、事件冒泡階段涨共。
23. EventLoop事件循環(huán)是什么?
js是一門單線程的需要宠漩,它的異步操作都是通過事件循環(huán)來完成的举反。整個(gè)事件循環(huán)大體由執(zhí)行棧、消息隊(duì)列和微任務(wù)隊(duì)列三個(gè)部分組成扒吁。
同步代碼會(huì)直接在執(zhí)行棧中調(diào)用執(zhí)行火鼻。
定時(shí)器中的回調(diào)會(huì)在執(zhí)行棧被清空且定時(shí)達(dá)成時(shí)推入執(zhí)行棧中執(zhí)行。
promise雕崩、async異步函數(shù)的回調(diào)會(huì)被推入到微任務(wù)隊(duì)列中魁索,當(dāng)執(zhí)行棧被清空且異步操作完成時(shí)立即執(zhí)行。
24.require/import之間的區(qū)別盼铁?
(1)require是CommonJS語(yǔ)法粗蔚,import是ES6語(yǔ)法;
(2)require只在后端服務(wù)器支持饶火,import在高版本瀏覽器及Node中都可以支持支鸡;
(3)require引入的是原始導(dǎo)出值的復(fù)制冬念,import則是導(dǎo)出值的引用趁窃;
(4)require時(shí)運(yùn)行時(shí)動(dòng)態(tài)加載牧挣,import是靜態(tài)編譯;
(5)require調(diào)用時(shí)默認(rèn)不是嚴(yán)格模式醒陆,import則默認(rèn)調(diào)用嚴(yán)格模式.
作者:星始流年
鏈接:https://juejin.cn/post/6913022820691738631
來源:掘金
著作權(quán)歸作者所有瀑构。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請(qǐng)注明出處刨摩。