Javascript
-
數(shù)據(jù)類型
基本數(shù)據(jù)類型:string咪笑、number、boolean娄涩、symbol窗怒、undefined、null;
引用類型:Object扬虚、Array努隙、Function、Map等孔轴;
-
判斷數(shù)據(jù)類型方法
typeof:能夠快速區(qū)分基本數(shù)據(jù)類型剃法,但是引用類型判斷都返回object(eg: console.log(typeof function(){}); // function);
instanceof:能夠快速區(qū)分引用類型路鹰,適合判斷自定義類實(shí)例對(duì)象贷洲,但是基本數(shù)據(jù)類型不能判斷(eg:console.log(2 instanceof Number); // false);
Object.prototype.toString.call:精準(zhǔn)判斷所有數(shù)據(jù)類型(eg:console.log(toString.call(null)); //[object Null])晋柱;
-
原型优构、原型鏈
原型:實(shí)例對(duì)象上有
__proto__
隱式原型、構(gòu)造函數(shù)上有prototype
原型對(duì)象雁竞;__proto__
指向構(gòu)造函數(shù)的prototype
钦椭。原型鏈:原型與原型層層相連接的過程就是原型鏈。
-
var碑诉、let彪腔、const
var:聲明的變量,其作用域?yàn)樵撜Z句所在的函數(shù)內(nèi)进栽,且存在變量提升現(xiàn)象德挣,可重復(fù)定義;
let:聲明的變量快毛,其作用域?yàn)樵撜Z句所在的代碼塊內(nèi)格嗅,不存在變量提升;
const:聲明的變量不允許修改唠帝;
-
閉包
假如一個(gè)函數(shù)能訪問外部的變量屯掖,那么這個(gè)函數(shù)它就是一個(gè)閉包,而不是一定要返回一個(gè)函數(shù)襟衰;
-
閉包使用場(chǎng)景
在全局作用域中讀取內(nèi)部函數(shù)的變量贴铜;
防止函數(shù)內(nèi)部的變量執(zhí)行完成后被銷毀,使其一直保存在內(nèi)存中瀑晒;
封裝私有變量阀湿;
-
繼承
原型鏈繼承:將函數(shù)prototype指向新的對(duì)象,基于原型鏈瑰妄,既是父類的實(shí)例陷嘴,也是子類的實(shí)例;缺點(diǎn)是無法實(shí)現(xiàn)多繼承间坐,所有實(shí)例都會(huì)共享父類實(shí)例的屬性灾挨;
構(gòu)造繼承:將函數(shù)call綁定this邑退,可以實(shí)現(xiàn)多繼承(call多個(gè)),解決了所有實(shí)例共享父類實(shí)例屬性的問題劳澄;缺點(diǎn)是只能繼承父類實(shí)例的屬性和方法地技,不能繼承原型上的屬性和方法;
組合繼承:將上面兩種組合使用秒拔,可以繼承實(shí)例屬性/方法莫矗,也可以繼承原型屬性/方法;缺點(diǎn)是調(diào)用了兩次父類構(gòu)造函數(shù)砂缩,生成了兩份實(shí)例作谚;
-
淺拷貝、深拷貝
淺拷貝:只拷貝對(duì)象里面的數(shù)據(jù)庵芭,不拷貝對(duì)象里面的子對(duì)象妹懒;淺拷貝可以通過assign和三點(diǎn)擴(kuò)展運(yùn)算符方式實(shí)現(xiàn)
深拷貝:克隆出一個(gè)新的對(duì)象,數(shù)據(jù)相同双吆,但引用地址不同眨唬;深拷貝可以通過loadash.cloneDeep實(shí)現(xiàn),或者遞歸拷貝好乐,或者轉(zhuǎn)json字符串再轉(zhuǎn)json(會(huì)忽略u(píng)ndefined匾竿、symbol,不能序列化函數(shù)和解決循環(huán)引用對(duì)象)蔚万;
-
call岭妖、apply、bind
三個(gè)函數(shù)的作用都是將函數(shù)綁定到上下文中笛坦,用來改變函數(shù)中this的指向区转,借用已實(shí)現(xiàn)的方法苔巨,減少重復(fù)代碼版扩,節(jié)省內(nèi)存。
call:改變函數(shù)的this上下文后馬上執(zhí)行該函數(shù)侄泽,接收參數(shù)若干個(gè)參數(shù)列表礁芦;
Function.prototype.myCall = function(context, ...args) {
context = context || window
let fn = Symbol()
context[fn] = this
let result = context[fn](...args)
delete context[fn]
return result
}
apply:改變函數(shù)的this上下文后馬上執(zhí)行該函數(shù),接收參數(shù)是數(shù)組悼尾;
Function.prototype.myApply = function(context) {
context = context || window
let fn = Symbol()
context[fn] = this
let result
if (arguments[1]) {
result = context[fn](...arguments[1])
} else {
result = context[fn]()
}
delete context[fn]
return result
}
bind:返回改變了上下文后的函數(shù)柿扣,不執(zhí)行該函數(shù),接收參數(shù)若干個(gè)參數(shù)列表闺魏;
Function.prototype.myBind = function (context) {
var _this = this
var args = [...arguments].slice(1)
// 返回一個(gè)函數(shù)
return function F() {
// 因?yàn)榉祷亓艘粋€(gè)函數(shù)未状,我們可以 new F(),所以需要判斷
if (this instanceof F) {
return new _this(...args, ...arguments)
}
return _this.apply(context, args.concat(...arguments))
}
}
- ==和===區(qū)別
==:兩邊值類型不同的時(shí)候析桥,要先進(jìn)行類型轉(zhuǎn)換司草,再比較
如果類型不同艰垂,進(jìn)行類型轉(zhuǎn)換
判斷比較的是否是 null 或者是 undefined, 如果是, 返回 true .
判斷兩者類型是否為 string 和 number, 如果是, 將字符串轉(zhuǎn)換成 number
判斷其中一方是否為 boolean, 如果是, 將 boolean 轉(zhuǎn)為 number 再進(jìn)行判斷
判斷其中一方是否為 object 且另一方為 string、number 或者 symbol , 如果是, 將 object 轉(zhuǎn)為原始類型再進(jìn)行判斷
===:不做類型轉(zhuǎn)換埋虹,類型不同的一定不等
- 防抖和節(jié)流
防抖:防止函數(shù)多次調(diào)用猜憎,將多次執(zhí)行變?yōu)樽詈笠淮螆?zhí)行;
節(jié)流:防止函數(shù)多次調(diào)用搔课,將多次執(zhí)行變?yōu)槊扛粢欢螘r(shí)間執(zhí)行胰柑;
- 宏任務(wù)和微任務(wù)
宏任務(wù)(Task):同步代碼、setTimeout 回調(diào)爬泥、setInteval 回調(diào)柬讨、IO、UI 交互事件急灭、postMessage姐浮、MessageChannel;
微任務(wù)(MicroTask):Promise 狀態(tài)改變以后的回調(diào)函數(shù)(then 函數(shù)執(zhí)行葬馋,如果此時(shí)狀態(tài)沒變卖鲤,回調(diào)只會(huì)被緩存,只有當(dāng)狀態(tài)改變畴嘶,緩存的回調(diào)函數(shù)才會(huì)被丟到任務(wù)隊(duì)列)蛋逾、Mutation observer 回調(diào)函數(shù)、queueMicrotask 回調(diào)函數(shù)(新增的 API)窗悯;
宏任務(wù)會(huì)被丟到下一次事件循環(huán)区匣,并且宏任務(wù)隊(duì)列每次只會(huì)執(zhí)行一個(gè)任務(wù);微任務(wù)會(huì)被丟到本次事件循環(huán)蒋院,并且微任務(wù)隊(duì)列每次都會(huì)執(zhí)行任務(wù)直到隊(duì)列為空亏钩;假如每個(gè)微任務(wù)都會(huì)產(chǎn)生一個(gè)微任務(wù),那么宏任務(wù)永遠(yuǎn)都不會(huì)被執(zhí)行了欺旧;
- EventLoop
執(zhí)行?同步代碼
執(zhí)行完所有同步代碼后且執(zhí)行棧為空姑丑,判斷是否有微任務(wù)需要執(zhí)行
執(zhí)行所有微任務(wù)且微任務(wù)隊(duì)列為空
是否有必要渲染頁(yè)面
執(zhí)行一個(gè)宏任務(wù)
- localStorage、sessionStorage辞友、cookie栅哀、indexDB
localStorage:一直存在,除非手動(dòng)清理称龙,存儲(chǔ)大小5M留拾;
sessionStorage:tab標(biāo)簽頁(yè)關(guān)閉就自動(dòng)清理,存儲(chǔ)大小5M鲫尊;
cookie:由服務(wù)器生成痴柔、可設(shè)置過期時(shí)間,每次攜帶在請(qǐng)求header中疫向,存儲(chǔ)大小4K咳蔚;
indexDB:一直存在扛施,除非手動(dòng)清理,存儲(chǔ)大小沒有限制屹篓;
- 模塊化
AMD:依賴前置疙渣,提前執(zhí)行 (require.js),語法是define堆巧,require
CMD:依賴就近妄荔,延遲執(zhí)行 (sea.js),語法是 define谍肤,seajs.use([],cb)
CommonJS:CommonJS語法 module.exports=fn或者exports.a=1; 通過require('./a1')來引入啦租;CommonJs模塊首次執(zhí)行會(huì)被緩存,再次加載只返回緩存結(jié)果荒揣,require返回的值是輸出值的拷貝(對(duì)于引用類型是淺拷貝)
ES6 Module:es6 module 語法是 export {...}, import ...from..., export輸出的是值得引用
NodeJS篷角、webpack都是基于CommonJS該規(guī)范來實(shí)現(xiàn)的
- CommonJS和ES6 Module區(qū)別
Commonjs是同步導(dǎo)入,因用于服務(wù)端系任,文件都在本地恳蹲,同步導(dǎo)入即使卡住主線程影響也不大,后者是異步導(dǎo)入俩滥,因?yàn)橛糜跒g覽器端嘉蕾,需下載文件,如果采用同步導(dǎo)入對(duì)渲染會(huì)有很大影響霜旧。
CommonJS 在導(dǎo)出時(shí)都是值的拷貝错忱,就算導(dǎo)出的值變了,導(dǎo)入的值也不會(huì)變挂据。如果想更新以清,必須重新導(dǎo)入一回。
ES Module 導(dǎo)入導(dǎo)出的值指向同一個(gè)內(nèi)存地址崎逃。所以掷倔,導(dǎo)入值也會(huì)隨著導(dǎo)出值變化。
ES Module 會(huì)編譯成 require/exports來執(zhí)行婚脱。