1、浅拷贝、深拷贝的实现
浅拷贝
1. // 1. ...实现 2. let copy1 = {...{x:1}} 3. 4. // 2. Object.assign实现 5. let copy2 = Object.assign({}, {x:1})
深拷贝
javascript深拷贝和浅拷贝以及实现方法(推荐)_纸飞机博客-CSDN博客_js浅拷贝和深拷贝的区别
深拷贝和浅拷贝的区别?浅拷贝: 将原对象或原数组的引用直接赋给新对象,新数组,新对象/数组只是原对象的一个引用。深拷贝: 创建一个新的对象和数组,将原对象的各项属性的“值”(数组的所有元素)拷贝过来,是“值”而不是“引用”。为什么要用深拷贝?我们希望在改变新的数组(对象)的时候,不改变原数组(对象)一般是针对Array和Object类型数据的复制对象深拷贝方法1.JSON的方式实现function deepClone2(obj) { let _obj = JSON.st
https://blog.csdn.net/qq_32442973/article/details/118584594
2、手写防抖节流函数
javascript的防抖和节流深入理解_纸飞机博客-CSDN博客
基本概念函数防抖(debounce):触发高频事件后n秒内函数只会执行一次,如果n秒内高频事件再次被触发,则重新计算时间。函数节流(throttle):高频事件触发,但在n秒内只会执行一次,所以节流会稀释函数的执行频率。函数防抖(debounce)与 函数节流(throttle)都是为了限制函数的执行频次,以优化函数触发频率过高导致的响应速度跟不上触发频率,出现延迟,假死或卡顿的现象。函数防抖(debounce)实现方式:每次触发事件时设置一个延迟调用方法,并且取消之前的延时调用方法
https://blog.csdn.net/qq_32442973/article/details/118739927
3、instanceof (考察对原型链的理解)
instanceof作用:判断一个实例是否是其父类或者祖先类型的实例。
instanceof 在查找的过程中会遍历左边变量的原型链,直到找到右边变量的 prototype查找失败,返回 false。
let myInstanceof = (target,origin) => { while(target) { if(target.__proto__===origin.prototype) { return true } target = target.__proto__ } return false } let a = [1,2,3] console.log(myInstanceof(a,Array)); // true console.log(myInstanceof(a,Object)); // true
4、实现数组的map方法
Array.prototype.newMap = function(fn) { var newArr = []; for(var i = 0; i<this.length; i++){ newArr.push(fn(this[i],i,this)) } return newArr; }
5、实现 new 方法
function createNew() { let obj = {} // 1.创建一个空对象 let constructor = [].shift.call(arguments) // let [constructor,...args] = [...arguments] obj.__proto__ = constructor.prototype // 2.链接到原型 let result = constructor.apply(obj, arguments) // 3.绑定this值,为实例添加方法和属性 // let result = constructor.apply(obj, args) return typeof result === 'object' ? result : obj // 4.返回新对象 } function People(name,age) { this.name = name this.age = age } let peo = createNew(People,'Bob',22) console.log(peo.name) console.log(peo.age)
6、实现call&apply&bind
call
Function.prototype.myCall = function (context = window) { // 函数的方法,所以写在Fuction原型对象上 if (typeof this !== "function") { // 这里if其实没必要,会自动抛出错误 throw new Error("不是函数"); } const obj = context || window; //这里可用ES6方法,为参数添加默认值,js严格模式全局作用域this为undefined obj.fn = this; //this为调用的上下文,this此处为函数,将这个函数作为obj的方法 const arg = [...arguments].slice(1); //第一个为obj所以删除,伪数组转为数组 res = obj.fn(...arg); delete obj.fn; // 不删除会导致context属性越来越多 return res; };
apply(arguments[this, [参数1,参数2.....] ])
Function.prototype.myApply = function (context) { // 箭头函数从不具有参数对象!!!!!这里不能写成箭头函数 let obj = context || window; obj.fn = this; const arg = arguments[1] || []; //若有参数,得到的是数组 let res = obj.fn(...arg); delete obj.fn; return res; }; function f(a, b) { console.log(a, b); console.log(this.name); } let obj = { name: "张三", }; f.myApply(obj, [1, 2]); //arguments[1]
bind
// 思路:类似call,但返回的是函数 Function.prototype.mybind = function (context) { if (typeof this !== 'function') { throw new TypeError('Error') } let _this = this let arg = [...arguments].slice(1) return function F() { // 处理函数使用new的情况 if (this instanceof F) { return new _this(...arg, ...arguments) } else { return _this.apply(context, arg.concat(...arguments)) } } }
更多实现:bind方法的实现
7、手动实现promise
// Promise/A+ 规范规定的三种状态 const STATUS = { PENDING: 'pending', FULFILLED: 'fulfilled', REJECTED: 'rejected' } class MyPromise { // 构造函数接收一个执行回调 constructor(executor) { this._status = STATUS.PENDING // Promise初始状态 this._value = undefined // then回调的值 this._resolveQueue = [] // resolve时触发的成功队列 this._rejectQueue = [] // reject时触发的失败队列 // 使用箭头函数固定this(resolve函数在executor中触发,不然找不到this) const resolve = value => { const run = () => { // Promise/A+ 规范规定的Promise状态只能从pending触发,变成fulfilled if (this._status === STATUS.PENDING) { this._status = STATUS.FULFILLED // 更改状态 this._value = value // 储存当前值,用于then回调 // 执行resolve回调 while (this._resolveQueue.length) { const callback = this._resolveQueue.shift() callback(value) } } } //把resolve执行回调的操作封装成一个函数,放进setTimeout里,以实现promise异步调用的特性(规范上是微任务,这里是宏任务) setTimeout(run) } // 同 resolve const reject = value => { const run = () => { if (this._status === STATUS.PENDING) { this._status = STATUS.REJECTED this._value = value while (this._rejectQueue.length) { const callback = this._rejectQueue.shift() callback(value) } } } setTimeout(run) } // new Promise()时立即执行executor,并传入resolve和reject executor(resolve, reject) } // then方法,接收一个成功的回调和一个失败的回调 function then(onFulfilled, onRejected) { // 根据规范,如果then的参数不是function,则忽略它, 让值继续往下传递,链式调用继续往下执行 typeof onFulfilled !== 'function' ? onFulfilled = value => value : null typeof onRejected !== 'function' ? onRejected = error => error : null // then 返回一个新的promise return new MyPromise((resolve, reject) => { const resolveFn = value => { try { const x = onFulfilled(value) // 分类讨论返回值,如果是Promise,那么等待Promise状态变更,否则直接resolve x instanceof MyPromise ? x.then(resolve, reject) : resolve(x) } catch (error) { reject(error) } } } } const rejectFn = error => { try { const x = onRejected(error) x instanceof MyPromise ? x.then(resolve, reject) : resolve(x) } catch (error) { reject(error) } } switch (this._status) { case STATUS.PENDING: this._resolveQueue.push(resolveFn) this._rejectQueue.push(rejectFn) break; case STATUS.FULFILLED: resolveFn(this._value) break; case STATUS.REJECTED: rejectFn(this._value) break; } }) } catch (rejectFn) { return this.then(undefined, rejectFn) } // promise.finally方法 finally(callback) { return this.then(value => MyPromise.resolve(callback()).then(() => value), error => { MyPromise.resolve(callback()).then(() => error) }) } // 静态resolve方法 static resolve(value) { return value instanceof MyPromise ? value : new MyPromise(resolve => resolve(value)) } // 静态reject方法 static reject(error) { return new MyPromise((resolve, reject) => reject(error)) } // 静态all方法 static all(promiseArr) { let count = 0 let result = [] return new MyPromise((resolve, reject) => { if (!promiseArr.length) { return resolve(result) } promiseArr.forEach((p, i) => { MyPromise.resolve(p).then(value => { count++ result[i] = value if (count === promiseArr.length) { resolve(result) } }, error => { reject(error) }) }) }) } // 静态race方法 static race(promiseArr) { return new MyPromise((resolve, reject) => { promiseArr.forEach(p => { MyPromise.resolve(p).then(value => { resolve(value) }, error => { reject(error) }) }) }) } }