call,apply,bind是JS里面的改变作用域的三种方式,区别很明显,call参数是一个个穿进去的,apply的参数是数组,bind跟call,apply不同的是,bind绑定对象后,没有立即执行,前面的两个有执行。
下面来实现自己的call,apply,bind
call的自定义实现
function a(){ console.log(arguments) } var b = { name: 'gaofeng' }很显然b对象是不能调用a方法的,那非要强制调用a方法呢,我们可以
a.call(b) //{} a.call(b,1,2,3,4) //{ '0': 1, '1': 2, '2': 3, '3': 4 }其他的两个也可以实现,但不是这次要记录的重点。下面封装自己的call,apply,bind方法
Function.prototype.myCall = function (contxt) { //this 这里的this,我们要明白指的是谁,原型方法里的this,指的是实例,是我们new出来的对象 //比如a.myCall(b)现在的this指代的是a对象 if(typeof this !== 'function'){ throw new Errow('not a function') } console.log(this) //[Function: a] } a.myCall(b)现在的思路是在myCall里面调用a,然后把结果返回出来
Function.prototype.myCall = function (contxt) { //this 这里的this,我们要明白指的是谁,原型方法里的this,指的是实例,是我们new出来的对象 //比如a.myCall(b)现在的this指代的是a对象,记住函数也是对象 if(typeof this !== 'function'){ throw new Errow('not a function') } console.log(this) contxt = contxt || window; var args = [...arguments]; //方法要接收的参数 var self = this; // 我们要调用的方法名 var res = this(...args); return res; } a.myCall(b,123,456) //{ '0': { name: 'gaofeng' }, '1': 123, '2': 456 }另一种方法
Function.prototype.myCall = function (contxt = window) { if(typeof this !== 'function'){ throw new Errow("not a function") } contxt.fn = this; //上下文对象上添加一个属性指向this; var args = [...arguments].slice(1); var res = contxt.fn(...args); return res; } function a(){ console.log(arguments) } var b = { name: 'gaofeng' } a.myCall(b) //{ '0': { name: 'gaofeng', fn: [Function: a] }}可以看到答应的对象里面多出了一个fn属性,这不是我们想要的,所以要删掉
Function.prototype.myCall = function (contxt = window) { if(typeof this !== 'function'){ throw new Errow("not a function") } contxt.fn = this; //上下文对象上添加一个属性指向this; var args = [...arguments].slice(1); var res = contxt.fn(...args); delete contxt.fn return res; } function a(){ console.log(arguments) } var b = { name: 'gaofeng' } a.myCall(b,1,2) //{ '0': 1, '1': 2 }也实现了需求。
2.apply,与call方法的区别是参数的传递方式不一样
Function.prototype.myApply = function (contxt = window) { if (typeof this !== 'function') { throw new Error('not a function') } var args = arguments[1]; var self = this; var res; if (args) { res = this(...args ) } else { res = self(); } } function a(){ console.log(arguments) } var b = { name: 'gaofeng' } a.myApply(b,[1,2,3,4,5]) //{ '0': 1, '1': 2, '2': 3, '3': 4, '4': 5 }另外一种实现方式
Function.prototype.myApply = function (contxt) { if(typeof this !== 'function'){ throw new Error('not a function') } contxt = contxt || window; let res,args=arguments[1]; contxt.fn = this; if(args){ res - contxt.fn(...args) }else{ res = contxt.fn(); } delete contxt.fn; } function a(){ console.log(arguments) } var b = { name: 'gaofeng' } a.myApply(b,[1,2,3,4,5]) //{ '0': 1, '1': 2, '2': 3, '3': 4, '4': 5 }3.bind的实现
Function.prototype.myBind = function (contxt) { if(typeof this !== 'function'){ throw new Errow('not a function') } let _this = this; // 当前实例指的是a let args = [...arguments].slice(1); //这里是myBind函数的参数 return function F(){ if(this instanceof F){ //这里我们可以使用new方法来调用 return new _this(...args,...arguments) }else{ return _this.apply(contxt,args.concat(...arguments)) } } } function a(){ console.log(arguments) } var b = { name: 'gaofeng' } var b = a.myBind(b,'a','b')(1,2,3,4) //{ '0': 'a', '1': 'b', '2': 1, '3': 2, '4': 3, '5': 4 } var c = a.myBind(b,'a') var c1 = new c('1',2) console.log(c1) //{ '0': 'a', '1': '1', '2': 2 } //a {}4.instanceof
function instanceOf(left, right) { let leftValue = left.__proto__ let rightValue = right.prototype while (true) { if (leftValue === null) { return false } if (leftValue === rightValue) { return true } leftValue = leftValue.__proto__ } } function A(){ } var a = new A() var b = {} console.log(instanceOf(a,A)) //true console.log(instanceOf(b,A)) //false5.object.create()方法的实现
function create(obj){ function F(){} F.prototype = obj; return new F(); } var d = {c:1} var a = create(d) console.log(a.c); a.c = 2; console.log(a.c); console.log(d.c)6.实现new
function myNew(fun){ return function (){ let obj = { __proto__:fun.prototype } fun.call(obj,...arguments) return obj; } } function person(name,age){ this.name = name; this.age =age; } let obj = myNew(person)('gaofeng',20) console.log(obj)简易版的promise
class MyPromise{ constructor(fn){ this.state = 'pending'; this.value = undefined; this.reason = undefined; let resolve = value => { if(this.state === 'pending'){ this.state = 'fulfilled'; this.value = value } } let reject = value => { if(this.state === 'pending'){ this.state = 'rejected'; this.reason = value; } } try{ fn(resolve,reject); }catch(e){ reject(e) } } then(onFulfilled,onRejected){ switch(this.state){ case 'fulfilled': onFulfilled(); break; case 'rejected': onRejected(); break; default: } } } new MyPromise((resolve,reject) => { resolve('dddd') })
