目录
- 前言
- 改写this实现思路
- 前期准备
- 手写call方法
- 手写apply方法
- 手写bind方法
前言
改变this指向在书写业务的时候经常遇到,我们经常采用以下方法进行改写
- 使用作用声明变量存储this
- 使用jJavaScript的原生方法call,apply,以及bind进行改写
第一种方法就不说了,就是一个变量存储的问题,主要说第二种如何实现的
call,bind,apply方法都是JavaScript原生的方法,挂载在Function原型上,使得所有函数都可以调用,今天我们来实现一下call,apply,bind吧
改写this实现思路
我们声明一个函数,函数接受俩个参数,第一个参数是接受改变的this指向,第二个是剩余参数,用于执行改变方法后传递的使用参数,在函数中里面声明一个变量用于存储传递过来的this,遵循this指向的准则,this是在执行的时候生成的,函数的准则是谁调用它就指向谁,传递过来的this是一个对象,然后在传递过来的this上面声明一个方法,声明的方法就是当前函数,该方法由传递过来的this进行调用执行,这样就改变了this指向问题,在把传递过来的参数除第一个外全部传递给声明的方法,我们来实现一下
前期准备
这些数据用于配合手写的方法,由于call,bind,apply他们都是需要把他们挂载到函数原型上,函数才能调用的到,我们这里也把他挂载到原型上
var name = '前端';
var age = "7";
let obj = {
name: '若水',
age: '20'
};
function fnLog(arg) {
let str = `我叫${this.name}今年${this.age}岁了`;
console.log(str, '传递过来的', arg);
}
手写的call,bind,apply方法第一个参数都是改变的this指向,第二个参数是传递的参数
手写call方法
call方法是改变this后立即执行
Function.prototype.myCall = function(content, ...arg) {
// 创建一个变量接受改变的this,如果改变的this为空则采用window为默认this
let newThis = content || window;
/**newThis是一个对象,它是传递过来的this,在newThis上新增一个方法,这个方法就是
当前函数 ,this就是指向的myCall,调用这个方法就可以改变this指向,因为函数是谁调用
它this就指向谁
**/
newThis.fn = this;
/**执行改变this方法,接受返回值,这里容易被误导,这里是把myCall传递过来的参数传递
给了改变this的函数,由于不确定传递多少使用了剩余参数,这里也是 **/
let result = newThis.fn(...arg);
//删除传递过来this上声明的方法,防止出现问题
delete newThis.fn;
// 将执行结果返回
return result;
};
//执行手写的call方法
fnLog.myCall(obj, 'myCall');
手写apply方法
apply传递的参数只能传递数组
//如果arg没有传递参数,默认为空数组
Function.prototype.myApply = function(content, arg = []) {
// 判断传递参数是否为数组,如果不为数组则抛出错误,为数组则继续执行
if (!Array.isArray(arg)) {
throw '传递参数必须为数组';
}
// 创建一个变量接受改变的this,如果改变的this为空则采用window为默认this
let newThis = content || window;
// 给当前传递过来的this,添加一个方法,遵循this准则,谁调用就指向谁的原则
newThis.fn = this;
// 同mycall相同
let result = newThis.fn(arg);
//删除传递过来this上声明的方法,防止出现问题
delete newThis.fn;
// 将执行结果返回
return result;
};
//执行
fnLog.myApply(obj, [1, 212, 232]);
手写bind方法
bind不是立即执行而是返回一个新的函数
Function.prototype.myBind = function(content, ...arg) {
// 创建一个变量接受改变的this,如果改变的this为空则采用window为默认this
let newThis = content || window;
// 给当前传递过来的this,添加一个方法,遵循this准则,谁调用就指向谁的原则
newThis.fn = this;
// 由于bind不是立即执行,是返回一个函数作为bind方法执行的返回值,所以这里需要return出去一个函数
return function() {
// 然后在把执行当前的方法进行执行并把myBind接受剩余参数传递过去,接受返回值
let result = newThis.fn(...arg);
//删除当前的函数以及传递过来的this,防止出现问题
delete newThis.fn;
// 将执行结果返回
return result;
}
};
//调用bind函数,获取返回值,他的返回值是一个函数,所以我们需要在调用一下
let f1 = fnLog.myBind(obj, 2);
//调用bind的返回值
f1()
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

评论(0)