this
https://juejin.im/post/6844903496253177863
this 的指向
this永远指向最后调用它的那个对象
例1:
var name = "windowsName"
function a() {
var name = "Cherry"
console.log(this.name) // windowsName
console.log("inner:" + this) // inner:Window
}
a()
console.log("outer:" + this) // outer:Window
最后调用 a 的地方 a(),前面没有调用的对象 那么就是全局对象window,相当于是window.a()。(如果使用严格模式,全局对象是 undefined,会报错)
例2:
var name = "windowsName"
var a = {
name:"Cherry",
fn:function() {
console.log(this.name) // Cherry
}
}
a.fn()
函数fn是对象a调用的,所以打印的值就是a中的name的值。
例3:
var name = "windowsName"
var a = {
name:"Cherry",
fn:function() {
console.log(this.name) // Cherry
}
}
window.a.fn()
这里打印Cherry的原因也是因为“this永远指向最后调用它的那个对象”最后调用他的对象仍然是对象a
例4
var name = "windowsName"
var a = {
// name:"Cherry",
fn:function() {
console.log(this.name) // undefined
}
}
window.a.fn()
调用fn的是a对象,也就是说fn的内部的this是对象a,而对象a中并没有对name进行定义,就算a中没有name这个属性,也不会继续向上一个对象寻找 this.name,而是直接输出 undefined。
例5
var name = "windowsName"
var a = {
name:null,
fn:function() {
console.log(this.name) // windowsName
}
}
var f = a.fn
fn()
这里虽然将a对象的fn方法赋值给变量f了,但是没有调用,所以fn()最后仍然是被window调用的。所以this的指向也就是window。
例5
var name = "windowsName"
var a = {
var name = 'Cherry'
innerFunction()
function innerFunction() {
console.log(this.name) // windowsName
}
}
fn()
改变 this 的指向
- 使用es6的箭头函数
- 在函数内部使用 _this = this
- 使用 apply、call、bind
- new 一个实例化对象
例7:
var name = "windowsName"
var a = {
name:"Cherry"
func1:function() {
console.log(this.name)
}
func2:function() {
setTimeout( function() {
this.func1()
},100)
}
}
a.func2() // this.func1 is not a function
在不使用箭头函数情况下是会报错的,因为最后调用 setTimeout 的对象是 window,但是在 window 中并没有 func1 函数
箭头函数
箭头函数的this始终指向函数定义时的this,而非执行时。箭头函数中没有this绑定,必须通过查找作用域链来决定其值,如果箭头函数被非箭头函数包含,则this绑定在最近一层非箭头函数的this,否则,this为undefined
例8:
var name = "windowsName"
var a = {
name:"Cherry"
func1:function() {
console.log(this.name)
}
func2:function() {
setTimeout( () => {
this.func1()
},100)
}
}
a.func2() // Cherry
在函数内部使用 _this = this
先将调用这个函数的对象保存在变量 _this 中,然后在这个函数中都使用 _this,这样 _this 就不会改变了
例9:
var name = "windowsName"
var a = {
name:"Cherry"
func1:function() {
console.log(this.name)
}
func2:function() {
var _this = this
setTimeout( function() {
_this.func1()
},100)
}
}
a.func2() // Cherry
在 func2 中先设置 _this = this,这里的this 是调用func2 的对象a,为了防止在 func2 中的 setTimeout 被 window 调用而导致在 setTimeout 中的 this 为 window。将this(指向变量a)赋值给一个变量 _this,这样在 func2中使用_this 就指向对象a了。
使用apply、call、bind
例 10:
// 使用apply
var a = {
name:"Cherry"
func1:function() {
console.log(this.name)
}
func2:function() {
setTimeout( function() {
this.func1()
}.apply(a),100)
}
}
a.func2() // Cherry
例 11:
// 使用call
var a = {
name:"Cherry"
func1:function() {
console.log(this.name)
}
func2:function() {
setTimeout( function() {
this.func1()
}.call(a),100)
}
}
a.func2() // Cherry
例 12:
// 使用bind
var a = {
name:"Cherry"
func1:function() {
console.log(this.name)
}
func2:function() {
setTimeout( function() {
this.func1()
}.bind(a),100)
}
}
a.func2() // Cherry
apply和call的区别
基本类似 传参不同 call方法接收的是若干个参数列表,而apply接受的是一个包含多个参数的数组
例 13:
var a = {
name:"Cherry"
fn:function(a,b){
console.log(a+b)
}
}
var b = a.fn
b.apply(a,[1,2]) // 3
例 14:
var a = {
name:"Cherry"
fn:function(a,b){
console.log(a+b)
}
}
var b = a.fn
b.call(a,1,2) // 3
bind和apply、call的区别
bind()方法创建一个新的函数,当被调用时,将其this关键字设置为提供的值,在调用新函数时,在任何提供之前提供一个给定的参数序列。所以bind是创建一个新的函数,必须手动调用。
var a = {
name:"Cherry"
fn:function(a,b){
console.log(a+b)
}
}
var b = a.fn
b.bind(a,1,2)() // 3