文章目录
题目(大部分转自第一个参考网站)
AJAX
var request = new XMLHttpRequest()
request.open('GET', 'index/a/b/c?name=TianTian', true);
request.onreadystatechange = function () {
if(request.readyState === 4 && request.status === 200) {
console.log(request.responseText);
}};
request.send();
事件委托
function delegate(element, eventType, selector, fn) {
element.addEventListener(eventType, e => {
let el = e.target
while (!el.matches(selector)) {
if (element === el) {
el = null
break
}
el = el.parentNode
}
el && fn.call(el, e, el)
},true)
return element
}
防抖
function debounce(fn, delay) {
let timer = null
return function(...args) {
let context = this
if(timer) clearTimeout(timer)
timer = setTimeout(function(){
fn.apply(context,args)
},delay)
}
}
节流
function throttle(fn, delay) {
let flag = true,
timer = null
return function(...args) {
let context = this
if(!flag) return
flag = false
clearTimeout(timer)
timer = setTimeout(function() {
fn.apply(context,args)
flag = true
},delay)
}
}
数组去重
使用Set
let unique_1 = arr => [...new Set(arr)];
使用filter
function unique_2(array) {
var res = array.filter(function (item, index, array) {
return array.indexOf(item) === index;
})
return res;
}
reduce
let unique_3 = arr => arr.reduce((pre, cur) => pre.includes(cur) ? pre : [...pre, cur], []);
Object 键值对
function unique_4(array) {
var obj = {};
return array.filter(function (item, index, array) {
return obj.hasOwnProperty(typeof item + item) ? false : (obj[typeof item + item] = true)
})
}
数组扁平化
ES6 自带Array.prototype.flat(num)
function flatDeep(arr, d = 1) {
return d > 0 ? arr.reduce((acc, val) => acc.concat(Array.isArray(val) ? flatDeep(val, d - 1) : val),
[]) :
arr.slice();
};
// var arr1 = [1,2,3,[1,2,3,4, [2,3,4]]];
// flatDeep(arr1, Infinity);
call和apply
// 实现call
Function.prototype.mycall = function () {
let [thisArg, ...args] = [...arguments]
thisArg = Object(thisArg) || window
let fn = Symbol()
thisArg[fn] = this
let result = thisArg[fn](...args)
delete thisArg[fn]
return result
}
// 实现apply
Function.prototype.myapply = function () {
let [thisArg, args] = [...arguments];
thisArg = Object(thisArg)
let fn = Symbol()
thisArg[fn] = this;
let result = thisArg[fn](...args);
delete thisArg.fn;
return result;
}
//测试用例
let cc = {
a: 1
}
function demo(x1, x2) {
console.log(typeof this, this.a, this)
console.log(x1, x2)
}
demo.apply(cc, [2, 3])
demo.myapply(cc, [2, 3])
demo.call(cc,33,44)
demo.mycall(cc,33,44)
bind
// 实现bind
Function.prototype.mybind = function(context, ...args){
return (...newArgs) => {
return this.call(context,...args, ...newArgs)
}
}
// 测试用例
let cc = {
name : 'TianTian'
}
function say(something,other){
console.log(`I want to tell ${this.name} ${something}`);
console.log('This is some'+other)
}
let tmp = say.mybind(cc,'happy','you are kute')
let tmp1 = say.bind(cc,'happy','you are kute')
tmp()
tmp1()
深拷贝
function deepClone(obj, map = new WeakMap()) {
if (obj instanceof RegExp) return new RegExp(obj);
if (obj instanceof Date) return new Date(obj);
if (obj == null || typeof obj != 'object') return obj;
if (map.has(obj)) {
return map.get(obj);
}
let t = new obj.constructor();
map.set(obj, t);
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
t[key] = deepClone(obj[key], map);
}
}
return t;
}
//测试用例
let obj = {
a: 1,
b: {
c: 2,
d: 3
},
d: new RegExp(/^\s+|\s$/g)
}
let clone_obj = deepClone(obj)
obj.d = /^\s|[0-9]+$/g
console.log(clone_obj)
console.log(obj)
Object.create
//实现Object.create方法
function create(proto) {
function Fn() {};
Fn.prototype = proto;
Fn.prototype.constructor = Fn;
return new Fn();
}
let demo = {
c : '123'
}
let cc = Object.create(demo)
手写继承
寄生组合式(常用)
function inheritPrototype(subType, superType) {
// 创建对象,创建父类原型的一个副本
var prototype = Object.create(superType.prototype);
// 增强对象,弥补因重写原型而失去的默认的constructor 属性
prototype.constructor = subType;
// 指定对象,将新创建的对象赋值给子类的原型
subType.prototype = prototype;
}
Class实现
class Rectangle {
// constructor
constructor(height, width) {
this.height = height;
this.width = width;
}
// Getter
get area() {
return this.calcArea()
}
// Method
calcArea() {
return this.height * this.width;
}
}
const rectangle = new Rectangle(40, 20);
console.log(rectangle.area);
// 输出 800
// 继承
class Square extends Rectangle {
constructor(len) {
// 子类没有this,必须先调用super
super(len, len);
// 如果子类中存在构造函数,则需要在使用“this”之前首先调用 super()。
this.name = 'SquareIng';
}
get area() {
return this.height * this.width;
}
}
const square = new Square(20);
console.log(square.area);
// 输出 400
Promise源码
const PENDING = 'PENDING'; // 进行中
const FULFILLED = 'FULFILLED'; // 已成功
const REJECTED = 'REJECTED'; // 已失败
class Promise {
constructor(exector) { // 初始化状态
this.status = PENDING;
// 将成功、失败结果放在this上,便于then、catch访问
this.value = undefined; this.reason = undefined; // 成功态回调函数队列
this.onFulfilledCallbacks = []; // 失败态回调函数队列
this.onRejectedCallbacks = [];
const resolve = value => { // 只有进行中状态才能更改状态
if (this.status === PENDING) {
this.status = FULFILLED;
this.value = value; // 成功态函数依次执行
this.onFulfilledCallbacks.forEach(fn => fn(this.value));
}
}
const reject = reason => { // 只有进行中状态才能更改状态
if (this.status === PENDING) {
this.status = REJECTED;
this.reason = reason; // 失败态函数依次执行
this.onRejectedCallbacks.forEach(fn => fn(this.reason))
}
}
try {
// 立即执行executor
// 把内部的resolve和reject传入executor,用户可调用resolve和reject
exector(resolve, reject);
} catch (e) {
// executor执行出错,将错误内容reject抛出去
reject(e);
}
} then(onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
onRejected = typeof onRejected === 'function' ? onRejected :
reason => { throw new Error(reason instanceof Error ? reason.message : reason) } // 保存this
const self = this; return new Promise((resolve, reject) => {
if (self.status === PENDING) {
self.onFulfilledCallbacks.push(() => {
// try捕获错误
try {
// 模拟微任务
setTimeout(() => {
const result = onFulfilled(self.value);
// 分两种情况:
// 1. 回调函数返回值是Promise,执行then操作
// 2. 如果不是Promise,调用新Promise的resolve函数
result instanceof Promise ? result.then(resolve, reject) : resolve(result);
})
} catch (e) { reject(e); }
});
self.onRejectedCallbacks.push(() => {
// 以下同理
try {
setTimeout(() => {
const result = onRejected(self.reason);
// 不同点:此时是reject
result instanceof Promise ? result.then(resolve, reject) : reject(result);
})
} catch (e) { reject(e); }
})
} else if (self.status === FULFILLED) {
try {
setTimeout(() => {
const result = onFulfilled(self.value); result instanceof Promise ? result.then(resolve, reject) : resolve(result);
});
} catch (e) { reject(e); }
} else if (self.status === REJECTED) {
try {
setTimeout(() => {
const result = onRejected(self.reason); result instanceof Promise ? result.then(resolve, reject) : reject(result);
})
} catch (e) { reject(e); }
}
});
} catch(onRejected) {
return this.then(null, onRejected);
} static resolve(value) {
if (value instanceof Promise) {
// 如果是Promise实例,直接返回
return value;
} else {
// 如果不是Promise实例,返回一个新的Promise对象,状态为FULFILLED
return new Promise((resolve, reject) => resolve(value));
}
} static reject(reason) {
return new Promise((resolve, reject) => {
reject(reason);
})
}
}
Promise.all 及 race
// 实现Promise.all 以及 race
Promise.myall = function (arr) {
return new Promise((resolve, reject) => {
if (arr.length === 0) {
return resolve([])
} else {
let res = [],
count = 0
for (let i = 0; i < arr.length; i++) {
// 同时也能处理arr数组中非Promise对象
if (!(arr[i] instanceof Promise)) {
res[i] = arr[i]
if (++count === arr.length)
resolve(res)
} else {
arr[i].then(data => {
res[i] = data
if (++count === arr.length)
resolve(res)
}, err => {
reject(err)
})
}
}
}
})
}
Promise.myrace = function (arr) {
return new Promise((resolve, reject) => {
for (let i = 0; i < arr.length; i++) {
// 同时也能处理arr数组中非Promise对象
if (!(arr[i] instanceof Promise)) {
Promise.resolve(arr[i]).then(resolve, reject)
} else {
arr[i].then(resolve, reject)
}
}
})
}
参考网站
送你21道精选高频JavaScript手写面试题
32个手写JS,巩固你的JS基础
12道高频 JavaScript 手写面试题及答案