this
解析器在调用函数时都会向函数内部传入一个隐含的参数,这个隐含的参数就是this,this指向的是一个对象,这个对象就是函数执行的上下文对象。执行上下文对象是什么呢?它指的是当函数在执行时,会创建一个执行期上下文的内部对象。一个执行期上下文定义了一个函数执行时的环境。每调用一次函数,就会创建一个新的上下文对象,他们之间是相互独立且独一无二的。当函数执行完毕,它所产生的执行期上下文会被销毁。
函数内的this指向
我们知道函数的调用有6种形式,根据函数调用形式的不同,this指向也会发生相应的变化:
1、以函数(包括普通函数、定时器函数、立即执行函数)的形式来调用时,this的指向永远都是window,比如fun(),相当于window.fun()。比如:

function fun() {
    console.log(this)
    console.log(this.name)
}
var obj1 = {
    name: 'smyh',
    sayName: fun,
};

var obj2 = {
    name: 'vae',
    sayName: fun,
};
var name = 'xxx;//全局的name属性

fun()

打印结果:

window
xxx
上面的举例可以看出,this 指向的是 window 对象,所以 this.name 指的是全局的 name。
2、以方法的形式调用时,this指向调用该方法的对象。比如:

function fun() {
    console.log(this);
    console.log(this.name);
}

var obj1 = {
    name: 'smyh',
    sayName: fun,
};

var obj2 = {
    name: 'vae',
    sayName: fun,
};

var name = '全局的name属性';
//以方法的形式调用,this是调用方法的对象

obj2.sayName();

打印结果:

 Object
 vae

上面的举例可以看出,this 指向的是 对象 obj2 ,所以 this.name 指的是 obj2.name。
3、以构造函数的形式调用时,this指向实例对象
4、以事件绑定函数的形式调用时,this指向绑定事件的对象
5、使用call和apply调用时,this指向指定的那个对象
call()和apply()的用法:
这两个方法都是函数对象的方法,都需要通过函数对象来调用,当函数调用时,函数会立即执行。
都可以用来改变this的指向
第一个参数都是this要指向的对象,后面的参数都是函数方法的实参。
比如:

function foo(){
    console.log(this.a)
}
var obj = {
    a: 2
}
// 将 this 指向 obj
foo.apply(obj); //打印结果:2

第一个参数的传递:
(1)、thisObj不传或者为null、undefined时,函数中的this会指向window对象(非严格模式)。
(2)、传递一个别的函数名时,函数中的this将指向这个函数的引用。
(3)、传递的值为数字、布尔值、字符串时,this会指向这些基本类型的包装对象Number、Boolean、String。
(4)、传递一个对象时,函数中的this则指向传递的这个对象。
call()和apply()的区别:
实参传递方式不同。call()在对象之后依次传递实参,apply()在对象之后将实参封装进一个数组进行统一的传递(即使只有一个参数)。
6、箭头函数没有自己的this,如果我们在这样的函数中使用this,那么它取决于外部正常的函数。比如:

let user = {
  firstName: "Ilya",
  sayHi() {
    let arrow = () => alert(this.firstName);
    arrow();
  }
};

user.sayHi(); // Ilya