this
一,理解this
定义:this引用的是函数执行的环境变量
1.普通函数中的this
function fn() {
console.log(this)//this指向顶层,浏览器中是widow,node中是gobal对象
}
let obj = {
fn: function() {
console.log(this) //this指向obj对象
}
}
ARR.prototype.add = function(arr){
console.log(this) // this指向[1,2,3]。js指向调用此方法的对象
}
[1,2,3].add()
2.构造函数中的this
构造函数中的this指向新创建的对象本身
function person(obj) {
this.name = obj.name
console.log(this) //当前new的对象
}
var p1 = new person({name:"bob"})
console.log(p1) //同上
3.ES6箭头函数中的this
指向包裹箭头函数的最外层
var name = "Bob";
var obj = {
name: "Dancy",
fn: () => {
console.log(this); //顶层对象,在浏览器中是window对象
}
}
obj.fn();
二,call apply和bind的理解
三个方法都继承自Function.prototype。所以所有函数皆能调用
参数
- call:
call(this,arg1,arg2,arg3)
- apply:
apply(this,[arg1,arg2,arg3])
- bind:
bind(this,arg1,arg2,arg3)
定义:
call和apply: 指定函数内部的this指向,然后再所指定的作用域中调用该函数,立即执行该函数。
bind: 指定函数内部的this指向,然后返回一个新函数。bind不会立即执行一个函数
相同点:
- 三者第一个参数都是指定函数的this指向
- 都可以在函数调用时给函数传递参数
区别:
- call和apply都会自动调用函数。bind是返回一个新的函数。需要加
()
才能调用 - call和bind的参数一致。apply只有两个参数,第二个参数是个数组。传参都放在数组中
例子:
let obj ={
a:23,
e: 88
}
function fn(a,b,c) {
console.log(this.a); //obj.a this指向obj
console.log(a+b+c+this.e); //
}
fn.call(obj,1,2,3); // 23 94
fn.apply(obj,[1,2,3]) // 23 6
fn.bind(obj,1,2,3)() // 23 6
三,call apply和bind的应用场景
1.返回数组中的最大值
arr = [1,2,3,4]
console.log(Math.max.apply(null,arr)) // 把数组的每一项作为Math.max()的入参
console.log(Math.max.call(...arr))
console.log(Math.max.bind(...arr)())
2.将数组的空元素变为undefined
空元素与undefined的区别在于,数组的forEach方法会跳过空元素,但是不会跳过undefined和null
let a=[1,,3]
a.forEach((item)=>console.log(item)) //1 3 跳过空元素
Array.apply(null,a).forEach((item)=> console.log(item)) // 1 undefined 3
3.将类数组对象arguments转换成数组
function change(a,b,c) {
let arrarg = [].slice.call(arguments); //Array.prototype.slice.call(arguments);
console.log(arrarg);
}
change(1,2,3)
arguments不是数组,但是可以向数组一样循环。而slice方法的底层也是依靠循环实现的,且arr.slice() -> arr。我们只要在slice函数运行的时候把slice的this指向arguments就行。
只有数组才能调用现成slice函数。调用方法有两种
一, Array.prototype.slice() // 通过原型链直接去访问
二,[].slice //来个继承了slice的空数组
4.定时器中使用bind
只是单纯的需要一个指向新的this的函数,就可以用bind。call和apply会立即调用函数
obj={
index: 0,
time: 0
}
function fn() {
this.index ++
this.time += 100
console.log(this)
}
setInterval(fn.bind(obj),1000)
5.组合继承
function parent(value) {
this.val = value
}
parent.prototype.getValue=function(){
console.log(this.val)
}
function child(value){
parent.call(this,value)
}
child.prototype = new parent()
let test = new child(1)
test.getValue()