2021年前端各大公司都考了那些手写题(附带代码)

function indexOf(findVal, beginIndex = 0) {

if (this.length < 1 || beginIndex > findVal.length) {

return -1;

}

if (!findVal) {

return 0;

}

beginIndex = beginIndex <= 0 ? 0 : beginIndex;

for (let i = beginIndex; i < this.length; i++) {

if (this[i] == findVal) return i;

}

return -1;

}

实现sort

参考代码[4]

🌊 防抖节流[前端开发博客](()


实现防抖函数debounce

考察频率: (⭐⭐⭐⭐⭐)

function debounce(func, wait, immediate) {

var timeout, result;

var debounced = function () {

var context = this;

var args = arguments;

if (timeout) clearTimeout(timeout);

if (immediate) {

// 如果已经执行过,不再执行

var callNow = !timeout;

timeout = setTimeout(function(){

timeout = null;

}, wait)

if (callNow) result = func.apply(context, args)

}

else {

timeout = setTimeout(function(){

result = func.apply(context, args)

}, wait);

}

return result;

};

debounced.cancel = function() {

clearTimeout(timeout);

timeout = null;

};

return debounced;

}

实现节流函数throttle

考察频率: (⭐⭐⭐⭐⭐)

// 第四版

function throttle(func, wait, options) {

var timeout, context, args, result;

var previous = 0;

if (!options) options = {};

var later = function() {

previous = options.leading === false ? 0 : new Date().getTime();

timeout = null;

func.apply(context, args);

if (!timeout) context = args = null;

};

var throttled = function() {

var now = new Date().getTime();

if (!previous && options.leading === false) previous = now;

var remaining = wait - (now - previous);

context = this;

args = arguments;

if (remaining <= 0 || remaining > wait) {

if (timeout) {

clearTimeout(timeout);

timeout = null;

}

previous = now;

func.apply(context, args);

if (!timeout) context = args = null;

} else if (!timeout && options.trailing !== false) {

timeout = setTimeout(later, remaining);

}

};

return throttled;

}

⛲ Object篇


能不能写一个完整的深拷贝

考察频率: (⭐⭐⭐⭐⭐)

const getType = obj => Object.prototype.toString.call(obj);

const isObject = (target) => (typeof target === ‘object’ || typeof target === ‘function’) && target !== null;

const canTraverse = {

《大厂前端面试题解析+Web核心总结学习笔记+企业项目实战源码+最新高清讲解视频》无偿开源 徽信搜索公众号【编程进阶路】 ‘[object Map]’: true,

‘[object Set]’: true,

‘[object Array]’: true,

‘[object Object]’: true,

‘[object Arguments]’: true,

};

const mapTag = ‘[object Map]’;

const setTag = ‘[object Set]’;

const boolTag = ‘[object Boolean]’;

const numberTag = ‘[object Number]’;

const stringTag = ‘[object String]’;

const symbolTag = ‘[object Symbol]’;

const dateTag = ‘[object Date]’;

const errorTag = ‘[object Error]’;

const regexpTag = ‘[object RegExp]’;

const funcTag = ‘[object Function]’;

const handleRegExp = (target) => {

const { source, flags } = target;

return new target.constructor(source, flags);

}

const handleFunc = (func) => {

// 箭头函数直接返回自身

if(!func.prototype) return func;

const bodyReg = /(?<={)(.|\n)+(?=})/m;

const paramReg = /(?<=().+(?=)\s+{)/;

const funcString = func.toString();

// 分别匹配 函数参数 和 函数体

const param = paramReg.exec(funcString);

const body = bodyReg.exec(funcString);

if(!body) return null;

if (param) {

const paramArr = param[0].split(‘,’);

return new Function(…paramArr, body[0]);

} else {

return new Function(body[0]);

}

}

const handleNotTraverse = (target, tag) => {

const Ctor = target.constructor;

switch(tag) {

case boolTag:

return new Object(Boolean.prototype.valueOf.call(target));

case numberTag:

return new Object(Number.prototype.valueOf.call(target));

case stringTag:

return new Object(String.prototype.valueOf.call(target));

case symbolTag:

return new Object(Symbol.prototype.valueOf.call(target));

case errorTag:

case dateTag:

return new Ctor(target);

case regexpTag:

return handleRegExp(target);

case funcTag:

return handleFunc(target);

default:

return new Ctor(target);

}

}

const deepClone = (target, map = new WeakMap()) => {

if(!isObject(target))

return target;

let type = getType(target);

let cloneTarget;

if(!canTraverse[type]) {

// 处理不能遍历的对象

return handleNotTraverse(target, type);

}else {

// 这波操作相当关键,可以保证对象的原型不丢失!

let ctor = target.constructor;

cloneTarget = new ctor();

}

if(map.get(target))

return target;

map.set(target, true);

if(type === mapTag) {

//处理Map

target.forEach((item, key) => {

cloneTarget.set(deepClone(key, map), deepClone(item, map));

})

}

if(type === setTag) {

//处理Set

target.forEach(item => {

cloneTarget.add(deepClone(item, map));

})

}

// 处理数组和对象

for (let prop in target) {

if (target.hasOwnProperty(prop)) {

cloneTarget[prop] = deepClone(target[prop], map);

}

}

return cloneTarget;

}

参考博客[5]

实现new

考察频率: (⭐⭐⭐⭐)

function createObject(Con) {

// 创建新对象obj

// var obj = {};也可以

var obj = Object.create(null);

// 将obj.proto -> 构造函数原型

// (不推荐)obj.proto = Con.prototype

Object.setPrototypeOf(obj, Con.prototype);

// 执行构造函数,并接受构造函数返回值

const ret = Con.apply(obj, [].slice.call(arguments, 1));

// 若构造函数返回值为对象,直接返回该对象

// 否则返回obj

return typeof(ret) === ‘object’ ? ret: obj;

}

继承

考察频率: (⭐⭐⭐⭐)

原型链继承
借用构造函数(经典继承)
组合继承
原型式继承
寄生式继承
寄生组合式继承
Class实现继承(补充一下)

class Animal {

constructor(name) {

this.name = name

}

getName() {

return this.name

}

}

class Dog extends Animal {

constructor(name, age) {

super(name)

this.age = age

}

}

参考代码[6]

实现object.create

function newCreate(proto, propertiesObject) {

if (typeof proto !== ‘object’ && typeof proto !== ‘function’) {

throw TypeError('Object prototype may only be an Object: ’ + proto)

}

function F() { }

F.prototype = proto

const o = new F()

if (propertiesObject !== undefined) {

Object.keys(propertiesObject).forEach(prop => {

let desc = propertiesObject[prop]

if (typeof desc !== ‘object’ || desc === null) {

throw TypeError('Object prorotype may only be an Object: ’ + desc)

} else {

Object.defineProperty(o, prop, desc)

}

})

}

return o

}

🚂 Function篇


call

考察频率: (⭐⭐⭐⭐)

Function.prototype.myCall = function (thisArg) {

thisArg = thisArg || window;

thisArg.func = this;

const args = []

for (let i = 1; i<arguments.length; i++) {

args.push(‘arguments[’+ i + ‘]’)

}

const result = eval(‘thisArg.func(’ + args +‘)’)

delete thisArg.func;

return result;

}

bind

考察频率: (⭐⭐⭐⭐)

Function.prototype.sx_bind = function (obj, …args) {

obj = obj || window

const fn = Symbol()

obj[fn] = this

const _this = this

const res = function (…innerArgs) {

console.log(this, _this)

if (this instanceof _this) {

this[fn] = _this

thisfn

delete this[fn]

} else {

objfn

delete obj[fn]

}

}

res.prototype = Object.create(this.prototype)

return res

}

apply

考察频率: (⭐⭐⭐⭐)

Function.prototype.myApply = function (thisArg, arr) {

thisArg = thisArg || window;

thisArg.func = this;

const args = []

for (let i = 0; i<arr.length; i++) {

args.push(‘arr[’+ i + ‘]’)

}

const result = eval(‘thisArg.func(’ + args +‘)’)

delete thisArg.func;

return result;

}

实现柯里化

考察频率: (⭐⭐⭐)

参考代码[7]

实现链式调用

参考代码[8]

偏函数

参考代码[9]

🌍 ajax 与 jsonp


考察频率: (⭐⭐⭐)

实现ajax

function ajax({

url= null,

method = ‘GET’,

dataType = ‘JSON’,

async = true}){

return new Promise((resolve, reject) => {

let xhr = new XMLHttpRequest()

xhr.open(method, url, async)

xhr.responseType = dataType

xhr.onreadystatechange = () => {

if(!/1\d{2}$/.test(xhr.status)) return;

if(xhr.readyState === 4) {

let result = xhr.responseText

resolve(result)

}

}

xhr.onerror = (err) => {

reject(err)

}

xhr.send()

})

}

实现jsonp

const jsonp = ({ url, params, callbackName }) => {

const generateUrl = () => {

let dataSrc = ‘’

for (let key in params) {

if (params.hasOwnProperty(key)) {

dataSrc += ${key}=${params[key]}&

}

}

dataSrc += callback=${callbackName}

return ${url}?${dataSrc}

}

return new Promise((resolve, reject) => {

const scriptEle = document.createElement(‘script’)

scriptEle.src = generateUrl()

document.body.appendChild(scriptEle)

window[callbackName] = data => {

resolve(data)

document.removeChild(scriptEle)

}

})

}

🛫 ES6篇


实现set

class Set {

constructor() {

this.items = {};

this.size = 0;

}

has(element) {

return element in this.items;

}

add(element) {

if(! this.has(element)) {

this.items[element] = element;

this.size++;

}

return this;

}

delete(element) {

if (this.has(element)) {

delete this.items[element];

this.size–;

}

return this;

}

clear() {

this.items = {}

this.size = 0;

}

values() {

let values = [];

for(let key in this.items) {

if(this.items.hasOwnProperty(key)) {

values.push(key);

}

}

return values;

}

}

实现 map

function defaultToString(key) {

if(key === null) {

return ‘NULL’;

} else if (key === undefined) {

return ‘UNDEFINED’

} else if (Object.prototype.toString.call(key) === ‘[object Object]’ || Object.prototype.toString.call(key) === ‘[object Array]’) {

return JSON.stringify(key);

}

return key.toString();

}

class Map {

constructor() {

this.items = {};

this.size = 0;

}

set(key, value) {

if(!this.has(key)) {

this.items[defaultToString(key)] = value;

this.size++;

}

return this;

}

get(key) {

return this.items[defaultToString(key)];

}

has(key) {

return this.items[defaultToString(key)] !== undefined;

}

delete(key) {

if (this.has(key)) {

delete this.items[key];

this.size–;

}

return this;

}

clear() {

this.items = {}

this.size = 0;

}

keys() {

let keys = [];

for(let key in this.items) {

if(this.has(key)) {

keys.push(key)

}

}

return keys;

}

values() {

let values = [];

for(let key in this.items) {

if(this.has(key)) {

values.push(this.items[key]);

}

}

return values;

}

}

实现es6的class

参考代码[10]

🦉 其他


instanceof

考察频率: (⭐⭐⭐⭐)

function instance_of(Case, Constructor) {

// 基本数据类型返回false

// 兼容一下函数对象

if ((typeof(Case) != ‘object’ && typeof(Case) != ‘function’) || Case == ‘null’) return false;

let CaseProto = Object.getPrototypeOf(Case);

while (true) {

// 查到原型链顶端,仍未查到,返回false

if (CaseProto == null) return false;

// 找到相同的原型

if (CaseProto === Constructor.prototype) return true;

CaseProto = Object.getPrototypeOf(CaseProto);

}

}

实现千分位分隔符

考察频率: (⭐⭐⭐)

var str = “100000000000”,

reg = /(?=(\B\d{3})+$)/g;

str.replace(reg, “,”)

把一个JSON对象的key从下划线形式(Pascal)转换到小驼峰形式(Camel)

考察频率: (⭐⭐⭐)

参考代码[11]

实现数据类型判断函数

function myTypeof(obj) {

return Object.prototype.toString.call(obj).slice(8, -1).toLowerCase()

}

实现数组转树

参考代码[12]

实现sleep函数

// promise

const sleep = time => {

return new Promise(resolve => setTimeout(resolve,time))

}

sleep(1000).then(()=>{

console.log(1)

})

// ES5

function sleep(callback,time) {

if(typeof callback === ‘function’)

setTimeout(callback,time)

}

function output(){

console.log(1);

}

sleep(output,1000);

实现发布订阅模式

class EventEmitter {

constructor() {

this.cache = {}

}

on(name, fn) {

if (this.cache[name]) {

this.cache[name].push(fn)

} else {

this.cache[name] = [fn]

}

}

off(name, fn) {

let tasks = this.cache[name]

if (tasks) {

const index = tasks.findIndex(f => f === fn || f.callback === fn)

if (index >= 0) {

tasks.splice(index, 1)

}

}

}

emit(name, once = false, …args) {

if (this.cache[name]) {

// 创建副本,如果回调函数内继续注册相同事件,会造成死循环

let tasks = this.cache[name].slice()

for (let fn of tasks) {

fn(…args)

}

if (once) {

delete this.cache[name]

}

}

}

}

🛕 更多题目 [前端开发博客](()


传送门: 前端题目[13]

如果感觉有帮助的话,别忘了给小包点个 ⭐ 。

💘 往期精彩文章


  • 牛客最新前端JS笔试百题[14]

  • 牛客最新前端面经面试题汇总(含解析)[15]

  • 抓取牛客最新前端面试题五百道 数据分析JS面试热点[16]

  • 给VSCode和网站领养喵咪 一起快乐撸猫[17]

  • 原生JavaScript灵魂拷问(一),你能答上多少?[18]

  • JavaScript之彻底理解原型与原型链[19]

  • JavaScript之彻底理解EventLoop[20]

  • 《2w字大章 38道面试题》彻底理清JS中this指向问题[21]

💥 后语



  1. 23 ↩︎

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值