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)
})
}
})
}
}