人妻精品在线观看一区二区三区,蜜臀av精品一区二区三区网站,中文一区二区三区亚洲欧美,熟女人妇精品一区二区,人妻av在线观看视频,欧美日韩国产三级精品网站,黄色免费网站直接进入,超碰公开福利正在播放,国产毛片乡下农村妇女毛片

看看這些前端面試題,帶你搞定高頻知識(shí)點(diǎn)(八)-今日視點(diǎn)

來(lái)源:php中文網(wǎng) | 2023-03-06 19:58:56 |

本篇文章給大家整理總結(jié)一些JavaScript 面試題,帶你搞定高頻知識(shí)點(diǎn),希望對(duì)大家有所幫助!


【資料圖】

var、let、const

三者的區(qū)別

區(qū)別letconstvar
重復(fù)聲明不能重復(fù)聲明,會(huì)報(bào)SyntaxError錯(cuò)const 定義常量,值不能修改的變量叫做常量,一定要賦初始值,因?yàn)椴荒苄薷摹?/td>可以重復(fù)聲明
塊級(jí)作用域擁有擁有不擁有
會(huì)不會(huì)污染全局變量(掛載在window上)不會(huì)不會(huì)會(huì)

說(shuō)明 1.let和const也存在變量提升,只是提升的方式不同

var變量提升:變量的聲明提升到頂部,值為undefinedlet、const變量提升: 變量聲明提升到頂部,只不過(guò)將該變量標(biāo)記為尚未初始化let 和 const存在暫時(shí)性死區(qū),代碼執(zhí)行過(guò)程中的一段時(shí)間內(nèi),在此期間無(wú)法使用標(biāo)識(shí)符,也不能引用外層作用域的變量。
let answer;function fn(){//如果此時(shí)沒(méi)有將變量變量提升到這里,answer應(yīng)該取外層answer的值console.log(answer); //Uncaught ReferenceError: Cannot access "answer" before initializationlet answer=42;}

2.var創(chuàng)建的全局變量->全局對(duì)象的屬性,let和const在全局作用域聲明的變量->不是全局對(duì)象的屬性

3.如果常量是個(gè)數(shù)組或?qū)ο?,?duì)其內(nèi)部元素修改,不算對(duì)常量的修改,不會(huì)報(bào)錯(cuò)。常量指向了一個(gè)地址,地址不變就不會(huì)報(bào)錯(cuò)。

變量提升和函數(shù)提升

變量聲明升級(jí) 通過(guò)var定義(聲明)的變量,在定義語(yǔ)句之前的就可以訪問(wèn)到 但是值是undefined

函數(shù)聲明提升 通過(guò)function聲明的函數(shù),在之前就可以直接調(diào)用。值是函數(shù)體

//變量提升先于函數(shù)提升,提升后被函數(shù)聲明function覆蓋,所以就算換了順序也是functionfunction a(){}var a ;console.log(typeof a); //functionvar f1 = function () {    console.log(1);}function f1 () {    console.log(2);}f1() ; //1//變量提升后var f1;//變量提升function f1(){};//函數(shù)提升f1 = function () {    console.log(1);}f1() ;

變量提升練習(xí)題

作用域和作用域鏈

理解:一個(gè)代碼段所在的區(qū)域,是靜態(tài)的,在編寫代碼時(shí)就確定了。 作用:變量綁定在這個(gè)作用域內(nèi)有效,隔離變量,不同作用域下同名變量不會(huì)有沖突。 作用域分類

全局作用域

函數(shù)作用域

塊級(jí)作用域

作用域鏈:多個(gè)作用域嵌套,就近選擇,先在自己作用域找,然后去就近的作用域找。

函數(shù)的作用域在聲明的時(shí)候就已經(jīng)決定了,與調(diào)用位置無(wú)關(guān)所以執(zhí)行aaa()的時(shí)候先在aaa的作用域里面找,沒(méi)有找到a,再去父級(jí)作用域window里面找,找到a=10

var a = 10;  function aaa() {    alert(a);}function bbb() {    var a = 20;    aaa();}bbb();

執(zhí)行上下文

對(duì)當(dāng)前JavaScript的執(zhí)行環(huán)境的抽象,每當(dāng)JavaScript開始執(zhí)行的時(shí)候,它都在執(zhí)行上下文中運(yùn)行。

全局執(zhí)行上下文:在執(zhí)行全局代碼前將window確定為全局執(zhí)行上下文

對(duì)全局?jǐn)?shù)據(jù)進(jìn)行預(yù)處理

var定義的全局變量 --> undefined,添加為window的屬性

function聲明的全局函數(shù) --> 賦值(函數(shù)體),添加為window的方法

this --> 賦值window

開始執(zhí)行全局代碼

函數(shù)執(zhí)行上下文:在調(diào)用函數(shù),準(zhǔn)備執(zhí)行函數(shù)體之前,創(chuàng)建對(duì)應(yīng)的函數(shù)執(zhí)行上下文對(duì)象

對(duì)局部數(shù)據(jù)進(jìn)行預(yù)處理

形參變量 --> 賦值(實(shí)參)–> 添加到函數(shù)執(zhí)行上下文的屬性arguments(形參列表封裝成的偽數(shù)組)–>賦值(實(shí)參列表),添加到函數(shù)執(zhí)行上下文的屬性var定義的局部變量–>undefined,添加為函數(shù)執(zhí)行上下文的屬性function聲明的函數(shù)–>賦值(函數(shù)體),添加為函數(shù)執(zhí)行上下文的方法this–>賦值(調(diào)用函數(shù)的對(duì)象)開始執(zhí)行函數(shù)體代碼

執(zhí)行上下文棧1.在全局代碼執(zhí)行前,JS引擎就會(huì)創(chuàng)建一個(gè)棧來(lái)存儲(chǔ)管理所有的執(zhí)行上下文對(duì)象 2.在全局執(zhí)行上下文(window)確定后,將其添加到棧中(壓棧) 3.在函數(shù)執(zhí)行上下文創(chuàng)建后,將其添加到棧中(壓棧) 4.在當(dāng)前函數(shù)執(zhí)行完成后,將棧頂?shù)膶?duì)象移除(出棧) 5.當(dāng)所有的代碼執(zhí)行完后,棧中只剩下window

作用域執(zhí)行上下文
定義了幾個(gè)函數(shù) + 1 = 幾個(gè)作用域執(zhí)行了幾個(gè)函數(shù) + 1 = 幾個(gè)執(zhí)行上下文
函數(shù)定義時(shí)就確定了,一直存在,不會(huì)再變化,是靜態(tài)的全局執(zhí)行上下文環(huán)境實(shí)在全局作用域確定之后,js代碼執(zhí)行之前創(chuàng)建的調(diào)用函數(shù)時(shí)創(chuàng)建,函數(shù)調(diào)用結(jié)束被釋放,是動(dòng)態(tài)的
var foo = 1;function bar () {    console.log(foo);    var foo = 10;    console.log(foo);}bar();//變量提升后var foo = 1;function bar () {var foo = undefined;    console.log(foo); //undefined    foo = 10;    console.log(foo);//10}bar();

如何用ES5實(shí)現(xiàn)let和const

let:使用立即執(zhí)行函數(shù)創(chuàng)造出一個(gè)塊級(jí)作用域

(function(){  var a = 1;  console.log("內(nèi)部a:", a);})();

const1.使用立即執(zhí)行函數(shù)創(chuàng)造出一個(gè)塊級(jí)作用域。 2.對(duì)于不可變性,可以利用Object.defineProperty將變量掛載在對(duì)象上

var __const = function __const(data, value) {this.data = value // 把要定義的data掛載到某個(gè)對(duì)象,并賦值valueObject.defineProperty(this,data, { // 利用Object.defineProperty的能力劫持當(dāng)前對(duì)象,并修改其屬性描述符enumerable: false,configurable: false,get: function () {return value},set: function (data) {if (data !== value) { // 當(dāng)要對(duì)當(dāng)前屬性進(jìn)行賦值時(shí),則拋出錯(cuò)誤!throw new TypeError("Assignment to constant variable.")} else {return value}}})}//然后和立即執(zhí)行函數(shù)結(jié)合(function(){ var obj = {}_const.call(obj,"a",10)})()//當(dāng)執(zhí)行完畢后,全局上就不會(huì)有obj,也不會(huì)有obj.a這個(gè)變量,進(jìn)而實(shí)現(xiàn)了塊級(jí)作用域的功能

代碼輸出題

function a(){  a.name ="aaa";  return this.name;}var b = {  a,  name:"bbb",  getName:function(){    return this.name;  }}var c =b.getName;console.log(a()); //this指向window,window上沒(méi)有name,所以輸出undefinedconsole.log(b.a()); //b.a 是function,b調(diào)用a函數(shù),所以this指向b,所以輸出"bbb"console.log(b.getName);//通過(guò)b調(diào)用getName,所以getName指向b,所以輸出"bbb"console.log(c());//c是function,this指向window,window上沒(méi)有name,所以輸出undefined

數(shù)據(jù)類型

筆記鏈接

JS數(shù)據(jù)類型有哪些介紹一下Symbol和Bigint如何判斷一個(gè)數(shù)據(jù)類型Object.prototype.toString.call() 的缺點(diǎn)?各個(gè)方法的原理是什么typeof(NaN) typeof(Null)手寫 instanceof 方法null==undefined 和 null===undefined隱式轉(zhuǎn)換規(guī)則 === 和 == 的區(qū)別map和weakmap區(qū)別map和object區(qū)別for in、for of 區(qū)別,分別對(duì)對(duì)象和數(shù)組使用問(wèn)結(jié)果講一下數(shù)組的遍歷方法,filter與map的使用場(chǎng)景,some,every的區(qū)別map的操作原理map和forEach的區(qū)別使用迭代器實(shí)現(xiàn)for-of手寫數(shù)組去重手寫數(shù)組扁平化map和filter的區(qū)別數(shù)組的常用方法用reduce實(shí)現(xiàn)map

ES6 class和 ES5類的區(qū)別

ES5 function類ES6 class
可以new可以調(diào)用必須new調(diào)用,不能直接執(zhí)行
function存在變量提升class不存在變量提升
static靜態(tài)方法只能通過(guò)類調(diào)用,不會(huì)出現(xiàn)在實(shí)例上

this的指向

一般函數(shù)中this的指向會(huì)在調(diào)用時(shí)向函數(shù)傳遞執(zhí)行上下文對(duì)象中設(shè)置。以函數(shù)形式調(diào)用,指向window以方法形式調(diào)用,this指向調(diào)用的方法以構(gòu)造函數(shù)的形式調(diào)用,this是新創(chuàng)建的對(duì)象箭頭函數(shù):本身沒(méi)有this,它的this可以沿作用域鏈(定義時(shí)就確定了的)查找

bind、call、apply的區(qū)別與實(shí)現(xiàn)

apply、call、bind 函數(shù)可以改變 this 的指向。

區(qū)別callapplybind
調(diào)用函數(shù)×
參數(shù)從第二個(gè)參數(shù)開始依次傳遞封裝成數(shù)組傳遞從第二個(gè)參數(shù)開始依次傳遞

bind函數(shù)的特殊點(diǎn)多次綁定,只指向第一次綁定的obj對(duì)象。 多次綁定,一次生效。 原因:返回函數(shù),后續(xù)bind修改的是返回函數(shù)的this

call函數(shù)的實(shí)現(xiàn)

//從第二個(gè)參數(shù)開始依次傳入,所以接收時(shí)使用rest參數(shù)Function.prototype.call=function(obj,...args){obj = obj || window;args = args ? args : [];//給obj新增一個(gè)獨(dú)一無(wú)二的屬性以免覆蓋原有屬性    const key = Symbol()obj[key] = this;const res = obj[key](...args);delete obj[key];return res;}

apply函數(shù)的實(shí)現(xiàn)

Function.prototype.apply=function(obj,args){obj = obj || window;args = args ? args : [];//給obj新增一個(gè)獨(dú)一無(wú)二的屬性以免覆蓋原有屬性    const key = Symbol()obj[key] = this;const res = obj[key](...args);delete obj[key];return res;}

bind函數(shù)的實(shí)現(xiàn)

Function.prototype.bind=function(obj,...args){obj = obj || window;args = args ? args : [];return (...args2) => {return this.apply(obj,[...args,...args2])}}

一般函數(shù)和箭頭函數(shù)

箭頭函數(shù)的作用:確保函數(shù)內(nèi)部的this和外部的this是一樣的

箭頭函數(shù)是普通函數(shù)的語(yǔ)法糖,書寫要更加簡(jiǎn)潔

區(qū)別一般函數(shù)箭頭函數(shù)
this指向調(diào)用時(shí)確定定義時(shí)確定,沒(méi)有自己的this,沿著作用域鏈找父級(jí)的this
改變this指向call,apply,bind不能改變,靜態(tài)
arguments沒(méi)有,可以用rest參數(shù)代替
作為構(gòu)造函數(shù)× 沒(méi)有prototype屬性
匿名函數(shù)可以匿名可以不匿名匿名函數(shù)

閉包

是什么閉包就是在函數(shù)中能夠讀取其他函數(shù)內(nèi)部變量

function foo(){var a=2;function bar(){ //覆蓋foo()內(nèi)部作用域的閉包c(diǎn)onsole.log(a++);}return bar;}var bar = foo(); //foo執(zhí)行創(chuàng)建一個(gè)執(zhí)行上下文環(huán)境,由于bar引用了其內(nèi)部變量,也就是bar持有foo本次執(zhí)行上下文的引用,foo本次的執(zhí)行上下文不會(huì)被銷魂bar();//2bar();//3var fn = foo(); //foo執(zhí)行創(chuàng)建一個(gè)新的執(zhí)行上下文環(huán)境,fn持有了foo本次執(zhí)行上下文的引用fn();//2

有什么用1.可以讀取函數(shù)內(nèi)部的變量 2.使函數(shù)的內(nèi)部變量執(zhí)行完后,仍然存活在棧內(nèi)存中(延長(zhǎng)了局部變量的生命周期)。

JavaScript閉包就是在另一個(gè)作用域中保存了一份它從上一級(jí)函數(shù)或者作用域得到的變量,而這些變量是不會(huì)隨上一級(jí)函數(shù)的執(zhí)行完成而銷毀

常用場(chǎng)景:節(jié)流防抖缺點(diǎn)是什么1.函數(shù)執(zhí)行完后,函數(shù)內(nèi)的局部變量沒(méi)有釋放,占用內(nèi)存時(shí)間會(huì)變長(zhǎng) 2.容易造成內(nèi)存泄露怎么解決及時(shí)釋放:讓內(nèi)部函數(shù)成為垃圾對(duì)象(將閉包手動(dòng)設(shè)置為null)–> 回收閉包

手寫節(jié)流和防抖函數(shù)

作用是:控制回調(diào)函數(shù)觸發(fā)的頻率,進(jìn)行性能優(yōu)化 參數(shù): 控制觸發(fā)頻率的回調(diào)函數(shù)和時(shí)間wait 輸出: 到時(shí)間后,返回callback函數(shù)

節(jié)流:在函數(shù)被頻繁觸發(fā)時(shí), 函數(shù)執(zhí)行一次后,只有大于設(shè)定的執(zhí)行周期后才會(huì)執(zhí)行第二次。一個(gè)時(shí)間段,只觸發(fā)一次語(yǔ)法:throttle(callback, wait) 常用場(chǎng)景:比如拖動(dòng)、滾動(dòng)和輸入框聯(lián)想

//使用形式,綁定時(shí)候throttle函數(shù)就會(huì)執(zhí)行,所以this是windowwindow.addEventListener("scroll",throttle(()=>{},500))/*思路需要記錄上一次觸發(fā)的時(shí)間,才可以和當(dāng)前時(shí)間比較,是否超過(guò)了間隔時(shí)間第一次必然立刻觸發(fā)*/function throttle(callback,wait){let pre = new Date();//這里的this是windowreturn function(...args){//這里的this是綁定的DOMconst now = new Date();if(now-pre>=wait){callback.apply(this,args);pre = now;}}}/*使用setTimeout實(shí)現(xiàn)第一次需要延遲delay后觸發(fā)*/function throttle(callback,delay){let timer = null;//這里的this是windowreturn function(...args){if(timer){//說(shuō)明已經(jīng)觸發(fā)了return;}timer = setTimeout(()=>{callback.apply(this,args);timer = null;},delay)}}

函數(shù)防抖:指定時(shí)間間隔內(nèi)只會(huì)執(zhí)行一次任務(wù)。如果在等待的過(guò)程中再一次觸發(fā)了事件,計(jì)時(shí)器重新開始計(jì)時(shí),直到達(dá)到時(shí)間后執(zhí)行最后一次的回調(diào) 語(yǔ)法:debounce(callback, wait) 常用場(chǎng)景: 登錄、發(fā)短信等按鈕避免用戶點(diǎn)擊太快,以致于發(fā)送了多次請(qǐng)求,需要防抖。

function debounce(callback,delay){let timer = null;//這里的this是windowreturn function(){if(timer){//說(shuō)明已經(jīng)觸發(fā)了clearTimeout(timer);}timer = setTimeout(()=>{callback.apply(this,arguments);timer = null;},delay)}}//立即執(zhí)行function debounce(func,delay) {  let timeout;  return function (...args) {      if (timeout) clearTimeout(timeout);      const callNow = !timeout;      timeout = setTimeout(() => {          timeout = null;      }, delay)      if (callNow) func.apply(this, args)  }}

原型和原型鏈

筆記鏈接

原型和原型鏈繼承

JavaScript 線程機(jī)制與事件循環(huán)機(jī)制

筆記鏈接

內(nèi)容

進(jìn)程和線程進(jìn)程的通信方式瀏覽器多進(jìn)程架構(gòu)如何實(shí)現(xiàn)瀏覽器多標(biāo)簽之間的通訊H5 Web Workers JS多線程運(yùn)行瀏覽器的事件循環(huán)機(jī)制Node的事件循環(huán)機(jī)制node事件循環(huán)代碼輸出題 用于理解代碼輸出題

DOM渲染

筆記

內(nèi)容

DOM的渲染過(guò)程DOM渲染的時(shí)機(jī)與渲染進(jìn)程的概述 -瀏覽器的渲染流程CSS、JS、DOM解析和渲染阻塞問(wèn)題JS加載阻塞DOM渲染問(wèn)題,怎么解決? - 異步JS,JS三種異步加載的方式script 標(biāo)簽中的 async 和 defer 屬性DOMContentLoaded和LoadDOM渲染優(yōu)化

重繪和回流

筆記

內(nèi)容

什么是重繪和回流回流和重繪觸發(fā)的時(shí)機(jī)優(yōu)化方案GPU加速,如何開啟GPU加速JS優(yōu)化減少重繪和回流的觸發(fā)

setTimeout 、setInterval、requestAnimationFrame

筆記

內(nèi)容

setTimeout(cb, 0)會(huì)立刻執(zhí)行嗎?settimeout定時(shí)的時(shí)間準(zhǔn)確嗎? 為什么不準(zhǔn)確? 怎么解決?setTimeout和requestAnimation的區(qū)別requestAnimationFrame講一下你的理解setTimeout實(shí)際延遲時(shí)間用setTimeout實(shí)現(xiàn)setInterval,實(shí)現(xiàn)一個(gè)隨時(shí)停止的版本setTimeout 和 setInterval區(qū)別JS實(shí)現(xiàn)動(dòng)畫的方式requestAnimationFrame與requestIdleCallback分別是什么?requestAnimationFrame的執(zhí)行時(shí)機(jī)?requestanimationframe回調(diào)函數(shù)中進(jìn)行大量計(jì)算,會(huì)阻塞頁(yè)面的渲染嗎每隔一秒輸出一個(gè)數(shù)字

觀察者模式和發(fā)布訂閱機(jī)制

觀察者是軟件設(shè)計(jì)模式中的一種,但發(fā)布訂閱只是軟件架構(gòu)中的一種消息范式

觀察者模式

觀察者模式定義對(duì)象間的一種一對(duì)多的依賴關(guān)系,當(dāng)一個(gè)對(duì)象的狀態(tài)發(fā)生改變時(shí),所有依賴于它的對(duì)象都得到通知并被自動(dòng)更新。

被依賴的對(duì)象叫做subject,依賴的對(duì)象叫做觀察者Observer 。被依賴的對(duì)象首先需要提供一個(gè)添加觀察者方法,以供觀察者調(diào)用。所以還需要維護(hù)一個(gè)觀察者列表,自身發(fā)生變化后,依次通知觀察者。

//subject 被觀察者class Subject {  constructor() {    this.observerList = [];  }  addObserver(observer) {    this.observerList.push(observer);  }  removeObserver(observer) {    const index = this.observerList.findIndex(o => o.name === observer.name);    this.observerList.splice(index, 1);  }  notifyObservers(message) {    const observers = this.observeList;    observers.forEach(observer => observer.notified(message));  }}//Observer 觀察者class Observer {  constructor(name, subject) {    this.name = name;    if (subject) {      subject.addObserver(this);    }  }  notified(message) {    console.log(this.name, "got message", message);  }}//使用const subject = new Subject();const observerA = new Observer("observerA", subject);const observerB = new Observer("observerB");subject.addObserver(observerB);subject.notifyObservers("Hello from subject");subject.removeObserver(observerA);subject.notifyObservers("Hello again");

發(fā)布訂閱機(jī)制發(fā)布者和訂閱者不直接進(jìn)行通信,通過(guò)事件調(diào)度中心進(jìn)行管理。發(fā)布者將要發(fā)布的消息交由事件調(diào)度中心管理,訂閱者也是根據(jù)自己的情況,按需訂閱事件調(diào)度中心的消息。

//事件調(diào)度中心class PubSub {  constructor() {        // 存儲(chǔ)格式: warTask: [], routeTask: []        // {訂閱事件:[回調(diào)1,回調(diào)2...],訂閱事件2:[回調(diào)1,回調(diào)2..]}        this.events = {}     }     // 訂閱方法 訂閱哪個(gè)類型type就把對(duì)應(yīng)的回調(diào)函數(shù)放入      subscribe(type, cb) {         if (!this.events[type]) {            this.events[type] = [];        }        this.events[type].push(cb);     }     // 發(fā)布方法    publish(type, ...args) {        if (this.events[type]) {            this.events[type].forEach(cb => cb(...args))        }    }// 取消訂閱方法 的某一個(gè)類型的某一個(gè)回調(diào)    unsubscribe(type, cb) {        if (this.events[type]) {            const cbIndex = this.events[type].findIndex(e=> e === cb)            if (cbIndex != -1) {                this.events[type].splice(cbIndex, 1);            }        }        if (this.events[type].length === 0) {            delete this.events[type];        }    }}//測(cè)試let pubsub = new PubSub();//訂閱pubsub.subscribe("warTask", function (taskInfo){    console.log("宗門殿發(fā)布戰(zhàn)斗任務(wù),任務(wù)信息:" + taskInfo);})pubsub.subscribe("routeTask", function (taskInfo) {    console.log("宗門殿發(fā)布日常任務(wù),任務(wù)信息:" + taskInfo);});pubsub.subscribe("allTask", function (taskInfo) {    console.log("宗門殿發(fā)布五星任務(wù),任務(wù)信息:" + taskInfo);});//發(fā)布pubsub.publish("warTask", "獵殺時(shí)刻");pubsub.publish("allTask", "獵殺時(shí)刻");pubsub.publish("routeTask", "種樹澆水");pubsub.publish("allTask", "種樹澆水");

區(qū)別

類型描述特點(diǎn)
觀察者模式觀察者和被觀察者互相知道身份,目標(biāo)直接將通知分發(fā)到觀察者身上高耦合
發(fā)布訂閱機(jī)制發(fā)布訂閱機(jī)制通過(guò)事件調(diào)度中心來(lái)協(xié)調(diào),訂閱者和發(fā)布者互相不知道身份低耦合

異步編程解決方案 Generator生成器函數(shù) async/await、Promise

筆記鏈接

筆記內(nèi)容

Generator生成器函數(shù)Generator生成器函數(shù)使用上的補(bǔ)充 了解基于Promise對(duì)象的簡(jiǎn)單自動(dòng)執(zhí)行器iterator迭代器async/await是什么? 使用場(chǎng)景是什么?await/async與generator函數(shù)的區(qū)別await/async內(nèi)部實(shí)現(xiàn)原理 Generator函數(shù)和自動(dòng)執(zhí)行器async錯(cuò)誤捕獲方式promise概述promise知識(shí)點(diǎn) 了解promise.then、catch、finally的原理與實(shí)現(xiàn)Promise.all/Promise.race/Promise.allSettled的原理和實(shí)現(xiàn)手寫題:請(qǐng)求五秒未完成則終止promise實(shí)現(xiàn)并發(fā)的異步任務(wù)調(diào)度器

擴(kuò)展運(yùn)算符的原理和應(yīng)用

淺拷貝和深拷貝

深淺拷貝只是針對(duì)引用數(shù)據(jù)類型區(qū)分點(diǎn): 復(fù)制之后的副本進(jìn)行修改會(huì)不會(huì)影響到原來(lái)的

淺拷貝:修改拷貝以后的數(shù)據(jù)會(huì)影響原數(shù)據(jù)。使得原數(shù)據(jù)不安全。(只拷貝一層)深拷貝:修改拷貝以后的數(shù)據(jù)不會(huì)影響原數(shù)據(jù),拷貝的時(shí)候生成新數(shù)據(jù)。

淺拷貝

擴(kuò)展運(yùn)算符,適用于數(shù)組/對(duì)象

Aarry.prototype.concat(拷貝對(duì)象1,拷貝對(duì)象2...)數(shù)組的合并方法,將多個(gè)數(shù)組或?qū)ο罂截愡M(jìn)目標(biāo)數(shù)組,返回新數(shù)組。

Object.assign(目標(biāo)對(duì)象1,拷貝對(duì)象1,拷貝對(duì)象2.....)對(duì)象的合并方法,將拷貝對(duì)象拷貝進(jìn)目標(biāo)對(duì)象

深拷貝

方式一: JSON.parse(JSON.stringify())

JSON.stringify():將JavaScript對(duì)象轉(zhuǎn)換為JSON字符串JSON.parse():可以將JSON字符串轉(zhuǎn)為一個(gè)對(duì)象。

問(wèn)題1: 函數(shù)屬性會(huì)丟失,不能克隆方法 問(wèn)題2: 循環(huán)引用會(huì)出錯(cuò)

//循環(huán)引用:b中引用了c,c中又有bobj = {b:["a","f"],c:{h:20}}obj.b.push(obj.c);obj.c.j = obj.b;b:["a","f",{h:20,j:[]}],c:{h:20,j:["a","f",[]]}function deepClone1(target) {    //通過(guò)數(shù)組創(chuàng)建JSON格式的字符串    let str = JSON.stringify(target);    //將JSON格式的字符串轉(zhuǎn)換為JS數(shù)據(jù)    let data = JSON.parse(str);    return data;}

方式二:遞歸+map遞歸:實(shí)現(xiàn)深拷貝,不丟失屬性 map:存儲(chǔ)已經(jīng)拷貝過(guò)的對(duì)象,解決循環(huán)引用問(wèn)題

//map存放已經(jīng)拷貝過(guò)的對(duì)象,key為需要拷貝的對(duì)象,value為拷貝后的對(duì)象function deepClone(target,map=new Map()){//1.判斷是否是引用類型if(typeof target === "object" && target !==null ){if(map.has(target))return map.get(target); //說(shuō)明已經(jīng)拷貝過(guò)了let isArr = Array.isArray(target);let res = isArr?[]:{};map.set(target,res)if(isArr){//拷貝的是數(shù)組target.forEach((item,index) => {res[index] = deepClone(item,map);});}else{//拷貝的是對(duì)象Object.keys(target).forEach(key=>{res[key]=deepClone(target[key],map);})} return res; //返回的是一個(gè)數(shù)組或?qū)ο髛else{return target;}}//測(cè)試console.log(deepClone([1,[1,2,[3,4]]]))

commonJS和ES6模塊化

筆記鏈接

內(nèi)容

commonJs實(shí)現(xiàn)原理模塊執(zhí)行的原理require模塊加載原理ES6 module的特性import() 函數(shù) 動(dòng)態(tài)引入commonJs和es module的區(qū)別

【推薦學(xué)習(xí):javascript高級(jí)教程】

以上就是看看這些前端面試題,帶你搞定高頻知識(shí)點(diǎn)(八)的詳細(xì)內(nèi)容,更多請(qǐng)關(guān)注php中文網(wǎng)其它相關(guān)文章!

關(guān)鍵詞: javascript