JavaScript之一篇文章学会this和call、apply、bind

引言

为什么要用this,我们举个栗子:

北京古称燕京、北平,北京是中华人民共和国的首都,北京有长城、故宫等名胜古迹,北京是中国的政治经济中心。

这句话讲述主语是不是有点啰嗦?

替换成成this后的句子:

北京古称燕京、北平,这里是中华人民共和国的首都,这里有长城、故宫等名胜古迹,这里是中国的政治经济中心。

我们看看下面两组代码块:

 var person = {
   name:'小明',
   bobby:'打篮球',
   info:function(){
      console.log(`大家好,我是${person.name},我喜欢${person.bobby}`)
    }
}
person.info()
 var person = {
   name:'小明',
   bobby:'打篮球',
   info:function(){
      console.log(`大家好,我是${this.name},我喜欢${this.bobby}`)
    }
}
person.info()

 如果对象名很长的话,就会造成代码的冗余,所以使用this替换后的代码,变得简洁干净也便于阅读。

概念

大家最关心的应该是this的指向问题了,先给大家罗列几种常见的指代对象的方法:

this指向

调用主体指向
普通函数

window

对象该对象
定时器、延时器window
call、apply该对象
事件绑定绑定的DOM元素
构造函数该实例

笔者用一种有趣的方法教大家记忆一下:

普通函数

有人问小明,有没有女朋友,小明说有,但是没能说出女朋友是谁,所以就默认全世界中的某个女生是他女朋友,所以this指向全局,也就是window

function fn(){
   console.log(this) //window
}
fn()

对象

过了一段时间,又有人问小明有没有女朋友,这次小明不但说有,而且还能准确地说出女朋友的信息。当我们调用对象的方法时,就会出现隐式绑定,因为info方法是在girl里面的,所以this指向girl对象

var girl = {
  name:"小红",
  age:"18",
  hobby:"写代码",
  info:function fn(){
      console.log(`我是小明的女朋友${this.name},今年${this.age}岁,喜欢${this.hobby}`)
      console.log(this)  //girl
   }
}
girl.info()

call、apply 

此时因为一些矛盾,小明跟小红分手了,然后小明换了个新女友小白,并对公布了她的身份。apply和call的用法相似,都是拥有改变this指向的魔法,后面会有介绍。所以this指向new_girl对象

var girlName = {
   name:"小红",
   info:function fn(){
   console.log(`我是小明的女朋友${this.name}`)
   console.log(this)  //girl1
   }
}
var new_girl = {
    name:"小白"
}
girlName.info.call(new_girl)

构造函数

所谓浪子回头金不换,小明最终还是幡然醒悟,回到了小红的身边,并且扯证结婚。构造函数就像契约一样,把两人紧紧的捆绑在一起,所以this最终指向构造函数的实例xiaohong

function Lover(name){
   this.name = name
   this.say = function(){
       console.log("我跟"+name+"结婚啦!")
       console.log(this) //xiaohong
  }
}
var name = "小白"
var xiaohong = new Lover("小红")
xiaohong.say()

还有定时器和事件绑定的指向的故事就不讲了,总结来说this的指向浓缩成一句话:

谁调用就指向谁

注意:箭头函数没有自己的this,它的this指向函数上层作用域的this

var name = "a"
var obj = {
    name:"b",
    fn:()=>{
        console.log(this.name)
    }
}
obj.fn()//a

了解完基础概念以后整点题目巩固一下(答案在所有题目的后面)

第一题:

function a(){
   console.log(this)
   function b(){
      console.log(this)
      function c(){
         console.log(this)
      }
      c()
    }
    b()
}
a()

第二题:

var name = "a"
function fn1(){
    console.log(this.name)
}
var A = {
    name:"b",
    fn2:function(){
       console.log(this.name)
    },
    B:{
       name:"c",
       fn3:function(){
           console.log(this.name)
        }
     },
    fn4:fn1
}
A.fn2()
A.B.fn3()
A.fn4()

第三题:

var name = "a"
function fn1(){
    var name ="b"
    console.log(this.name)
}
function fn2(x){
    return x()
}    
var T = {
    name:"c",
    fn3:function(){
        console.log(this.name)
    },
    fn4:function(){
        return function(){
            console.log(this.name)
        };
    }
}
var B1 = T.fn3
T.fn1 = fn1
var B2 = T.fn4()
fn1()
B1()
T.fn1()
fn2(T.fn3)
B2()

答案:

1.window window window

2.b c b

3.a a c a a

call、apply和bind

上述三个讲明白一个,其他那两个大家也跟着学会了

前面已经讲到,call、apply有一个两个强大的功能:

1.可以调用函数

2.改变this的指向

先那call说事,举个例子给大家:

小猫和小狗出去玩,小狗带了充电宝且手机还有80%电,小猫的手机只有10%的电量,但是小猫没有充电宝该怎么办呢?当然是问小狗借啦!

由于cat对象没用charge方法,所以需要通过call方法去改变this的指向,指向cat本身,所以就能成功调用charge方法。

call(对象,值)//call函数第一个参数为你需要this指向的那个对象,第二个参数是你要传的参数

let dog = {
     phone:80,
     charge:function(level){
     this.phone= level           
     }
}
let cat = {
    phone:10
}
dog.charge.call(cat,100)
console.log(cat.phone)

 

那apply这个方法怎么用呢?其实很简单,跟call差不多,只不过传递的参数需要以数组的形式传递

let dog = {
     phone:80,
     charge:function(level1,level2){
        this.phone1 = level1           
        this.phone2 = level2         
      }
}
let cat = {
    phone1:10,
    phone2:5
}
dog.charge.apply(cat,[100,90])
console.log(cat.phone1,cat.phone2)

 dog.charge.apply(cat,[100,90])   等价于  dog.charge.call(cat,100,90)

bind在这里就特殊一点,因为他不像call和apply一样,可以调用函数,bind方法会把函数作为返回值返回出来,然后需要一个参数去接收返回值再调用。

let fn = dog.charge.bind(cat,100,90)
fn()

类比记忆:

call和bind接收参数的方法一致

call和apply都可以调用函数

今天你学废了吗?

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值