您当前的位置:首页 > 电脑百科 > 程序开发 > 语言 > javascript

前端面试这些API必须会手写(面试)

时间:2019-09-10 11:07:25  来源:  作者:

 

在面试中,常常会遇到一些手写XXX之类的面试题,因此好好总结一下,对于巩固我们的原生js的基础是非常必要的。

尽管在网上已经有了非常多的总结文章,但在我看来有一个普遍的问题,那就是把原理性的东西过于复杂化了。如果站在面试官的角度,他的目的是在最短的时间内考察出面试者对于JS语言的理解程度,但是在看了网站的诸多总结文章后我发现其中的代码有很大一部分是做意义不大的操作,比如实现一个简单的防抖,只要是核心的流程展示即可,至于其他的一些等模式则没有必要再去深挖,一大堆的if-else让人看上去也眼花缭乱,甚至误导别人直接去背代码,另外,核心的逻辑都能展示出来,再去横向的实现其他的类似情况恐怕也不是什么问题了。

在以下的整理中,建议大家先照的核心要点自己写一遍,然后对照下面的代码,复习效果更好。本文的目的就在于以最简洁的代码帮你从第一性原理的角度理解api的内部运作流程,凡是对于我们理解api没有帮助的的边界情况都不做处理。

一、用ES5实现数组的map方法

核心要点:

1.回调函数的参数有哪些,返回值如何处理。

2.不修改原来的数组。

Array.prototype.MyMap = function(fn, context){
 var arr = Array.prototype.slice.call(this);//由于是ES5所以就不用...展开符了
 var mAppedArr = [];
 for (var i = 0; i < arr.length; i++ ){
 mappedArr.push(fn.call(context, arr[i], i, this));
 }
 return mappedArr;
}

二、用ES5实现数组的reduce方法

核心要点:

1、初始值不传怎么处理

2、回调函数的参数有哪些,返回值如何处理。

Array.prototype.myReduce = function(fn, initialValue) {
 var arr = Array.prototype.slice.call(this);
 var res, startIndex;
 res = initialValue ? initialValue : arr[0];
 startIndex = initialValue ? 0 : 1;
 for(var i = startIndex; i < arr.length; i++) {
 res = fn.call(null, res, arr[i], i, this);
 }
 return res;
}

三、实现call/apply

思路: 利用this的上下文特性。

//实现apply只要把下一行中的...args换成args即可
Function.prototype.myCall = function(context = window, ...args) {
 let func = this;
 let fn = Symbol("fn");
 context[fn] = func;
 let res = context[fn](...args "fn");//重点代码,利用this指向,相当于context.caller(...args)
 delete context[fn];
 return res;
}

四、实现Object.create方法(常用)

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

五、实现bind方法

核心要点:

1.对于普通函数,绑定this指向

2.对于构造函数,要保证原函数的原型对象上的属性不能丢失

Function.prototype.bind = function(context, ...args) {
 let self = this;//谨记this表示调用bind的函数
 let fBound = function() {
 //this instanceof fBound为true表示构造函数的情况。如new func.bind(obj)
 return self.apply(this instanceof fBound ? this : context || window, args);
 }
 fBound.prototype = Object.create(this.prototype);//保证原函数的原型对象上的属性不丢失
 return fBound;
}

大家平时说的手写bind,其实就这么简单:)

六、实现new关键字

核心要点:

  1. 创建一个全新的对象,这个对象的__proto__要指向构造函数的原型对象执行构造函数返回值为object类型则作为new方法的返回值返回,否则返回上述全新对象
function myNew(fn, ...args) {
 let instance = Object.create(fn.prototype);
 let res = fn.apply(instance, args);
 return typeof res === 'object' ? res: instance;
}

七、实现instanceof的作用

核心要点:原型链的向上查找。

function myInstanceof(left, right) {
 let proto = Object.getPrototypeOf(left);
 while(true) {
 if(proto == null) return false;
 if(proto == right.prototype) return true;
 proto = Object.getPrototypeof(proto);
 }
}

八、实现单例模式

核心要点: 用闭包和Proxy属性拦截

function proxy(func) {
 let instance;
 let handler = {
 constructor(target, args) {
 if(!instance) {
 instance = Reflect.constructor(fun, args);
 }
 return instance;
 }
 }
 return new Proxy(func, handler);
}

九、实现数组的flat

方式其实很多,之前我做过系统整理,有六种方法,请参考:

JS数组扁平化(flat)方法总结[1]

十、实现防抖功能

核心要点:

如果在定时器的时间范围内再次触发,则重新计时。

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

十一、实现节流功能

核心要点:

如果在定时器的时间范围内再次触发,则不予理睬,等当前定时器完成,才能启动下一个定时器。

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

十二、实现深拷贝

以下为简易版深拷贝,没有考虑循环引用的情况和Buffer、Promise、Set、Map的处理,如果一一实现,过于复杂,面试短时间写出来不太现实,如果有兴趣可以去这里深入实现:

深拷贝终极探索[2]。

const clone = parent => {
 // 判断类型
 const isType = (target, type) => `[object ${type}]` === Object.prototype.toString.call(target)
 // 处理正则
 const getRegExp = re => {
 let flags = "";
 if (re.global) flags += "g";
 if (re.ignoreCase) flags += "i";
 if (re.multiline) flags += "m";
 return flags;
 };
 const _clone = parent => {
 if (parent === null) return null;
 if (typeof parent !== "object") return parent;
 let child, proto;
 if (isType(parent, "Array")) {
 // 对数组做特殊处理
 child = [];
 } else if (isType(parent, "RegExp")) {
 // 对正则对象做特殊处理
 child = new RegExp(parent.source, getRegExp(parent));
 if (parent.lastIndex) child.lastIndex = parent.lastIndex;
 } else if (isType(parent, "Date")) {
 // 对Date对象做特殊处理
 child = new Date(parent.getTime());
 } else {
 // 处理对象原型
 proto = Object.getPrototypeOf(parent);
 // 利用Object.create切断原型链
 child = Object.create(proto);
 }
 for (let i in parent) {
 // 递归
 child[i] = _clone(parent[i]);
 }
 return child;
 };
 return _clone(parent);
};


Tags:API   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
近日只是为了想尽办法为 Flask 实现 Swagger UI 文档功能,基本上要让 Flask 配合 Flasgger, 所以写了篇 Flask 应用集成 Swagger UI 。然而不断的 Google 过程中偶然间发现了...【详细内容】
2021-12-23  Tags: API  点击:(6)  评论:(0)  加入收藏
一个项目的大部分API,测试用例在参数和参数值等信息会有很多相似的地方。我们可以复制API,复制用例来快速生成,然后做细微调整既可以满足我们的测试需求1.复制API:在菜单发布单...【详细内容】
2021-12-14  Tags: API  点击:(20)  评论:(0)  加入收藏
10月18号, W3C中网络平台孵化器小组(Web Platform Incubator Community Group)公布了HTML Sanitizer API的规范草案。这份草案用来解决浏览器如何解决XSS攻击问题。 网络安全中...【详细内容】
2021-12-07  Tags: API  点击:(20)  评论:(0)  加入收藏
当我们通过kubectl来查看、修改Kubernetes资源时,有没有想过后面的接口到底是怎样的?有没有办法探查这些交互数据呢?Kuberenetes客户端和服务端交互的接口,是基于http协议的。所...【详细内容】
2021-11-23  Tags: API  点击:(29)  评论:(0)  加入收藏
前言客户端请求API,通常需要通过返回码来判断API返回的结果是否符合预期,以及该如何处理返回的内容等。相信很多同学都吃过返回码定义混乱的亏,有的API用返回码是int类型,有的是...【详细内容】
2021-10-28  Tags: API  点击:(52)  评论:(0)  加入收藏
凭借着平缓的学习曲线和简单直接的语法,Python在全球范围内的受欢迎程度,正在呈指数级增长。该编码语言往往可以被用于Web开发、软件开发、数学计算、系统脚本、以及几乎所有...【详细内容】
2021-09-22  Tags: API  点击:(48)  评论:(0)  加入收藏
Guava提供的RateLimiter可以限制物理或逻辑资源的被访问速率,咋一听有点像java并发包下的Samephore,但是又不相同,RateLimiter控制的是速率,Samephore控制的是并发量。RateLimit...【详细内容】
2021-09-17  Tags: API  点击:(72)  评论:(0)  加入收藏
前言前后端分离开发模式中,api文档是最好的沟通方式。今天就来说一说如何整合Swagger生成一套漂亮、美观、实用的接口文档。 源码传送门: https://gitee.com/huoqstudy/xiliu-...【详细内容】
2021-09-08  Tags: API  点击:(65)  评论:(0)  加入收藏
注:商业级功能效果演示,非开源,无源码。研发基础在之前AJAX请求数据加密效果之上,更进一步,对返回数据加密。之前是单纯用于登录场景。更广泛的场景是所有此类AJAX WEB API接口。...【详细内容】
2021-09-03  Tags: API  点击:(75)  评论:(0)  加入收藏
最近一连串的 API 安全事件(Peloton、Experian、Clubhouse 等)无疑迫使许多安全和开发团队仔细检查他们的 API 安全状况,以确保它们不会成为下一个被攻击对象。创建面向外部受...【详细内容】
2021-09-01  Tags: API  点击:(59)  评论:(0)  加入收藏
▌简易百科推荐
1、通过条件判断给变量赋值布尔值的正确姿势// badif (a === &#39;a&#39;) { b = true} else { b = false}// goodb = a === &#39;a&#39;2、在if中判断数组长度不为零...【详细内容】
2021-12-24  Mason程    Tags:JavaScript   点击:(6)  评论:(0)  加入收藏
给新手朋友分享我收藏的前端必备javascript已经写好的封装好的方法函数,直接可用。方法函数总计:41个;以下给大家介绍有35个,需要整体文档的朋友私信我,1、输入一个值,将其返回数...【详细内容】
2021-12-15  未来讲IT    Tags:JavaScript   点击:(20)  评论:(0)  加入收藏
1. 检测一个对象是不是纯对象,检测数据类型// 检测数据类型的方法封装(function () { var getProto = Object.getPrototypeOf; // 获取实列的原型对象。 var class2type =...【详细内容】
2021-12-08  前端明明    Tags:js   点击:(23)  评论:(0)  加入收藏
作者:一川来源:前端万有引力 1 写在前面Javascript中的apply、call、bind方法是前端代码开发中相当重要的概念,并且与this的指向密切相关。本篇文章我们将深入探讨这个关键词的...【详细内容】
2021-12-06  Nodejs开发    Tags:Javascript   点击:(19)  评论:(0)  加入收藏
概述DOM全称Document Object Model,即文档对象模型。是HTML和XML文档的编程接口,DOM将文档(HTML或XML)描绘成一个多节点构成的结构。使用JavaScript可以改变文档的结构、样式和...【详细内容】
2021-11-16  海人为记    Tags:DOM模型   点击:(35)  评论:(0)  加入收藏
入口函数 /*js加载完成事件*/ window.onload=function(){ console.log("页面和资源完全加载完毕"); } /*jQuery的ready函数*/ $(document).ready(function(){ co...【详细内容】
2021-11-12  codercyh的开发日记    Tags:jQuery   点击:(36)  评论:(0)  加入收藏
一、判断是否IE浏览器(支持判断IE11与edge)function IEVersion() {var userAgent = navigator.userAgent; //取得浏览器的userAgent字符串var isIE = userAgent.indexOf("comp...【详细内容】
2021-11-02  V面包V    Tags:Javascript   点击:(40)  评论:(0)  加入收藏
Null、Undefined、空检查普通写法: if (username1 !== null || username1 !== undefined || username1 !== &#39;&#39;) { let username = username1; }优化后...【详细内容】
2021-10-28  前端掘金    Tags:JavaScript   点击:(51)  评论:(0)  加入收藏
今天我们将尝试下花 1 分钟的时间简单地了解下什么是 JS 代理对象(proxies)?我们可以这样理解,JS 代理就相当于在对象的外层加了一层拦截,在拦截方法里我们可以自定义一些个性化...【详细内容】
2021-10-18  前端达人    Tags:JS   点击:(51)  评论:(0)  加入收藏
带有多个条件的 if 语句把多个值放在一个数组中,然后调用数组的 includes 方法。// bad if (x === "abc" || x === "def" || x === "ghi" || x === "jkl") { //logic } // be...【详细内容】
2021-09-27  羲和时代    Tags:JS   点击:(58)  评论:(0)  加入收藏
最新更新
栏目热门
栏目头条