this指向,并改变this指向

不同场景下的this指向问题

window

在js文件中直接打印this

console.log(this); // window 

浏览器中如下:
在这里插入图片描述

对象

1、首先创建一个平平无奇 对象,在方法中打印this:

const obj = {
    name: 'wang',
    age: 18,
    play: 'pingpang',
    baseInfo: function() {
        console.log(this); // obj对象
        console.log(this.name + '的年龄是' + this.age ); // wang的年龄是18
    }
}    
obj.baseInfo()

浏览器打印如下:
baseInfo

因此:调用对象的方法,this指向对象本身

2、下一步,我们改造上面obj,改变[‘play’]的值,并创造 一个新属性

const obj = {
    name: 'wang',
    age: 18,
    play: 'pingpang',
    likes: function() {
        this.play = 'basketball'
        console.log(this); // 更改后的 obj对象
        this.likeType = '有氧'
        console.log(this.name + ' like ' + this.play +'。并喜爱' + this.likeType); // wang like basketball。并喜爱有氧
    }
}

obj.likes()

打印如下:
likes
因此,this指向对象时,改变原有对象的key值,或创建一个新的key,此时this指向被改变之后的对象

3、上面我们测试了对象中的普通函数,如果换成 箭头函数 呢?继续改造obj:

const obj = {
    name: 'wang',
    age: 18,
    play: 'pingpang',
    test: () => {
        console.log(this); // window 对象
        this.testA = '语文'
        console.log(this.name + ' 喜欢的课程是' + this.testA); //   喜欢的课程是语文
    }
}

obj.test()

打印如下:
test
因此:调用对象的箭头函数方法,this的指向是window,不能再如第二步改变 play 的值一样改变 name,所以上面打印不是 “wang喜欢的课程是语文” 而是 “喜欢的课程是语文”

4、如果我们进一步改造obj的方法,测试下在setTimeout里的this指向呢?

const obj = {
    name: 'wang',
    age: 18,
    play: 'pingpang',
    testSetTimeout: function() {
    	
         setTimeout(function() {
            console.log('setTimeout(function(){})=======', this)  // window
            console.log(this.play)
        },5)
        
        setTimeout(() => {
            console.log('setTimeout(()=>{})=======', this)  // obj
            console.log(this.play)
        },10)
    }
}

obj.testSetTimeout()

打印如下:
testSetTimeout
这里的结果似乎有些出乎意料~
调用对象的方法:
setTimeout里回调是普通函数时,this的指向是window
setTimeout里回调是箭头函数时,this的指向是对象本身

函数

创建一个普通函数

function testFunc(){
    console.log(this);
    this.num1 = 20;
    console.log('this.num1: ', this.num1); // 20
}
// 调用1
testFunc()  // window

// 调用2
let test2 = testFunc()
test2()  // window

打印如下:
func
因此,在普通函数中,this指向window

1、创建一个类

class fatherObj {
    constructor(name, age){
        this.name = name
        this.age = age
    }
    showText(){
        console.log(this) // fatherObj
        return '姓名是:' + this.name + ',年龄是:' + this.age
    }
}
const fatherObj_C = new fatherObj('wang', 18)

console.log(fatherObj_C.showText()) // 姓名是:wang,年龄是:18

打印如下:
fatherclass
因此,在类里使用this,this指向类本身

2、进一步改变类的方法 showText,我们来改变name的值来查看变化

class fatherObj {
    constructor(name, age){
        this.name = name
        this.age = age
    }
    showText(){
        this.name = '小王'
        console.log(this) // 新fatherObj
        return '姓名是:' + this.name + ',年龄是:' + this.age
    }
}
const fatherObj_C = new fatherObj('wang', 18)

console.log(fatherObj_C.showText()) // 姓名是:小王,年龄是:18

打印如下:
在这里插入图片描述
由此可见,this指向的是更新之后的类

3、保留第2步的fatherObj类,我们进一步测试,创建它的子类

class sonObj extends fatherObj {
    constructor(name, age, sex){
        super(name, age)
        this.sex = sex
    }
    showMore(){
        console.log(this)
        return super.showText()+' ,性别是:' + this.sex
    }
}
const son_C = new sonObj("xiaowang", 5, 'nv')

console.log('son_C: ', son_C.showMore());

打印如下:
son
因此,在类里,this始终指向的是类本身。也很清晰看到,子类sonObj的原型上是父类fatherObj

改变this的指向

前置代码,先码个对象和函数吧~

const testFunc = function(params1, params2) {
    console.log(this)
    console.log('params1: ', params1);
    console.log('params2: ', params2);
    return {name: 'wang'}

}
const testObj = {
    p1: 11,
    p2: 22,
    showThis(params){
        console.log('showThis=====', this, params)
    }
}

如果我们调用testFunc()testObj.showThis() ,this的指向应分别是 windowtestObj吧。
下面,我们来看看改变this的指向~

call 、bind 、 apply 这三个函数的第一个参数都是 this 的指向对象

call

1、改变testFunc的this指向:


testFunc.call(testObj, 3,4) 
// {p1: 11, p2: 22, showThis: ƒ}
// params1:  3
// params2:  4

testFunc.call(testObj, 'test2')
// {p1: 11, p2: 22, showThis: ƒ}
// params1:  test2
// params2:  undefined

testFunc.call(testObj)
// {p1: 11, p2: 22, showThis: ƒ}
// params1:  undefined
// params2:  undefined

testFunc.call() 
// window
// params1:  undefined
// params2:  undefined

testFunc.call(null)
// window
// params1:  undefined
// params2:  undefined

testFunc.call(undefined) 
// window
// params1:  undefined
// params2:  undefined

testFunc.call(2) 
// Number{2}
// params1:  undefined
// params2:  undefined

2、改变testObj的指向

testObj.showThis.call(testFunc())
// Window {}
// params1:  undefined
// params2:  undefined
// showThis===== {name: 'wang'} undefined


testObj.showThis.call(testFunc(), 18)
// showThis===== {name: 'wang'} 18

apply

apply 和 call 的区别在于,apply的参数要放在数组里传过去,call的参数直接放进去

testFunc.apply(testObj, [1,2]) 
// {p1: 11, p2: 22, showThis: ƒ}
// params1:  1
// params2:  2

testFunc.apply([1,2])
// [1, 2]
// params1:  undefined
// params2:  undefined

testFunc.apply(undefined)
// Window {}
// params1:  undefined
// params2:  undefined

bind

bind 除了返回是函数需要自调用外,它的参数和 call 一样。

testFunc.bind(testObj, 3, 4)()
// {p1: 11, p2: 22, showThis: ƒ}
// params1:  3
// params2:  4

参考文章:
1、this的指向
2、call、apply、bind的用法

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值