alert 输入的是字符串
一、手写call&bind
~function anonymous(proto){ function bind(context = window, ...args){ return (...amArgs) => { this.apply(context, args.conact(amArgs)); } } function call (context, ...args){ context === null ? context = window : null; let type = typeof context; if(type !== 'object' && type !== 'function' && type !== 'symbol' ){ switch(type){ case "number": context = new Number(context); break; case 'string': context = new String(context); break; case 'boolean': context = new Boolean(context); break; } } context.$fn = this; let result = context.$fn(...args) delete context.$fn; return result; } proto.call = call proto.bind = bind}(Function.prototype)
二、节流防抖
节流: 多少秒再执行,如果没到执行工夫内持续点击,则从新计算执行工夫 利用: input输入
function debounce(fn, delay){ let timer = null; return function (){ if(timer){ clearTimeout(timer) } timer = setTimeout(() => { fn.call(this, ...arguments) timer = null; }, delay) } } // 示例: handleChange = (e) => { this.value = e.target.value; } Input.onChange = debounce(handleChange, 500); Input.onChange = function(){ if(timer){ clearTimeout(timer); } timer = setTimeout(() => { handleChange.call(this, ...arguments) }, 500) }
防抖: 设置两秒距离点击一次,无论你点击多少次,都是两秒之后执行 利用: resize,scroll
1、工夫戳
function throttle(fn, interval){ // 此时立刻执行 let last = new Date().getTime(); return function(){ let now = new Date().getTime(); if(now - last > interval){ last = now; fn.apply(this, [...arguments]) } }}
2、定时器
function throttle(fn, interval){ let timer = null return function(){ if(!timer ){ timer = setTimeout(() => { fn.apply(this, [arguments]) clearTimeout(timer) }, interval) } }}
3、工夫戳和定时器联合形式
function throttle(fn, delay){ // 节流 10 let timer = null; let startTime = new Date().getTime(); 30 return function (){ let curTime = new Date().getTime(); let remaining = delay - (curTime - startTime); let context = this; let args = arguments; clearTimeout(timer); if(remaining <= 0){ fn.apply(context, args); startTime = curTime; } else { timer = setTimeout(fn, remaining); } } }
三、实现一个new
function self_new(Func, ...args){ // 默认创立一个实例对象(而且是属于以后这个类的一个实例) let obj = {}; obj.__proto__ == Func.prototype; // IE 大部分浏览中不容许咱们间接操作__proto__; // let obj = Object.create(Dog.prototype); 等价于下面两行 let result = Func.call(obj, ...args); if((typeof result === 'object' && result !== null) || ( typeof result === 'function') ){ return result } return obj; // 也会把类当做一般函数执行 // 执行的时候要保障this指向创立的实例}
四、继承的四种形式
1、原型继承
function A () { this.x = 100; } A.prototype.getX = function getX () { console.log(this.x) } function B (){ this.y = 200; } // 原型继承 B.prototype = new A() B.prototype.getY = function getY(){ console.log(this.y); } let b = new B; // 特点: 并不会把父类的办法克隆给子类,而是建设了子类和父类的原型链查找机制 // 重定向子类的原型后,默认会失落原有的constructor属性, // 任何一个子类能够批改父类上的属性办法, // 父类的公有属性办法变成子类的私有属性
2、call继承
function A (){ this.x = 100; } A.prototype.getX = function getX(){ console.log(this.x) } // 把父类当做一般函数执行,让其执行的时候,办法中的this变为子类的实例即可 function B(){ A.call(B); this.y = 200; } B.prototype.getY = function getY(){ console.log(this.y) } let b = new B; // 只能继承父类的公有属性,继承的公有属性赋值给子类实例的公有属性 // 父类的原型办法无奈被继承
3、寄生组合继承(perfect)
// call继承实现公有属性继承 // 原型继承实现私有属性继承 function A (){ this.x = 100; } A.prototype.getX = function getX(){ console.log(this.x) } // 把父类当做一般函数执行,让其执行的时候,办法中的this变为子类的实例即可 function B(){ A.call(B); this.y = 200; } // Object.create :创立一个空对象,让其__proto__ 指向A.prototype B.prototype = Object.create(A.prototype); B.prototype.constructor = B.prototype.getY = function getY(){ console.log(this.y) } let b = new B;
4、class继承
class A { constructor(){ this.x = 100; } // 设置A.prototype上的办法 num = 1000; // 把A当做一般对象设置的属性和办法 static n = 2000; static getH () { console.log('123123') } getX(){ console.log(this.x) } } class B extends A{ constructor(){ super(); this.y = 300; } getY(){ console.log(this.y); } }
五、深拷贝
JOSN.parse(JSON.stringify(obj))缺点: 本义之后,正则 => {} 函数 => null
function deepClone(obj){ if(obj === null) return null; // 如果是根本数据值或者函数,也能够间接返回即可(函数无须要克隆) if(typeof obj !== 'object') return obj; // 如果是正则 if(Object.toString.call(obj) === '[Object RegExp]') return new RegExp(obj); // 如果是日期格局 if(Object.toString.call(obj) === '[Object Date]') return new Date(obj); // obj.constructor:找到所属类原型上的constructor,而原型上的constructor指向的事以后类的自身 ==> 保障传递进来什么类型的值,咱们最初创立的newObj也是对应类型 let newObj = new obj.constructor; for(let key in obj){ if(!obj.hasOwnProperty(key)) break; newObj[key] = deepClone(obj[key]) } return newObj;}
六、实现promise
class MyPromise{ constructor(executor){ // 每一个promise实例都有一个状态和后果属性 this.PromiseStatus = 'pending'; this.PromiseValue = undefined; this.resoveFnArr = []; this.rejectFnArr = [] // 定义resolve/reject办法用来扭转promise实例的状态和后果 let change = (status, value) => { if(this.PromiseStatus !== 'pending') return; this.PromiseValue = value; this.PromiseStatus = status; let fnArr = status === 'resolved'? this.resoveFnArr: this.rejectFnArr; fnArr.forEach(item => { if(typeof item !== 'function'){ return } item(this.PromiseValue); }) } let resolve = result => { if(this.resoveFnArr.length){ change('resolved', result) return } let delayTimer = setTimeout(() => { change('resolved', result) clearTimeout(delayTimer) }, 0) } let reject = resason => { if(this.resoveFnArr.length){ change('rejected', resason) return } let delayTimer = setTimeout(() => { change('resolved', result) clearTimeout(delayTimer) }, 0) } // 每一次new Promise 都会执行executor函数 try{ executor(resolve, reject); } catch(err){ reject(err); } } then(resolveFn, rejectFn){ // 每一次执行then都会返回一个新的promise实例 // this.resoveFnArr.push(resolveFn); // this.rejectFnArr.push(rejectFn); // 如果传递的参数不是函数(null/或者不传递),咱们让胜利或者失败传递顺延 if(typeof resoveFn !== 'function'){ resolveFn = (result) => { return result; } } if(typeof rejectFn !== 'function'){ rejectFn = (reason) => { return MyPromise.reject(reason); } } return new MyPromise((resolve, reject) => { // 执行resolve/reject决定新的实例是胜利还是失败的 // 只有执行新实例的executor函数中的resolve/reject就晓得新的实例是胜利的还是失败的 this.resoveFnArr.push((result) => { try{ //不报错,则承受办法的返回后果,会依据后果判断胜利还是失败 let x = resolveFn(result); console.log('设置then执行的数据', x , x instanceof MyPromise) if(x instanceof MyPromise){ x.then(resolve, reject); return } resolve(x); } catch(err){ // 执行报错代表新实例是失败的 reject(err) } }); this.rejectFnArr.push((reason) => { try{ // 不报错,则承受办法的返回后果,会依据后果判断胜利还是失败 let x = rejectFn(reason); if(x instanceof MyPromise){ x.then(resolve, reject); return } resolve(x); }catch(err){ // 执行报错代表新实例是失败的 reject(err) } }); }) } // MyPromise.prototype.catch(fn) === MyPromise.prototye.then(null, fn) catch(rejectFn){ return this.then(null, rejectFn); } // 静态方法 static resolve(result){ return new MyPromise((resolve, reject) => { resolve(result); }) } static reject(reason){ return new MyPromise((resolve, reject)=> { reject(reason); }) } static all(arr){ return new MyPromise((resolve,reject) => { let index = 0; let results = []; for(let i = 0; i < arr.length; i++){ let item = arr[i]; if(!(item instanceof MyPromise)) continue; item.then( result => { index++; results[i] = result; if(index === arr.length){ resolve(results); } }).catch(reason => { reject(reason) }) } }) }}