JavaScript 中的 this
TODO:了解一些规则定义 https://blog.csdn.net/cjgeng88/article/details/79846670 https://blog.csdn.net/itKingOne/article/details/84783351
全局执行
console.log(this) // window
全局作用域中 this 指向当前的全局对象 Window
函数中执行
- 非严格模式下
function func() {
console.log(this)
}
func()
// window
2
3
4
5
- 严格模式中
'use strict'
function func() {
console.log(this)
}
func()
// undefined
2
3
4
5
6
作为对象的方法调用
当一个函数作为一个对象的方法调用的时候,this 指向当前的对象 obj:
var obj= {
name:'kk'
func:function(){
console.log(this.name)
}
}
obj.func()
// kk
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
2
3
4
5
6
7
8
9
作为一个构造函数使用
function Person(name) {
this.name = name
console.log(this.name)
}
var p1 = new Person('kk')
// kk
2
3
4
5
6
此时,this 指向这个构造函数调用的时候实例化出来的对象。
如果将构造函数当做一个普通函数来调用,this 指向 window:
var p2 = Person('MM')
// undefined
// window 上不存在 name 属性
2
3
在定时器中使用
setInterval(function() {
console.log(this)
}, 2000)
// window
2
3
4
如果没有特殊指向,setInterval 和 setTimeout 的回调函数中 this 的指向都是 Window 。这是因为 JS 的定时器方法是定义在 Window 下的。
箭头函数
在全局环境中调用:
var func = () => {
console.log(this)
}
func()
// window
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
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
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
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"}
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
解析:因为箭头函数不会改变 this 的指向,此时的 this 永远指向定义时的作用域。即为 obj,故为 3。如果是普通函数,bar 执行时,指向 bar 自身所在的作用域,故为 2。