浅析JS中的this

JS中的this

为什么要使用this

关于什么是this,首先要知道使用this会解决什么问题。
我们先创建一个对象:

let obj={
    name:'小白',
    dogName:function(){
        console.log(obj.name)  //小白
    }
}

之后我们调用obj中的dogName方法,就可以使用这个函数,打印出obj.name。但是如果声明了一个函数,要在别的对象中引用该函数的方法,就会发现问题所在,因为会发现这个dogName中的name始终无法指定,除非单独写入对象中,再依次修改。

let dogName=function(){
    console.log(`你好,我叫`+   name?  )  //这里的name到底是谁的name
}
let dog2={
    name:'小花'
    dogName:dogName
}

如果创建一个class类,那就更能够理解这一点问题:

class Dog{
    constructor(name){
        this.name=name
        //这里的name是new强行指定的
    }
    dogName(){
        console.log(???)
    }
}

这里就更写不出来了,因为你不知道未来创建的对象到底叫什么名字,因此不可能采用对象的引用,那么如何拿到name呢?
这时候就可以用this了(当然也可以用形参来代替this,但是这样引用的时候就会变得很丑)

class Dog{
    constructor(name){
        this.name=name
        //这里的name是new强行指定的
    }
    dogName(){
        console.log('这条狗的名字叫'+this.name)
    }
}

这样当你在用Dog类来实例化一个新对象时,使用这个方法,该方法就会自动的将对象的参数以this的方式传入函数里。这样一来,就可以不用知道对象的名字,也可以在类中添加一个新方法了。

this到底指向谁?

关于this的指向,每个人都有每个人的说法,我自己的理解是:谁调用了这个方法,那么this就指向谁。
来两道面试题:

var name='小白';
function special(){
    console.log('姓名:'+this.name);
}
var girl={
    name:'小红',
    detail:function(){
        console.log('姓名:'+this.name);
    },
    woman:{
        name:'小黄',
        detail:function(){
            console.log('姓名:'+this.name);
        },
    }
    special:special
}

girl.detail();  //小红
girl.woman.detail();  //小黄
girl.special();  //小红

解析:
girl.detail()为什么打印出小红?
因为此时调用的是girl中的detail方法,那么对于这个方法来说,它是girl中的方法,那么此时的this也是指向的girl中的name。

girl.woman.detail()为什么打印出小黄?
因为此时调用的是girl中woman对象中的一个方法detail,那么对于这个方法来说,他是处于woman中的一部分,那么它的this就是指向woman中的name。

girl.special()为什么打印出小红?
因为此时调用的是girl中的special方法,girl.special采用了之前声明的special函数,文中可以等价于将special函数的内容全部搬进girl对象中,那么此时调用special,就是在girl对象中调用special(这句话好像重复了。。),那么这个方法中的this就自然是指向girl中的name了。

还有下一道题:

var name='小红'
function a(){
    var name = '小白'
    console.log(this.name)
}
function d(i){
    return i()
}
var b = {
    name:'小黄',
    detail:function(){
        console.log(this.name)
    },
    bibi:function(){
        return function(){
            console.log(this.name)
        }
    }
}
var c = b.detail
b.a = a
var e = b.bibi()

a();  //小红
c();  //小红
b.a(); //小黄
d(b.detail); //小红
e(); //小红

解析:
a()为什么打印出小红?
因为当我们调用a函数时,此时a函数是一个全局函数,也就是说它的this也是指向全局的,那么在全局中的name,只有在全局作用域定义的var name='小红'了。

c()为什么打印出小红?
因为此时c赋值了b中的detail方法,那么此时的c就是b中的detail方法,但只是内容相同,使用上没有任何关系,那么这时候c就与a一样,是一个全局函数,那么this也是指向全局的name=小红了。(赋值时b.detail没有调用,只是将方法给了c,如果是c=b.detail(),那么此时的c就是b.detail调用后的值–undefined)

b.a()为什么打印出小黄?
因为此时在b中增加了一个方法a,那么调用b中的方法a,a的this就指向了b中的name,也就是小黄了。

d(b.detail)为什么打印出小红?
首先要明白d函数是什么意思,d函数的意思是,接受一个参数,然后返回这个参数的调用,那么我们就可以把b.detail这个函数单做参数传入d中,然后就会调用b.detail这个参数了,那么调用的这个参数与c一样,只是方法,调用时与b.detail没有任何关系,那么d函数是一个全局的函数,那么this也就会指向全局的name小红了。

e()为什么打印出小红?
此时e被赋值了b.bibi(),此时b.bibi被调用了,那么调用后的bibi会返回一新的函数,那么此时的e就是等于这个新的函数,那么调用e就是调用这个新函数,由于e是全局的函数,那么this就是指向全局的name了。

好好思考这两个面试题,就可以大概想明白this的指向。上题中有个很简单的规律,那就是看调用时函数点前面的是什么,那么this就是什么,什么意思呢?比如a()的this就是window,也就是全局;b.a()的this就是b,看函数最后被调用前点前面的对象是什么,那么this就是什么。

绑定this指向

JS中提供了三种能够绑定this的指向,分别是call、apply和bind。
他们的区别在于call和apply,只要使用,函数就会被调用,bind不会直接调用,而是会生成一个新函数,需要去主动调用这个新函数。
call和apply的区别在于,call和bind传入的参数是多个单独的变量,而apply传入的参数是一个数组。
他们的共同点还有一个,就是传入参数的第一个值就是需要指定给函数的this值。
语法如下:

function.call(thisArg, arg1, arg2, ...)
function.apply(thisArg, argsArray)
function.bind(thisArg[, arg1[, arg2[, ...]]])
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值