this
this
的值:当前执行代码的环境对象,this
的指向不取决于它在什么位置建立,彻底取决于函数在什么地方被调用,this
不能在执行期间被赋值,而且在每次函数被调用时this的值也可能会不一样。javascript
this
的值在全局环境(任何函数调用的外部)中,this
的值都是全局对象(浏览器中是window
对象,node中是global
对象)html
在函数内部环境,this
的值取决于函数被调用的方式java
this
指向规则简单总结一个原理:this 永远指向最后调用它的那个对象node
直接调用函数的时候this
指向的是全局对象后端
var name = 'Window.name'
function foo() {
console.log('this',this.name)
}
foo() // Window.name
复制代码
注意:若是使用的是严格模式的话,全局对象是undefined
数组
var name = 'Window.name'
function foo() {
'use strict'
console.log('this',this.name)
}
foo() // Uncaught TypeError: Cannot read property 'name' of undefined
复制代码
当函数做为对象的属性被调用的时候就属于隐式绑定,这个时候,this指向的是这个函数的对象浏览器
var obj = {
num:0,
add:function() {
console.log('this',this) // this {num: 0, add: ƒ}
this.num +=1
}
}
obj.add()
console.log('obj',obj) // obj {num: 1, add: ƒ}
复制代码
在看下面一个栗子:app
var name = 'ahwgs'
var obj = {
name:'aaa',
foo:function() {
console.log('name',this.name)
}
}
var res = obj.foo
res() // ahwgs
复制代码
申明一个obj
对象,虽然将obj.foo
的引用赋值给res
,但实际上此时是res()
是不带修饰的函数调用(属于第一种函数绑定的状况),因此此时打印的值是ahwgs
函数
下面咱们作一点改动:ui
var name = 'ahwgs'
var obj = {
name:'aaa',
foo:function() {
console.log('name',this.name)
}
}
obj.foo() // name aaa
复制代码
这就是正常的隐式调用,这时候的this
为obj
自己
在看一个栗子:
var name = 'ahwgs'
function doFoo(fn) {
console.log('fn',fn)
fn() //f(){console.log('name',this.name)} fn=obj.foo
}
var obj = {
name:'aaa',
foo:function() {
console.log('name',this.name)
}
}
doFoo(obj.foo) // name ahwgs
复制代码
这时候,obj.foo
做为参数传递给了doFoo
,实际上调用仍是doFoo
,这时候this
指向的是全局对象,因此打印的是ahwgs
最后一个栗子:
var name = 'ahwgs'
function foo() {
var name = 'aaa'
fn()
function fn() {
console.log('name',this.name)
}
}
foo() // ahwgs
复制代码
借用开头说的一句话,this指向的是这个函数所属的对象因此,fn
指向的是全局对象
使用call/apply/bind
方法进行显式绑定
var name = 'ahwgs'
function foo() {
console.log('this',this)
console.log('name',this.name)
}
var obj = {
name:'obj'
}
foo.apply(obj) // name obj
foo.call(obj)// name obj
foo.bind(obj)()// name obj
复制代码
这时候的this
指向都被显式绑定至obj
,此后,不管如何调用函数,总会将obj绑定到foo中的this上。
new
绑定经过new
关键字调用的函数,属于new
绑定模式。这时this
关键字指向这个新建立的对象。
function User(name,age) {
this.name = name
this.age = age
this.getInfo = function() {
console.log('info',this.name + '--->'+this.age)
}
}
var user = new User('ahwgs',20)
console.log(user) // User {name: "ahwgs", age: 20, getInfo: ƒ}
console.log(user.getInfo()) // info ahwgs--->20
复制代码
this
指向箭头函数的 this 始终指向函数定义时的 this,而非执行时,箭头函数中没有 this
绑定,必须经过查找做用域链来决定其值,若是箭头函数被非箭头函数包含,则 this
绑定的是最近一层非箭头函数的 this
,不然,this 为 undefined
。
看一个栗子:
var name = 'ahwgs'
var obj = {
name:'aaa',
foo1:function() {
console.log('this.name',this.name)
},
foo2:function() {
setTimeout(()=>{
this.foo1()
},100)
}
}
obj.foo2() // aaa
复制代码
因为定时器中使用的是箭头函数的形式,上一级没有使用箭头函数,因此this
绑定的是最近一层非箭头函数的this
,在这里,即obj
const self = this
var name = 'ahwgs'
var obj = {
name:'aaa',
foo1:function() {
console.log('this.name',this.name)
},
foo2:function() {
var self = this
setTimeout(function() {
self.foo1()
})
}
}
obj.foo2() // aaa
复制代码
定义一个变量,将当前的this
指向改变至self
中,这样调用foo1
的时候this
指向就是obj
这个对象
apply、call、bind
先看一下这三个函数的使用方法:
apply
function.apply(obj, [param1,params2,...]) // obj:要绑定的this // 第二个参数:类数组或数组,做为function的参数传入 // 当即执行 复制代码
call
function.call(obj, param1, param2, ...) // obj:要绑定的this // 第二个参数:函数运行的参数,用逗号隔开 // 当即执行 复制代码
bind
function.bind(obj, param1, param2, ...) // obj:要绑定的this // 第二个参数:函数运行的参数,用逗号隔开 // 返回一个函数 复制代码
下面使用这三种方法修改this
指向
apply
var name = 'ahwgs'
var obj = {
name:'aaa',
foo1:function() {
console.log('this.name',this.name)
},
foo2:function() {
setTimeout(function() {
this.foo1()
}.apply(obj),100)
}
}
obj.foo2() // aaa
复制代码
call
var name = 'ahwgs'
var obj = {
name:'aaa',
foo1:function() {
console.log('this.name',this.name)
},
foo2:function() {
setTimeout(function() {
this.foo1()
}.call(obj),100)
}
}
obj.foo2() // aaa
复制代码
bind
var name = 'ahwgs'
var obj = {
name:'aaa',
foo1:function() {
console.log('this.name',this.name)
},
foo2:function() {
setTimeout(function() {
this.foo1()
}.bind(obj)(),100)
}
}
obj.foo2() // aaa
复制代码
注意:bind
与其余两种方法不一样,由于他返回的是一个函数,因此须要咱们()
去调用它。
null/undefined
做为bind/call/apply
的参数var name = 'ahwgs'
var obj = {
name:'aaa',
foo1:function() {
console.log('this.name',this.name)
},
foo2:function() {
setTimeout(function() {
this.foo1()
}.call(null),100)
}
}
obj.foo2() //Uncaught TypeError: this.foo1 is not a function
复制代码
若是使用null/undefined
做为参数的话,被调用的时候会被忽略,因此调用obj.foo2()
的时候this
指向的是全局对象,而全局对象中却没有foo2
这个函数,因此报错。
new
实例化新对象可看上述new
绑定实例
this
指的是容许的上下文环境,与后端语言不一样this
不是一成一变的,会随着环境而变化this
也不同this
的指向