JavaScript 中的 this

TODO:了解一些规则定义 https://blog.csdn.net/cjgeng88/article/details/79846670 https://blog.csdn.net/itKingOne/article/details/84783351

全局执行

console.log(this) // window
1

全局作用域中 this 指向当前的全局对象 Window

函数中执行

  1. 非严格模式下
function func() {
  console.log(this)
}
func()
// window
1
2
3
4
5
  1. 严格模式中
'use strict'
function func() {
  console.log(this)
}
func()
// undefined
1
2
3
4
5
6

作为对象的方法调用

当一个函数作为一个对象的方法调用的时候,this 指向当前的对象 obj:

var obj= {
	name:'kk'
	func:function(){
		console.log(this.name)
	}
}
obj.func()
// kk
1
2
3
4
5
6
7
8

如果把对象的方法赋值给一个变量,调用该方法时,this 指向 window

var obj = {
  name: 'kk',
  func: function() {
    console.log(this.name)
  }
}
var test = obj.func
test()
// window
1
2
3
4
5
6
7
8
9

作为一个构造函数使用

function Person(name) {
  this.name = name
  console.log(this.name)
}
var p1 = new Person('kk')
// kk
1
2
3
4
5
6

此时,this 指向这个构造函数调用的时候实例化出来的对象
如果将构造函数当做一个普通函数来调用,this 指向 window:

var p2 = Person('MM')
// undefined
// window 上不存在 name 属性
1
2
3

在定时器中使用

setInterval(function() {
  console.log(this)
}, 2000)
// window
1
2
3
4

如果没有特殊指向,setInterval 和 setTimeout 的回调函数中 this 的指向都是 Window 。这是因为 JS 的定时器方法是定义在 Window 下的。

箭头函数

在全局环境中调用:

var func = () => {
  console.log(this)
}
func()
// window
1
2
3
4
5

作为对象的一个函数调用:

var obj = {
  name: 'hh',
  func: function() {
    console.log(this)
  }
}
obj.func()
// obj

var obj = {
  name: 'hh',
  func: () => {
    console.log(this)
  }
}
obj.func()
// window
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

因为箭头函数不会改变 this 的指向,此时 this 指向的是调用时上下文环境。
特殊情况:结合定时器调用:

var obj = {
  name: 'hh',
  func: function() {
    setTimeout(function() {
      console.log(this)
    }, 0)
  }
}
obj.func()
// window
1
2
3
4
5
6
7
8
9
10

普通函数作为定时器延时执行的函数调用时,this 指向 window

var obj = {
  name: 'hh',
  func: function() {
    setTimeout(() => {
      console.log(this)
    }, 0)
  }
}
obj.func()
// obj
1
2
3
4
5
6
7
8
9
10

箭头函数不可以改变 this 的指向

箭头函数中 this 的值取决于该函数外部非箭头函数的 this 的值,且不能通过 call() 、 apply() 和 bind() 方法来改变 this 的值

call、apply、bind

call: fun.call(thisArg[,arg1[,arg2[,...]]])
它会立即执行函数,第一个参数是指定执行函数中 this 的上下文,后面的参数是执行函数需要传入的参数。

apply: fun.apply(thisArg,[argsArray])
它也会立即执行函数,第一个参数是指定执行函数中 this 的上下文,第二个参数是一个数组,是传给执行函数的参数(与 call 的区别)。

bind: var foo = fun.bind(thisArg[, arg1[, arg2[, ...]]]);
它不会执行函数,而是返回一个新的函数,这个新的函数被指定了 this 的上下文,后面的参数是执行函数需要传入的参数。

function Person(name, age) {
  this.name = name
  this.age = age
  console.log(this)
}
var obj = {
  name: 'kk',
  age: 0
}
Person.call(obj, 'mm', 10)
// {name: "mm", age: 10}
Person.apply(obj, ['mm', 10])
// {name: "mm", age: 10}
var test = Person.bind(obj, 'mm', 10)
new test()
// Person{name:"mm",age:"10"}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

怎么改变 this 的指向

  • call apply bind
  • 在 setTimeout 中使用箭头函数
  • 在函数内部保存 this 对象 var self = this

示例

function foo(){ 
    return () => {
        console.log( this.a );
    }   
}

var a = 2;

var obj = { 
    a: 3,
    foo: foo 
};

var bar = obj.foo();
bar(); //3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

解析:因为箭头函数不会改变 this 的指向,此时的 this 永远指向定义时的作用域。即为 obj,故为 3。如果是普通函数,bar 执行时,指向 bar 自身所在的作用域,故为 2。

上次更新时间: 8/11/2020, 4:44:59 PM