日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

當前位置:首頁 > 科技  > 軟件

13個 JavaScript 面試難題及代碼實現

來源: 責編: 時間:2024-07-15 17:11:30 138觀看
導讀今天我將帶你深入了解 14 個常見的 JavaScript 高級面試問題。這些問題涵蓋了 JavaScript 的面向對象、事件循環機制、Promise 等高級概念,以及函數柯里化和深度復制等實用技術。我們不僅從概念層面對每個問題進行了分

今天我將帶你深入了解 14 個常見的 JavaScript 高級面試問題。這些問題涵蓋了 JavaScript 的面向對象、事件循環機制、Promise 等高級概念,以及函數柯里化和深度復制等實用技術。Gza28資訊網——每日最新資訊28at.com

Gza28資訊網——每日最新資訊28at.com

我們不僅從概念層面對每個問題進行了分析,還提供了具體的代碼實現。Gza28資訊網——每日最新資訊28at.com

那我們現在就開始吧。Gza28資訊網——每日最新資訊28at.com

1.this關鍵字指向

this關鍵字指向當前執行上下文中的一個對象。在函數中,this關鍵字通常指向函數的調用者。Gza28資訊網——每日最新資訊28at.com

問題:以下代碼輸出什么?為什么?Gza28資訊網——每日最新資訊28at.com

const obj = {  name: 'obj',  getName: function() {    return function() {      return this.name;    }  }}const fn = obj.getName();fn();

答案:undefinedGza28資訊網——每日最新資訊28at.com

分析:因為getName函數內部是在全局作用域內執行的,這里的this指向window/global,而window/global沒有name屬性,所以返回undefined。Gza28資訊網——每日最新資訊28at.com

如果想讓內部函數的this也指向obj,可以使用箭頭函數或者bind綁定this:Gza28資訊網——每日最新資訊28at.com

const obj = {  name: 'obj',  getName: function() {    return () => {       return this.name;    }  }}

2.閉包的實現與應用

問題:實現一個計數器工廠函數:Gza28資訊網——每日最新資訊28at.com

function createCounter() {  let count = 0;  return function() {    return count++;   }} const counter1 = createCounter();const counter2 = createCounter();counter1(); // 1counter1(); // 2 counter2(); // 1

解析:不同的計數器之所以能獨立遞增,是因為利用了閉包的特性。createCounter函數創建了一個閉包,在其外層作用域中可以訪問變量count,counter1和counter2引用不同的閉包函數實例,從而實現了計數獨立性。Gza28資訊網——每日最新資訊28at.com

3.事件循環機制

問:對事件循環機制做一下解釋說明。Gza28資訊網——每日最新資訊28at.com

答:事件循環機制主要有以下幾個流程:Gza28資訊網——每日最新資訊28at.com

  1. 同步任務在主線程執行,形成執行上下文棧。
  2. 執行棧中同步任務執行完后,系統會讀取隊列中的異步任務,如Promise.then()、setTimeout、AJAX回調等。
  3. 異步任務會被加入到任務隊列中
  4. 清空執行棧后,系統會檢查任務隊列,如果不為空,則取出第一個任務放到執行棧中執行。
  5. 主線程重復了棧和隊列交替執行的過程,從而實現了線程的排隊執行。

事件循環允許在同一個線程中交替執行同步任務和異步任務,充分利用CPU資源。這對于支持UI交互和響應性的JavaScript來說很重要。Gza28資訊網——每日最新資訊28at.com

4.Promise對象

問題:實現Promise的簡單版本:Gza28資訊網——每日最新資訊28at.com

Promise對象是處理異步事件的異步編程解決方案。Promise對象可以表示異步操作的狀態,包括:Gza28資訊網——每日最新資訊28at.com

  • pending
  • fulfilled
  • rejected

Promise對象的實現如下:Gza28資訊網——每日最新資訊28at.com

class MyPromise {  constructor(executor) {    this._state = "pending";    this._value = undefined;    this._reason = undefined;    this._onFulfilledCallbacks = [];    this._onRejectedCallbacks = [];    executor(this.resolve.bind(this), this.reject.bind(this));  }  resolve(value) {    if (this._state !== "pending") {      return;    }    this._state = "fulfilled";    this._value = value;    setTimeout(() => {      for (const callback of this._onFulfilledCallbacks) {        callback(value);      }    });  }  reject(reason) {    if (this._state !== "pending") {      return;    }    this._state = "rejected";    this._reason = reason;    setTimeout(() => {      for (const callback of this._onRejectedCallbacks) {        callback(reason);      }    });  }  then(onFulfilled, onRejected) {    return new MyPromise((resolve, reject) => {      if (this._state === "pending") {        this._onFulfilledCallbacks.push((value) => {          setTimeout(() => {            try {              const result = onFulfilled(value);              resolve(result);            } catch (error) {              reject(error);            }          });        });        this._onRejectedCallbacks.push((reason) => {          setTimeout(() => {            try {              const result = onRejected(reason);              resolve(result);            } catch (error) {              reject(error);            }          });        });      } else {        setTimeout(() => {          try {            if (this._state === "fulfilled") {              const result = onFulfilled(this._value);              resolve(result);            } else {              const result = onRejected(this._reason);              resolve(result);            }          } catch (error) {            reject(error);          }        });      }    });  }  catch(onRejected) {    return this.then(null, onRejected);  }  isFulfilled() {    return this._state === "fulfilled";  }  isRejected() {    return this._state === "rejected";  }}

分析:Gza28資訊網——每日最新資訊28at.com

  1. MyPromise類是一個自定義的Promise類,其構造函數接受一個執行函數作為參數。
  2. 構造函數中的執行函數會被立即執行,并接受兩個參數resolve和reject,用于修改Promise的狀態。
  3. resolve方法用于將Promise的狀態從“pending”修改為“fulfilled”,并將值傳遞給后續的handler。
  4. reject方法用于將Promise的狀態從“pending”修改為“rejected”,并將原因傳遞給后續的handler。
  5. then方法用于注冊一個回調函數,在Promise完成或被拒絕時執行,它接受兩個參數onFulfilled和onRejected,分別在Promise完成或被拒絕時調用。
  6. then方法返回一個新的MyPromise實例,以支持鏈式調用。如果 onFulfilled 或 onRejected 返回一個值,它將被用作下一個 MyPromise 實例的解析值。
  7. catch 方法是 then(null, onRejected) 的簡寫形式。
  8. isFulfilled 方法用于檢查 Promise 是否處于已實現狀態。
  9. isRejected 方法用于檢查 Promise 是否處于已拒絕狀態。

5.類繼承實現

原型鏈是每個對象的一個屬性,它指向該對象構造函數的原型對象。一個構造函數的原型對象指向另一個構造函數的原型對象,依此類推。Gza28資訊網——每日最新資訊28at.com

問題:要實現一個 People 類,可以通過構造函數或 new 操作符實例化對象。同時,它有一個繼承 Person 類的方法。Person 類有一個 sayHi 方法:Gza28資訊網——每日最新資訊28at.com

class Person {  constructor(name) {    this.name = name;  }  sayHi() {    console.log(`Hello ${this.name}`)  }}class People extends Person {  constructor(name) {    super(name);  }  method() {    console.log('people method')  }}const people = new People('John')people.sayHi() // Hello Johnpeople.method() // people method

分析:通過構造函數調用super繼承屬性,原型鏈實現方法繼承。Gza28資訊網——每日最新資訊28at.com

6.MVC與MVVM模式

問:簡述MVC與MVVM的概念和區別?Gza28資訊網——每日最新資訊28at.com

答:MVC模式中:Gza28資訊網——每日最新資訊28at.com

  1. Model負責管理數據邏輯
  2. View負責顯示界面
  3. Controller連接Model與View并傳遞數據

MVVM模式中:Gza28資訊網——每日最新資訊28at.com

  1. Model負責管理數據邏輯
  2. View負責顯示界面
  3. ViewModel作為View與Model的交互代理,將Model同步到View,將View的變化同步回Model。

區別在于:Gza28資訊網——每日最新資訊28at.com

  • MVVM中沒有Controller的角色,View直接將數據綁定到ViewModel。
  • ViewModel負責將數據轉換成View可以識別的格式,提供給View使用。
  • ViewModel可以將View的變化通知回Model層,實現雙向數據綁定。
  • MVVM可以解耦View與Model之間的緊耦合,利于單元測試和組件開發。

7.Ajax實現

問題:實現一個ajax請求函數:Gza28資訊網——每日最新資訊28at.com

ajax('/api/users', {  method: 'GET'  }).then(data => {  console.log(data)})

回答:Gza28資訊網——每日最新資訊28at.com

function ajax(url, options) {  return new Promise((resolve, reject) => {    const xhr = new XMLHttpRequest();    const method = options.method || 'GET';    const headers = options.headers || {};    const body = options.body || null;    const timeout = options.timeout || 0;    xhr.open(method, url);    xhr.onload = () => {      if (xhr.status >= 200 && xhr.status < 300) {        resolve(xhr.response);      } else {        reject(new Error(xhr.statusText));      }    };    xhr.onerror = () => reject(xhr.error);    xhr.ontimeout = () => reject(new Error('Request timeout'));    xhr.timeout = timeout;    for (const [header, value] of Object.entries(headers)) {      xhr.setRequestHeader(header, value);    }    xhr.send(body);  });}

實現一個支持Promise的ajax請求函數:Gza28資訊網——每日最新資訊28at.com

  • 使用XMLHttpRequest對象發送請求
  • 初始化open方法,配置請求方法和url
  • 添加onload和onerror回調函數
  • onload判斷狀態碼是否在200–300范圍內resolve,否則reject

onerror直接rejectGza28資訊網——每日最新資訊28at.com

  • 請求成功后resolve返回response,失敗后reject報錯。
  • 支持options配置請求參數和請求體
  • 返回一個Promise對象,可以使用then/catch進行外部處理

分析:使用Promise封裝異步ajax請求,實現同步編程風格。Gza28資訊網——每日最新資訊28at.com

8.JSONP跨域實現

問題:實現一個JSONP跨域請求:Gza28資訊網——每日最新資訊28at.com

jsonp('/api/data', {  params: {    name: 'jsonp'  }  })

回答:Gza28資訊網——每日最新資訊28at.com

function jsonp(url, options) {  return new Promise((resolve, reject) => {    const script = document.createElement('script');    const callbackName = `jsonpCallback_${Date.now()}_${Math.floor(Math.random() * 10000)}`;    const timer = setTimeout(() => {      cleanup();      reject(new Error('JSONP request timeout'));    }, options.timeout || 5000);    function cleanup() {      delete window[callbackName];      clearTimeout(timer);      script.remove();    }    window[callbackName] = function(data) {      cleanup();      resolve(data);    };    options.params = options.params || {};    options.params['callback'] = callbackName;    const paramsArr = Object.keys(options.params).map(key => {      return `${encodeURIComponent(key)}=${encodeURIComponent(options.params[key])}`;    });    script.src = `${url}?${paramsArr.join('&')}`;    script.onerror = () => {      cleanup();      reject(new Error('JSONP request error'));    };    document.body.appendChild(script);  });}

分析:創建腳本節點script.src,設置回調函數callbackName,解析參數并拼接URL,動態插入body中實現JSONP跨域請求,返回Promise接口。Gza28資訊網——每日最新資訊28at.com

9.實現深度克隆

問題:實現一個函數deepClone,實現對象的深度克隆:Gza28資訊網——每日最新資訊28at.com

答案:Gza28資訊網——每日最新資訊28at.com

function deepClone(source, clonedMap) {  clonedMap = clonedMap || new Map();  if (source === null || typeof source !== 'object') {    return source;  }  if (clonedMap.has(source)) {    return clonedMap.get(source);  }  var result;  var type = getType(source);  if (type === 'object' || type === 'array') {    result = type === 'array' ? [] : {};    clonedMap.set(source, result);    for (var key in source) {      if (source.hasOwnProperty(key)) {        result[key] = deepClone(source[key], clonedMap);      }    }  } else {    result = source;  }  return result;}function getType(source) {  return Object.prototype.toString    .call(source)    .replace(/^/[object (.+)/]$/, '$1')    .toLowerCase();}const obj = {  a: 1,  b: {    c: 2  }}const clone = deepClone(obj)

分析:遞歸實現對象和數組的深度克隆,直接返回基本類型,引用類型遞歸分層調用深度克隆。Gza28資訊網——每日最新資訊28at.com

10.函數柯里化

問題:實現一個可以把1+2+3加起來的add函數:Gza28資訊網——每日最新資訊28at.com

function add() {     // When executing for the first time, define an array specifically to store all parameters     var _args = [].slice.call(arguments);     // Declare a function internally, use the characteristics of closure to save _args and collect all parameter values     var adder = function () {         var _adder = function() {             // [].push.apply(_args, [].slice.call(arguments));             _args.push(...arguments);             return _adder;         };         //Using the characteristics of implicit conversion, implicit conversion is performed when it is finally executed, and the final value is calculated and returned.         _adder.toString = function () {             return _args.reduce(function (a, b) {                 return a + b;             });         }         return _adder;     }     // return adder.apply(null, _args);     return adder(..._args);}var a = add(1)(2)(3)(4); // f 10var b = add(1, 2, 3, 4); // f 10var c = add(1, 2)(3, 4); // f 10var d = add(1, 2, 3)(4); // f 10// You can use the characteristics of implicit conversion to participate in calculationsconsole.log(a + 10); // 20console.log(b + 20); // 30console.log(c + 30); // 40console.log(d + 40); // 50// You can also continue to pass in parameters, and the result will be calculated using implicit conversion again.console.log(a(10) + 100); // 120console.log(b(10) + 100); // 120console.log(c(10) + 100); // 120console.log(d(10) + 100); // 120//In fact, the add method in Shangli is the curried function of the following function, but we do not use the general formula to convert, but encapsulate it ourselves.function add(...args) {     return args.reduce((a, b) => a + b);}

分析:add函數的柯里化是通過遞歸調用一個不斷接受參數的函數來實現的。Gza28資訊網——每日最新資訊28at.com

11.實現promise.all方法

問題:實現一個myAll方法,類似Promise.all:Gza28資訊網——每日最新資訊28at.com

myAll([  myPromise1,   myPromise2]).then(([res1, res2]) => {  //...})

回答:Gza28資訊網——每日最新資訊28at.com

function myAll(promises) {  return new Promise((resolve, reject) => {    const result = new Array(promises.length);    let count = 0;    promises.forEach((p, index) => {      p.then(res => {        result[index] = res;        count++;        if (count === promises.length) {          resolve(result);        }      })      .catch(reject);    });  });}

分析:利用Promise.all原理,通過計數器和結果數組同步Promise狀態。Gza28資訊網——每日最新資訊28at.com

12.實現Instanceof

問題:實現一個instanceof操作符Gza28資訊網——每日最新資訊28at.com

答案:Gza28資訊網——每日最新資訊28at.com

function instanceof(left, right) {  if (arguments.length !== 2) {    throw new Error("instanceof requires exactly two arguments.");  }  if (left === null) {    return false;  }  if (typeof left !== "object") {    return false;  }  let proto = Object.getPrototypeOf(left);  while (proto !== null) {    if (right.prototype === proto) {      return true;    }    proto = Object.getPrototypeOf(proto);  }  return false;}

以上代碼用于判斷一個對象是否是另一個對象的實例。Gza28資訊網——每日最新資訊28at.com

JavaScript 中的 instanceof 運算符可用于判斷一個對象是否是另一個對象的實例。但是,instanceof 運算符有一些限制,例如:Gza28資訊網——每日最新資訊28at.com

  1. instanceof 運算符只能確定與原型鏈直接相連的對象。
  2. instanceof 運算符無法檢測具有循環原型鏈的對象。
  3. 因此,以上代碼提供了一個更通用的 instanceof 函數,可以確定任意兩個對象之間的關系。
  4. 該函數的實現原理是:
  5. instanceof 函數接收兩個參數:left 和 right。
  6. 首先,代碼檢查參數數量是否為 2,如果不是,則拋出錯誤。
  7. 接下來,代碼檢查左操作數 left 是否為 null。如果是,則直接返回 false,因為 null 不能是任何對象的實例。
  8. 然后,代碼檢查左操作數 left 的類型是否為對象。如果不是,則直接返回false,因為只有對象才能是構造函數的實例。
  9. 接下來,代碼使用Object.getPrototypeOf()獲取左操作數left的原型,并將其賦值給變量proto。
  10. 在循環中,代碼繼續遍歷proto的原型鏈,直到proto為null。
  11. 在循環中,代碼檢查右操作數right的原型是否等于當前的proto,如果相等,則表示左操作數left是右操作數right的實例,返回true。
  12. 如果在循環結束時沒有找到匹配的原型,即proto為null,則表示左操作數left不是右操作數right的實例,返回false。

該函數可以在以下場景中使用:Gza28資訊網——每日最新資訊28at.com

  1. 判斷一個對象是否是另一個對象的實例。
  2. 判斷一個對象是否從另一個對象繼承而來。
  3. 判斷一個對象是否屬于某個特定的類。

13. 實現 debounce 防抖功能

問題:實現 debounce 防抖功能Gza28資訊網——每日最新資訊28at.com

答案:Gza28資訊網——每日最新資訊28at.com

function debounce(fn, delay = 500) {   let timer;   return function(...args) {     clearTimeout(timer);     timer = setTimeout(() => {       fn.apply(this, args);     }, delay);     // Return to clear function     return () => {       clearTimeout(timer);     }   }}// useconst debouncedFn = debounce(fn, 1000);const cancel = debouncedFn();// clearcancel();


Gza28資訊網——每日最新資訊28at.com

本文鏈接:http://www.www897cc.com/showinfo-26-100982-0.html13個 JavaScript 面試難題及代碼實現

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: Python excel、word報表生成神器

下一篇: 大廠內幕:SpringBoot項目為何棄用Tomcat,轉投Undertow懷抱?

標簽:
  • 熱門焦點
  • vivo TWS Air開箱體驗:真輕 臻好聽

    在vivo S15系列新機的發布會上,vivo的最新款真無線藍牙耳機vivo TWS Air也一同發布,本次就這款耳機新品給大家帶來一個簡單的分享。外包裝盒上,vivo TWS Air保持了vivo自家產
  • 7月安卓手機性能榜:紅魔8S Pro再奪榜首

    7月份的手機市場風平浪靜,除了紅魔和努比亞帶來了兩款搭載驍龍8Gen2領先版處理器的新機之外,別的也想不到有什么新品了,這也正常,通常6月7月都是手機廠商修整的時間,進入8月份之
  • 六大權益!華為8月服務日開啟:手機免費貼膜、維修免人工費

    8月5日消息,一年一度的華為開發者大會2023(Together)日前在松山湖拉開帷幕,與此同時,華為8月服務日也式開啟,到店可享六大專屬權益。華為用戶可在華為商城Ap
  • 服務存儲設計模式:Cache-Aside模式

    Cache-Aside模式一種常用的緩存方式,通常是把數據從主存儲加載到KV緩存中,加速后續的訪問。在存在重復度的場景,Cache-Aside可以提升服務性能,降低底層存儲的壓力,缺點是緩存和底
  • 分布式系統中的CAP理論,面試必問,你理解了嘛?

    對于剛剛接觸分布式系統的小伙伴們來說,一提起分布式系統,就感覺高大上,深不可測。而且看了很多書和視頻還是一臉懵逼。這篇文章主要使用大白話的方式,帶你理解一下分布式系統
  • 2023年,我眼中的字節跳動

    此時此刻(2023年7月),字節跳動從未上市,也從未公布過任何官方的上市計劃;但是這并不妨礙它成為中國最受關注的互聯網公司之一。從2016-17年的抖音強勢崛起,到2018年的&ldquo;頭騰
  • 當家的盒馬,加速謀生

    來源 | 價值星球Planet作者 | 歸去來自己&ldquo;當家&rdquo;的盒馬,開始加速謀生了。據盒馬官微消息,盒馬計劃今年開放生鮮供應鏈,將其生鮮商品送往食堂。目前,盒馬在上海已經與
  • 小米MIX Fold 3下月亮相:今年唯一無短板的全能折疊屏

    這段時間以來,包括三星、一加、榮耀等等有不少品牌旗下的最新折疊屏旗艦都有新的進展,其中榮耀、三星都已陸續發布了最新的折疊屏旗艦,尤其號榮耀Magi
  • 華為Mate60系列模具曝光:采用碩大圓形后置相機模組+拼接配色方案

    據此前多方爆料,今年華為將開始恢復一年雙旗艦戰略,除上半年推出的P60系列外,往年下半年的Mate系列也將迎來更新,有望在9-10月份帶來全新的華為Mate60
Top 主站蜘蛛池模板: 章丘市| 威海市| 油尖旺区| 海淀区| 恩施市| 涞源县| 桦川县| 伊吾县| 邓州市| 隆林| 永福县| 厦门市| 松滋市| 辽中县| 徐闻县| 满城县| 浦北县| 抚松县| 阿坝| 海安县| 水城县| 麦盖提县| 福建省| 永定县| 萍乡市| 文安县| 马边| 长寿区| 昌邑市| 海伦市| 南和县| 浦县| 启东市| 卢龙县| 万宁市| 毕节市| 大兴区| 连江县| 彭州市| 丰县| 阜阳市|