今天来重温一下更改this指向的三种方法bind, call, apply。
突然面试被问到了,bind和call的区别?直接一脸懵逼,后来查了一下:bind改变this指向之后回返回一个函数,不会立即执行,需要手动触发一下。
call、apply、bind正常用法
let user = {
birthday: '2/25'
}
var test = getData.bind(user);
function getData(name, age) {
console.log('name', name);
console.log('age', age);
console.log('this.birthday', this.birthday);
}
// call和apply只是传入方式不同,call是列表,apply是数组
getData.call(user, 'tian', '22');
getData.apply(user, ['tian', '22']);
test(); // this.birthday 2/25
call、apply、bind模拟方法
call
实现方法
// 原理是我们可以通过给user创建个gatData方法,然后执行完后再删除来模拟更改this指向的操作。
Function.prototype.call = function (context) {
// 获得this指向的对象
var cxt = context || window;
// 改变传入对象函数的this指向
cxt.fn = this;
/* 获得传入对象后面的参数
arguments: [对象,参数1,参数2]
arguments.slice(1): [参数1, 参数2]
**/
var reuslt;
var args;
if (arguments[1]) {
args = [...arguments]. slice(1);
result = cxt.fn(...args);
} else {
result = cxt.fn();
}
// 将参数传入函数
delete cxt.fn;
return result
}
apply
实现方法
// 原理相同,但是不同的是,apply接收参数是数组形式,所以只需要获得数组参数即可
Function.prototype.apply = function (context) {
var ctx = context || window;
ctx.fn = this;
var result;
if (arguments[1]) {
result = ctx.fn(... arguments[1]);
} else {
result = cxt.fn()
}
delete ctx.fn;
return result
}
bind
实现方法
// 最后bind实现起来就比较简单,不需要各种传参数之类的,只需要注意当前环境必须是function
Function.prototype.bind = function (context) {
if (typeof this !== 'function') {
throw new TypeError('Error')
}
var _this = this
var args = [...arguments].slice(1)
// 返回一个函数
return function F() {
// 因为返回了一个函数,我们可以 new F(),所以需要判断
if (this instanceof F) {
return new _this(...args, ...arguments)
}
return _this.apply(context, args.concat(...arguments))
}
}
3种方法都是能改变this的指向,平时可以根据需求自由选择~
今天就重温到这里,明天再见😝
网友评论