实现一个Promise
过程
1.new Promise((resolve,reject) = > { }) ,传入一个参数executor,传入就执行。executor有两个参数resolve和reject。
2.Promise存在三个状态 pending(等待态)、fulfilled(成功态)、rejected(失败态)。
3.new Promise((resolve, reject)=>{resolve(value)}) resolve为成功,接收参数value,状态改变为fulfilled,不可再次改变。
4.若是executor函数报错 直接执行reject()
5.then方法,有两个参数onFulfilled,onRejected。这两个是可选参数,当参数不是函数类型时,需要创建一个函数赋值给相应的参数
6.then时state还是pending等待状态 我们就需要在then调用的时候,将成功和失败存到各自的数组,一旦reject或者resolve,就调用它们。如果是fulfilled状态,就执行onFulfilled; rejected状态,就执行onRejected
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49class Promise{
constructor(executor){
this.state='pending';
this.value=undefined;
this.reason=undefined;
this.resolvedCbs=[];
this.rejectedCbs=[];
let resolve=(value)=>{
if(this.state==='pending'){
this.state='fulfilled';
this.value=value;
this.resolvedCbs.forEach(cb=>cb());
}
}
let reject=(reason)=>{
if(this.state==='pending'){
this.state='rejected';
this.reason=reason;
this.rejectedCbs.forEach(cb=>cb());
}
}
try{
executor(resolve,reject);
}catch(err){
reject(err);
}
}
then(onFulfilled,onRejected){
onFulfilled=typeof onFulfilled ==='function'?onFulfilled:v=>v;
onRejected=typeof onRejected==='function'?onRejected:(err)=>{
throw err;
}
if(this.state==='fulfilled'){
onFulfilled(this.value);
}
if(this.state==='rejected'){
onRejected(this.reason);
}
if(this.state==='pending'){
this.resolvedCbs.push(()=>{onFulfilled(this.value)});
this.rejectedCbs.push(()=>{onRejected(this.reason)});
}
}
}
实现Promise.all
- 必须为数组
- 可以传入非promise,all自动将其转换为promise对象
- 传入的值必须按顺序输出
- 一旦又一个reject则状态立马变为reject,并将错误原因抛出
1 | function myPromiseAll(promiseArr){ |
实现Promise.race
1 | function myPromiseRace(promiseArr){ |
实现Ajax
1 | function ajax(url,fnSucc,fnFail){ |
实现 call,apply
如何实现这几个函数
- 如果不传入第一个参数,那么上下文默认为window
- 改变this指向,让新的对象可以执行该函数,并接受参数 (this的使用场景:对象属性使用)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49//call
Function.prototype.myCall=function (obj){
if(typeof this !== 'function'){
throw new Error('error');
}
obj=obj || window;
const args=[...arguments].slice(1);//去掉第一个参数
obj.fn=this;//将执行函数设为对象属性
const res=obj.fn(...args);
delete obj.fn;
return res;
}
//Test
const foo={
value:1,
}
function bar(name){
console.log(this.value);//在全局作用域下执行,this指向 window
console.log(name);
}
bar.myCall(foo);
//apply
Function.prototype.myApply=function (obj){
if(typeof this !== 'function'){
throw new Error('Error');
}
obj=obj || window;
obj.fn=this;
let res;
if(arguments[1]){
res=obj.fn(...arguments[1]);
}else{
res=obj.fn();
}
delete obj.fn;
return res;
}
//Test
const foo={
value:1,
}
function bar(name){
console.log(this.value);//在全局作用域下执行,this指向 window
console.log(name);
}
bar.myApply(foo,['winnie']);
实现 bind
注意
1.改变this指向,可用call或apply
2.返回的是一个函数,也可以传参,两次传参要合并
3.对绑定函数的使用new 操作符时,传入的this忽略,但其他参数仍可用(this规则的优先级,new优先级最高)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27Function.prototype.myBind=function(obj){
if(typeof this !== 'function'){
throw new Error('error');
}
const exeFn=this;
const args1=[...arguments].slice(1);
return function F(...arguments){
if(this instanceof F){//使用了new 操作符
return new exeFn(...args1,...arguments);
}
return exeFn.apply(obj,args1.concat(...arguments));
}
}
//Test
const foo={
value:1,
}
function Bar(name,age){
console.log(this.value);
console.log(name);
console.log(age);
}
const myBar=Bar.myBind(foo,'winnie');//对绑定函数的使用new 操作符时,传入的this忽略,但其他参数仍可用
const bar1=new myBar(18);
const bar2=Bar.myBind(foo,'lm',18)();
实现一个继承
寄生组合继承
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18function Parent(val){
this.value=val;
}
Parent.prototype.getValue=function (){
console.log(this.value);
}
function Child(val){
//继承父类属性
Parent.call(this,val);
}
Child.prototype=Object.create(Parent.prototype,{
constructor:{
value:Child,
enumerable:false,
writable:true,
configurable:true
}
});//Object.create()方法创建一个新对象,使用现有对象来提供新建对象的__proto__
实现一个深拷贝
1 | function deepClone(obj){ |
实现一个 instanceOf
1 | function myInstanceOf(left,right){ |
实现一个new操作符
1 | function Person(name){ |
实现防抖和节流
- 防抖 原理:延迟一段时间再执行,如果在延迟的时间内继续触发,会重新计算。
- 节流 原理:隔一段时间,执行一次。就像水龙头滴一样。
1 | //防抖 |
实现一个函数柯里化
1 | const curry=(fn,...arguments)=>{ |
斐波那契数
- 递归版
1 | const recursionFib=(n)=>{ |
- 迭代版
1 | const iterationFib=(n)=>{ |
判断变量类型
1 | //判断JS变量类型,值类型、引用类型、null单独判断 |
最长公共子串
1 | const LCS=(str1,str2)=>{ |
最长回文子串
1 | const LPS=(str)=>{ |
杨辉三角
1 | const triangle=(n)=>{ |
括号匹配
1 | const matchBrackets=(s)=>{ |
实现函数的累加
1 | const plus_one=(...arguments)=>{//对arguments使用扩展运算符不能少 |
闭包的应用
1 | function CoolModule(){ |
实现一个按顺序加载的 promise
1 | /* 使用 async await */ |
实现一个 EventEmitter 方法
1 | class EventEmitter { |
实现一个jsonp
1 | function jsonp({url,params,callback}){ |