2020年了,12道高频 JavaScript 手写面试题及答案





JavaScript笔试部分

本文分享 12 道高频JavaScript的面试题,包含手写以及常用的正则。

实现防抖函数 (debounce)


防抖函数原理 : 在事件被触发n秒后在执行回调,如果在这n秒内又被触发,则重新计时。

那么与节流函数的区别直接看这个动画实现即可。


手写简化版

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

适用场景 :

  • 按钮提交场景: 防止多次提交按钮,只执行最后提交的一次

  • 服务端验证场景 : 表单验证需要服务端配合,只执行一段连续的输入事件的最后一次,还有搜索联想词功能类似

生存环境请用lodash.debounce


实现节流函数 (throttle)


防抖函数原理:规定在一单位时间内。只能触发一次函数。如果这个单位时间内触发多次函数,只有一次生效。

//手写简化版

//节流函数const throttle = (fn,delay = 500) =>{    let flag = true;    return (...args) =>{        if (!flag) return;        flag = false;        setTimeout(() => {        fn.apply(this,args)        },delay);    };};

适用场景:

  • 拖拽场景: 固定时间内只执行一次,防止超高频次触发位置变动

  • 缩放场景: 监控浏览器resize

  • 动画场景: 避免短时间内多次触发动画引起性能问题


深克隆 (deepclone)


简单版 :

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

局限性 :1、他无法实现函数、RegExp等特殊对象的克隆

2、会抛弃对象的constructor,所有的构造函数会指向Object

3、对象有循环引用,会报错

实现Event (event bus)


event bus既是node中各个模块的基石,又是前端组件通信的依赖手段之一,同时涉及了订阅-发布设计模式,是非常重要的基础。

简单版:

class EventEmeitter {    constructor(){        this._events = this._events || new Map(); //储存事件/回调键值对        this._maxListeners = this._maxListeners || 1o;//设立监听上限    }}
//触发名为type的事件EventEmeitter.prototype.emit = function(type,...args){    let hander;    //从储存事件键值对的this._events中获取对应事件回调函数    handler = this._events.get(type);    if (args.length > 0) {        hander.apply(this,args);    }else{        handler.call(this);    }    return true;};
//监听名为type事件EventEmeitter.prototype.addListener = function(type,fn) {    //将type事件以及对应的fn函数放入this._events中储存    if (!this._events.get(type)) {        this._events.set(type,fn);    }};

实现instanceOf

//模拟 instanceoffunction 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操作符做了这些事:

  • 他创建了一个全新的对象

  • 他会被执行[[Prototype]] (也就是__proto__) 链接

  • 它使this指向新创建的对象

  • 通过new创建的每个对象将最终被[[Prototype]]链接到这个函数的prototype对象上

  • 如果函数没有返回对象类型Object(包含Function,Array,Date,RegExg,Error),那么new表达式中的函数调用将返回对象引用

// 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;}

实现一个call


call做了什么 :

  • 将函数设为对象的属性

  • 执行&删除这个函数

  • 指定this到函数并传人给定参数执行函数

  • 如果不传入参数,默认指向为 window

//模拟 call bar.mycall(null);//实现一个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;};

实现apply方法


apply原理与call很相似,不多獒数

//模拟 applyFunction.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;}

实现bind


实现bind要做什么

  • 返回一个函数,绑定this,传递预置参数

  • bind返回的函数可以作为构造函数使用。故作为构造函数时应使得this失效,但是传人的参数依然有效

// mdn的实现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的构造函数调用          return fToBind.apply(this instanceof fBound                ? this                : oThis,                // 获取调用时(fBound)的传参.bind 返回的函数入参往往是这么传递的                aArgs.concat(Array.prototype.slice.call(arguments)));        };
    // 维护原型关系    if (this.prototype) {    }    // 下行的代码使fBound.prototype是fNOP的实例,因此    // 返回的fBound若作为new的构造函数,new生成的新对象作为this传入fBound,新对象的__proto__就是fNOP的实例    fBound.prototype = new fNOP();
    return fBound;  };}详解请移步JavaScript深入之bind的模拟实现 #12
模拟Object.createObject.create()方法创建一个新对象,使用现有的对象来提供新创建的对象的__proto__。// 模拟 Object.create
function create(proto) {  function F() {}  F.prototype = proto;
  return new F();}

模拟Object.create


Object.create() 方法创建一个新对象,使用现有的对象来提供新创建的对象的__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)
/* 结果{ user: 'anonymous',  id: [ 123, 456 ], // 重复出现的 key 要组装成数组,能被转成数字的就转成数字类型  city: '北京', // 中文需解码  enabled: true, // 未指定值的 key 约定为 true}*/

转化为驼峰命名

var s1 = "get-element-by-id"
//转化为 getElementById
var f = function(s){    return s.replace(/-\w/g,function(x){      return x.slice(1).toUpperCase();    })}

本文主要是一些基础知识,希望能帮助那些基础不太好的同行们。加油~~~~~~


源自:https://juejin.im/post/5e100cdef265da5d75243229

声明:文章著作权归作者所有,如有侵权,请联系小编删除。


感谢 · 转发


欢迎关注


                                                 

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容

  • JavaScript笔试部分 点击关注本公众号「程序员面试官」获取文档最新更新,并可以领取配套于本指南的 《前端面...
    寻找海蓝阅读 963评论 0 24
  • 函数和对象 1、函数 1.1 函数概述 函数对于任何一门语言来说都是核心的概念。通过函数可以封装任意多条语句,而且...
    道无虚阅读 4,521评论 0 5
  • 本文中讲述到的面试题: 说说对闭包的认识, 它解决了什么问题?跨域问题有哪些处理方式?for...in 和 for...
    写代码的胖猴子阅读 1,099评论 0 5
  • 前端开发面试题 面试题目: 根据你的等级和职位的变化,入门级到专家级,广度和深度都会有所增加。 题目类型: 理论知...
    怡宝丶阅读 2,568评论 0 7
  • PNG 有PNG8和truecolor PNG PNG8类似GIF颜色上限为256,文件小,支持alpha透明度,...
    hudaren阅读 1,500评论 0 0