欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

2020年12道高頻JavaScript手寫面試題及答案

  發(fā)布時間:2020-01-06 16:21:47   作者:小耿學前端   我要評論
這篇文章主要介紹了2020年12道高頻JavaScript手寫面試題及答案,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

JavaScript筆試部分

本文分享 12 道高頻JavaScript的面試題,包含手寫以及常用的正則。

實現(xiàn)防抖函數(shù) (debounce)

防抖函數(shù)原理 : 在事件被觸發(fā)n秒后在執(zhí)行回調(diào),如果在這n秒內(nèi)又被觸發(fā),則重新計時。

那么與節(jié)流函數(shù)的區(qū)別直接看這個動畫實現(xiàn)即可。

手寫簡化版

//防抖函數(shù)
const debounce = (fn,delay)=>{
    let timer = null;
    return (...args)=>{
        clearTimeout(timer);
        timer = setTimeout(()=>{
        fn.apply(this,args)
        },delay);
    };
};

適用場景 :

  • 按鈕提交場景: 防止多次提交按鈕,只執(zhí)行最后提交的一次
  • 服務(wù)端驗證場景 : 表單驗證需要服務(wù)端配合,只執(zhí)行一段連續(xù)的輸入事件的最后一次,還有搜索聯(lián)想詞功能類似

生存環(huán)境請用lodash.debounce

實現(xiàn)節(jié)流函數(shù) (throttle)

防抖函數(shù)原理:規(guī)定在一單位時間內(nèi)。只能觸發(fā)一次函數(shù)。如果這個單位時間內(nèi)觸發(fā)多次函數(shù),只有一次生效。

//手寫簡化版
//節(jié)流函數(shù)
const throttle = (fn,delay = 500) =>{
    let flag = true;
    return (...args) =>{
        if (!flag) return;
        flag = false;
        setTimeout(() => {
        fn.apply(this,args)
        },delay);
    };
};

適用場景:

  • 拖拽場景: 固定時間內(nèi)只執(zhí)行一次,防止超高頻次觸發(fā)位置變動
  • 縮放場景: 監(jiān)控瀏覽器resize
  • 動畫場景: 避免短時間內(nèi)多次觸發(fā)動畫引起性能問題

深克隆 (deepclone)

簡單版 :

const newObj = JSON.parse(JSON.stringify(oldObj));

局限性 :
1、他無法實現(xiàn)函數(shù)、RegExp等特殊對象的克隆
2、會拋棄對象的constructor,所有的構(gòu)造函數(shù)會指向Object
3、對象有循環(huán)引用,會報錯

實現(xiàn)Event (event bus)

event bus既是node中各個模塊的基石,又是前端組件通信的依賴手段之一,同時涉及了訂閱-發(fā)布設(shè)計模式,是非常重要的基礎(chǔ)。

簡單版:

class EventEmeitter {
    constructor(){
        this._events = this._events || new Map(); //儲存事件/回調(diào)鍵值對
        this._maxListeners = this._maxListeners || 1o;//設(shè)立監(jiān)聽上限
    }
}

//觸發(fā)名為type的事件
EventEmeitter.prototype.emit = function(type,...args){
    let hander;
    //從儲存事件鍵值對的this._events中獲取對應(yīng)事件回調(diào)函數(shù)
    handler = this._events.get(type);
    if (args.length > 0) {
        hander.apply(this,args);
    }else{
        handler.call(this);
    }
    return true;
};

//監(jiān)聽名為type事件
EventEmeitter.prototype.addListener = function(type,fn) {
    //將type事件以及對應(yīng)的fn函數(shù)放入this._events中儲存
    if (!this._events.get(type)) {
        this._events.set(type,fn);
    }
};

實現(xiàn)instanceOf

//模擬 instanceof
function instance_of(L,R){
    var O = R.prototype;//取 R 的顯示原型
    L = L.__proto__;//取 L 的隱式原型
    while (true) {
        if (L === null) return false;
        if (O === L)
        // 這里重點 : 當 O 嚴格等于 L 時,返回 true
        return true;
        L = L.__proto__;
    }
}

模擬new

new操作符做了這些事:

  • 他創(chuàng)建了一個全新的對象
  • 他會被執(zhí)行[[Prototype]] (也就是__proto__) 鏈接
  • 它使this指向新創(chuàng)建的對象
  • 通過new創(chuàng)建的每個對象將最終被[[Prototype]]鏈接到這個函數(shù)的prototype對象上
  • 如果函數(shù)沒有返回對象類型Object(包含F(xiàn)unction,Array,Date,RegExg,Error),那么new表達式中的函數(shù)調(diào)用將返回對象引用
// objectFactory(name,'cxk','18')
function objectFactory(){
    const obj = new object();
    const Constructor = [].shift.call(arguments);
    
    obj.__proto__ = Constructor.prototype;
    
    const ret = Constructor.apply(obj,arguments);
    
    return typeof ret === "object" ? ret : obj;
}

實現(xiàn)一個call

call做了什么 :

  • 將函數(shù)設(shè)為對象的屬性
  • 執(zhí)行&刪除這個函數(shù)
  • 指定this到函數(shù)并傳人給定參數(shù)執(zhí)行函數(shù)
  • 如果不傳人參數(shù),默認指向為 window
//模擬 call bar.mycall(null);
//實現(xiàn)一個call方法;
Function.prototype.myCall = function(context){
    //此處沒有考慮context非object情況
    context.fn = this;
    let args = [];
    for (let i = 1,len = arguments.length,i < len; i++){
        args.push(arguments[i]);
    }
    context.fn(...args);
    let result = context.fn(...args);
    delete context.fn;
    return result;
};

實現(xiàn)apply方法

apply原理與call很相似,不多獒數(shù)

//模擬 apply
Function.prototype.myapply = function(context,arr){
    var context = Object(context) || window;
    context.fn = this;
    
    var result;
    if (!arr){
        result = context.fn();
    }else{
        var args = [];
        for (var i = 0,len = arr.length;i < len; i++){
            args.push("arr["+ i +"]");
        }
        result = eval("context.fn("+ args + ")");
    }
    delete context.fn;
    return result;
}

實現(xiàn)bind

實現(xiàn)bind要做什么

  • 返回一個函數(shù),綁定this,傳遞預(yù)置參數(shù)
  • bind返回的函數(shù)可以作為構(gòu)造函數(shù)使用。故作為構(gòu)造函數(shù)時應(yīng)使得this失效,但是傳人的參數(shù)依然有效

 

// mdn的實現(xiàn)
if (!Function.prototype.bind) {
  Function.prototype.bind = function(oThis) {
    if (typeof this !== 'function') {
      // closest thing possible to the ECMAScript 5
      // internal IsCallable function
      throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
    }

    var aArgs   = Array.prototype.slice.call(arguments, 1),
        fToBind = this,
        fNOP    = function() {},
        fBound  = function() {
          // this instanceof fBound === true時,說明返回的fBound被當做new的構(gòu)造函數(shù)調(diào)用
          return fToBind.apply(this instanceof fBound
                 ? this
                 : oThis,
                 // 獲取調(diào)用時(fBound)的傳參.bind 返回的函數(shù)入?yún)⑼沁@么傳遞的
                 aArgs.concat(Array.prototype.slice.call(arguments)));
        };

    // 維護原型關(guān)系
    if (this.prototype) {
    }
    // 下行的代碼使fBound.prototype是fNOP的實例,因此
    // 返回的fBound若作為new的構(gòu)造函數(shù),new生成的新對象作為this傳入fBound,新對象的__proto__就是fNOP的實例
    fBound.prototype = new fNOP();

    return fBound;
  };
}

詳解請移步JavaScript深入之bind的模擬實現(xiàn) #12

模擬Object.create

Object.create()方法創(chuàng)建一個新對象,使用現(xiàn)有的對象來提供新創(chuàng)建的對象的__proto__。
// 模擬 Object.create

function create(proto) {
  function F() {}
  F.prototype = proto;

  return new F();
}

模擬Object.create

Object.create() 方法創(chuàng)建一個新對象,使用現(xiàn)有的對象來提供新創(chuàng)建的對象的__proto__。

// 模擬 object.create

function create(proto){
    function F(){
        F.prototype = proto;
        
        return new F();
    }
}

解析 URL Params為對象

let url = 'http://www.domain.com/?user=anonymous&id=123&id=456&city=%E5%8C%97%E4%BA%AC&enabled';
parseParam(url)

/* 結(jié)果
{ user: 'anonymous',
  id: [ 123, 456 ], // 重復(fù)出現(xiàn)的 key 要組裝成數(shù)組,能被轉(zhuǎn)成數(shù)字的就轉(zhuǎn)成數(shù)字類型
  city: '北京', // 中文需解碼
  enabled: true, // 未指定值得 key 約定為 true
}
*/

轉(zhuǎn)化為駝峰命名

var s1 = "get-element-by-id"

//轉(zhuǎn)化為 getElementById

var f = function(s){
    return s.replace(/-\w/g,function(x){
      return x.slice(1).toUpperCase(); 
    })
}

本文主要是一些基礎(chǔ)知識,希望能幫助那些基礎(chǔ)不太好的同行們。加油~~~~~~

以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 新手怎么學JS?JavaScript基礎(chǔ)語法入門要學什么?

    這篇文章主要介紹了新手怎么學JS?JavaScript基礎(chǔ)語法入門要學什么?本文給大家介紹一個大致的學習路線和方向,需要的朋友趕緊一起來看看吧
    2020-03-19
  • 深入理解javascript作用域,作用域鏈,閉包的面試題

    這篇文章主要介紹了javascript作用域,作用域鏈,閉包的面試題,在一些前端面試中經(jīng)常會問題,今天小編特此整理分享到腳本之家平臺,需要的朋友可以參考下
    2020-02-21
  • JavaScript關(guān)于數(shù)組的四道面試題

    這篇文章主要介紹了JavaScript關(guān)于數(shù)組的四道面試題,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習
    2019-12-23
  • 11道JS選擇題(聽說第一題就難倒80%的人)

    這篇文章主要介紹了11道JS選擇題(聽說第一題就難倒80%的人),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-12-18
  • 10個比較流行的JavaScript面試題

    JS 初學者總是對this關(guān)鍵字感到困惑,因為與其他現(xiàn)代編程語言相比,JS 中的這this關(guān)鍵字有點棘手。今天小編給大家?guī)?0個比較流行的JavaScript面試題 ,感興趣的朋友一起
    2019-07-12
  • 10個JavaScript筆試題解析

    這篇文章主要介紹了10個JavaScript筆試題解析,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2020-06-02

最新評論