this
普通函数this
- 在函数中直接使用 类似于 fun.call(window, 参数)
- 函数作为对象的方法被调用(谁调用,指向谁) obj.run.call(obj,参数)
箭头函数this
- 箭头函数中的this是在函数定义时绑定的,而不是函数执行时绑定的
- 箭头函数中this指向的固定化,并不是因为箭头函数内部有绑定this的机制,而是因为箭头函数没有自己的this,导致内部的this是外层代码块的this,也因此,箭头函数不能用作构造函数
call|apply|bind
改变函数运行时this的指向
function person(age, gender,type) {
console.log(this);
return `my name is ${this.fullName},my age is ${age} and my gender is ${gender} ps:${type}`;
}
let obj = {
fullName: 'obj full name'
}
window.fullName = 'window full name';
//call方法调用
person.call(obj, 20, 'female','call改变指向obj');//指向obj
person.call(null, 57, 'female','call改变指向window');//指向window
//apply方法调用
person.apply(obj, 20, ['female','apply改变指向obj']);//指向obj
person.apply(null, 57, ['female','apply改变指向window']);//指向window
//bind方法
let f1 = person.bind(obj);//指定指向
let f2 = person.bind(obj, 30);//指定指向,传递部分参数
let f3 = person.bind(obj, 30, 'female','bind改变指向obj');指定指向并传参
//bind方法调用
f1(30, 'female','bind改变指向obj');
f2('female','bind改变指向obj');
f3();
call
call(参数1,参数2)
- 参数1:绑定给this的值,若为
null|undefined
,则默认指向window
- 参数2:参数列表
手写call
//通过rest参数,获取函数的实参,代替arguments。将剩余参数作为一个数组进行传递
Function.prototype.myCall = function(context, ...args){
//未传值或传空对象,指向window对象
context = context || window;
//定义临时方法
context.temp = this;
//调用临时方法,通过扩展运算符对传入参数数组进行展开
let res = context.temp(...args);
//删除临时方法
delete context.temp;
//返回结果
return res;
}
//手写call方法调用
person.myCall(obj, 20, 'female','手写call改变指向obj');//指向obj
person.myCall(null, 57, 'female','手写call改变指向window');//指向window
apply
apply(参数1,参数2)
- 参数1:绑定给this的值,若为
null|undefined
,则默认指向window
- 参数2:参数数组
手写apply
Function.prototype.myApply = function(context, args){
//未传值或传空对象,指向window对象
context = context || window;
//定义临时方法
context.temp = this;
//调用临时方法,传入的args为数组,需要使用扩展运算符进行展开
let res = context.temp(...args);
//删除临时方法
delete context.temp;
//返回结果
return res;
}
person.myApply(obj, 20, ['female','手写apply改变指向obj']);//指向obj
person.myApply(null, 57, ['female','手写apply改变指向window']);//指向window
bind
bind(参数1,参数2)
- 参数1:绑定给this的值,若为
null|undefined
,则默认指向window
- 参数2:参数列表
- 返回值:函数
手写bind
Function.prototype.bind = function(context, ...args){
var self = this;
return function(...args2){
self.call(context, ...args, ...args2);
}
}
let f1 = person.myBind(obj); //指定指向
let f2 = person.myBind(obj, 30); //指定指向,传递部分参数
let f3 = person.myBind(obj, 30, 'female', '手写bind改变指向obj'); //指定指向并传参
//调用
f1(30, 'female', '手写bind改变指向obj');
f2('female', '手写bind改变指向obj');
f3();
应用场景
-
求数组的最大值最小值
var arr = [1,2,3,4,5,6]; var max = Math.max.apply(null, arr); var min = Math.min.apply(null, arr);
-
将类数组转化为数组
var arr = Array.prototype.slice.call(arrayLike);
-
数组追加
var arr1 = [1,2,3]; var arr2 = [4,5,6]; var add = [].push.apply(arr1, arr2);//返回追加后的数组长度,此处为6 //arr1:[1,2,3,4,5,6] //arr2:[4,5,6]
-
判断变量类型
function isArray(obj){ return Object.prototype.toString.call(obj) == '[object Array]'; } isArray([]);//true isArray('dot');//false
-
利用call和apply做继承
function Person(name, age){ this.name = name; this.age = age; this.sayName = function(){ console.log(this.name); } } function Son(){ Person.apply(this, arguments); } var inherit = new Son("Son's name", 24);
-
使用log代理console.log
function log(){ console.log.call(console, arguments); }