this是在运行时绑定的,跟函数定义的位置没有关系,跟函数调用的方式以及调用位置有关系。
遵循四个规则:
1.默认绑定
2.隐式绑定
3.显示绑定
4.new绑定
默认绑定
当函数直接调用(独立调用)时,在浏览器中this指向window,在node环境下this指向空对象 {}
隐式绑定
通过上下文对象调用,这种需要对象内部必须有一个属性是对函数的引用,this绑定到这个上下文对象
显式绑定
通过call、apply、bind调用,this绑定到指定的对象
new绑定
通过new调用,this绑定到新创建的实例上
绑定例外:
规则总有例外,这里也是一样的
1.被忽略的this
当你把null,undefined作为this传给call,apply,bind,会被忽略,这里就会采用默认绑定
- var a = 'hello'
- function foo() {
- console.log(this.a, 'this')
- }
- foo.call(null) // hello
2.箭头函数中的this
this的经典面试题:
- var name = 'window'
- var person1 = { // person1只是定义对象,并没有产生作用域
- name: 'person1',
- foo1: function () {
- console.log(this.name)
- },
- foo2: () => console.log(this.name), //上层作用域是全局
- foo3: function () {
- return function () {
- console.log(this.name)
- }
- },
- foo4: function () {
- return () => {
- console.log(this.name)
- }
- }
- }
- var person2 = { name: 'person2' }
- person1.foo1(); //person1
- person1.foo1.call(person2); // person2 (显示绑定的优先级大于隐式绑定)
- person1.foo2(); // window (箭头函数不绑定this,上层作用域是全局)
- person1.foo2.call(person2); //window (箭头函数不绑定this,上层作用域是全局)
- person1.foo3()(); // (独立的函数调用) //window
- person1.foo3.call(person2)(); // (独立的函数调用)window
- person1.foo3().call(person2); // person2
- person1.foo4()(); //person1(箭头函数不绑定this,上层作用域是person1)
- person1.foo4.call(person2)(); // person2 (箭头函数不绑定this,上层作用域是person2)
- person1.foo4().call(person2); // person1 (箭头函数不绑定this,上层作用域是person1)
- var name = 'window'
- function Person(name) {
- this.name = name
- this.foo1 = function () {
- console.log(this.name)
- },
- this.foo2 = () => console.log(this.name),
- this.foo3 = function () {
- return function () {
- console.log(this.name)
- }
- },
- this.foo4 = function () {
- return () => {
- console.log(this.name)
- }
- }
- }
- var person1 = new Person('person1')
- var person2 = new Person('person2')
- person1.foo1() // person1
- person1.foo1.call(person2) // person2 (显示绑定大于隐式绑定)
- person1.foo2() // person1 (上层作用域的this是person1)
- person1.foo2.call(person2) //person1 (箭头函数中不绑定this ,所以依旧中啊上层作用域)
- person1.foo3()() //window (独立函数调用)
- person1.foo3.call(person2)() // window (独立函数调用)
- person1.foo3().call(person2) // person2
- person1.foo4()() // person1
- person1.foo4.call(person2)() //person2
- person1.foo4().call(person2) // person1