自己尝试一下如何实现call,apply,bind
- 第一步我们先在Function的原型上面新建一个函数吧.叫myApply
const obj = {
name:'joy',
};
function getName() {
console.log(this.name);
}
Function.prototype.newApply= function () {
console.log(this);
};
getName.newApply(); //ƒ getName(){ console.log(this.name); }
这时候打印出来,this是getName这个函数.
根据我之前写过的一篇文章 (确定this的指向)
得知,this绑定的优先级是
箭头函数 > new > 显式 > 隐式 > 默认绑定
call,apply是属于显示绑定,那肯定不能用箭头函数和new来代替了,否则优先级就改变了,那就只能用隐式绑定的方式了
- 所以我们要用隐式绑定的方式去改变this的指向
const obj = {
name:'joy'
};
function getName(){
console.log(this.name);
}
Function.prototype.newApply= function (that) {
that.myFn = this;
const result = that.myFn();
return result
};
getName.newApply(obj); //joy
这里已经是初步完成了改变this指向的功能了,让我们在来完善一下
- 加上传递参数和不传this调用
const obj = {
name:'joy'
};
function getName(a,b){
console.log(this.name,a,b);
}
Function.prototype.newApply = function (that,arg) {
if(typeof this !== 'function'){
throw this+'is not a function'
}
that = that || window; //因为第一个参数如果不传就会绑定到window上面
arg = arg || [];
that.myFn = this;
const result = that.myFn(...arg); //解构赋值把参数传进来,先把结果存起来
delete that.myFn; //再删除,否则就有副作用了
return result;
};
getName.newApply(obj,[1,2]); // joy
- 这样一个apply就完成了,可能还有些地方没考虑到,但是大概功能都出来了,call也是差不多就是传参不太一样
const obj = {
name:'joy'
};
function getName(a,b){
console.log(this.name,a,b);
}
Function.prototype.newCall = function (that, ...arg) {
if (typeof this !== 'function') {
throw this + 'is not a function'
}
that = that || window; //因为第一个参数如果不传就会绑定到window上面
that.myFn = this;
const result = that.myFn(...arg); //解构赋值把参数传进来,先把结果存起来
delete that.myFn; //再删除,否则就有副作用了
return result;
};
getName.newApply(obj, 1, 2); // joy 1 2
以上就是apply和call自己实现的方式了.
- 接下来到一个难点bind了,bind有点不一样,call和apply是绑定直接调用,而bind是绑定不调用,返回绑定后的函数
- 那么直接利用apply不就可以了
const obj = {
name:'joy'
};
function getName(){
console.log(this.name);
}
Function.prototype.newBind = function (that) {
const fn = this;
return function () {
fn.apply(that)
}
};
getName.newBind(obj)() //joy
- 再优化一下
const obj = {
name:'joy'
};
function getName(){
console.log(this.name);
}
Function.prototype.newBind = function (that) {
if (typeof this !== 'function') {
throw new TypeError('Error')
}
const args = [...arguments].slice(1);
const fn = this;
return function () {
fn.apply(that)
};
// 返回一个函数
return function F() {
// 因为返回了一个函数,如果是new的话this就要指向新创建的对象了
if (this instanceof F) {
return new fn(...args, ...arguments)
}
return fn.apply(that, args.concat(...arguments))
}
};
getName.newBind(obj)() //joy
以上就是实现call,apply,bind的内容了