从call、apply、bind引发的思考

这段时间一直看JavaScript高级程序设计,然后就翻到call、apply、bind的介绍,突然有“社交恐惧症”感,不太想打招呼。可我既然买来这本书,还立志要成为一个优(zhuang)秀(bi)的前端开发者,可不能被这些屈服了啊~

6af89bc8gw1f8ub3qow2tj203902gq2x.jpg

要知道call、apply、bind对很多人来说是一个比较晦涩的用法,包括我,以前很多次看到这个,甚至常出现在面试题,但我觉得这些太晦涩的,就选择视而不见的。正如“今天你对我爱理不理,明天我让你高攀不起”这句话,捂脸ing,但我一定要高攀得起(会打自己的脸么)好啦,该正经了~

6af89bc8gw1f8t5k9h5tzj20jg0hrdgm.jpg

this

要理解call、apply、bind,首先要知道this。书上是这样介绍的:

this引用的是函数执行的环境对象(当在网页的全局作用域中调用函数时,this对象引用的就是window)

好比说我有一个函数,谁拿我的函数来调用,我就认谁当爸爸,爸爸就是this。我们来看看例子:

例1:

window.name="window";
function fun(){
    let name="I am fun";
    console.log(this.name);
}
fun(); //window

打印出“window”,而不是“I am fun”,为什么呢?关键在于 this,因为fun()被调用的是全局对象window,所以this指向window,然后window的name的值就是“window”,所以打印出window~然后我们再小小的改动下,看例2

例2:

window.name="window";
function fun(){
    this.name="I am fun";
    console.log(this.name);
}
fun(); //I am fun

let 改成 this.,此时this就是指向window,而window也有name的属性,就被this.name的值覆盖了,所以打印出I am fun

这就是全局作用域调用函数的说法,然后我们来看看对象调用函数,什么叫对象调用函数,首先要知道什么叫对象,有基础的人应该知道了叭,下面我们来看看例子:

例1:

window.name="window";
let obj={
    name:'obj'
};//这就是对象
function fun(){
    console.log(this.name);
}
obj.fun=fun;
obj.fun(); //obj

建立一个obj对象,有一个属性name,然后把全局的fun函数指向obj,注意这里并没有加(),因为如果加()就是全局对象直接调用函数,自己可以试试。指向obj后,这就相当于

obj={
    name:'obj',
    fun:function(){
        console.log(this.name);//obj
    }
}

此时this就是obj,而obj的name是obj,所以打印出 obj

假如obj没有name,会怎样呢?
例2:

obj={
    // name:'obj',
    fun:function(){
        console.log(this.name);
    }
}
obj.fun();//undefined

this仍然指向obj,而obj没有name的属性,所以打印出 undefined

这下可以明白了this的作用叭,还是不明白的话,看来我还得提高文笔水平和表达能力~没明白的话,文章结尾会献出参考链接,有些人写的比我好~

Unknown.jpg

apply、call、bind

看到这个,别觉得头疼哈~别以为了有了es6,就不用这些了。毕竟我们中国使用的技术情况,你懂的~apply、call、bind的作用就是改变this,嗯,怎么讲呢?先看看书上的说法~

用途都是在特定的作用域中调用函数,实际上等于设置函数体内this对象的值

就好比说一个导游(touristGuide)有一个旅游的计划,但只有静安寺,然后旅者(traveller)不想去静安寺,就想去城隍庙,在js上一般做法的就是再建立一个新的对象,名字改为“城隍庙”,这不是累死导游么?这时候apply、call就用上了,在原本上的计划(必须在函数上,因为函数才具有apply、call的属性),引用旅者的对象,this就指向旅者想要的地方,这就可以了,导游表示爽歪歪的,下面看看例子:

例1:

let toristGuide={
    name:'静安寺',
    fun:function(){
        console.log('要去的地方:'+this.name);
    }
}
let traveller={
    name:'城隍庙',
}
toristGuide.fun();//"要去的地方:静安寺"
toristGuide.fun.apply(traveller);//“要去的地方:城隍庙”

touristGuide.fun()中的this指向自己(就是toristGuide本身),所以才会打印出静安寺,然后用apply,this的指向就发生变化,改为指向traveller对象,而traveller的name是“城隍庙”,所以才会打印出城隍庙

然后我们再小小的改下,如果旅者没说明要去哪儿:
例2:

let toristGuide={
    name:'静安寺',
    fun:function(){
        console.log('要去的地方:'+this.name);
    }
}
let traveller={
}
toristGuide.fun();//"要去的地方:静安寺"
toristGuide.fun.apply(traveller);//要去的地方:undefined

嘿,即使旅者没说啥,也会根据旅者的打印出undefined,毕竟“顾客为上”

apply和call作用一样,就是接受的第二个参数不同

apply

接受两个参数,第一个参数是在其中运行函数的作用域,第二个参数是数组,也可以是arguments对象,看例子,根据上面的例子改动下,加个参数:
例1:

let toristGuide={
    name:'静安寺',
    fun:function(a,b){
        console.log('想要做什么:'+a,b);
    }
}
let traveller={
    name:'城隍庙',
}
toristGuide.fun('吃','玩');//想要做什么:吃,玩
toristGuide.fun.apply(traveller,['拍照','吃美食']);//想要做什么:拍照,吃美食

call

第一个参数和上面的一样,而第二个参数不同,就是直接传递给函数,看下面的例子:
例1:

let toristGuide={
    name:'静安寺',
    fun:function(a,b){
        console.log('想要做什么:'+a,b);
    }
}
let traveller={
    name:'城隍庙',
}
toristGuide.fun('吃','玩');//想要做什么:吃,玩
toristGuide.fun.call(traveller,'拍照','吃美食');//想要做什么:拍照,吃美食

bind

bind和上面用途一样的,也是改变this的指向,但用法不一样的,书上的说法是:

这个方法会创建一个函数

嗯,好像不太理解的,看例子:

例1:

let toristGuide={
    name:'静安寺',
    fun:function(a,b){
        console.log('想要做什么:'+a,b);
    }
}
let traveller={
    name:'城隍庙',
}
toristGuide.fun.bind(traveller,'拍照','吃美食');

改为bind后,结果没打印出什么的,反而是打印出函数体,然后根据书上的说法和例子,就加上个()

toristGuide.fun.bind(traveller,'拍照','吃美食')();//想要做什么:拍照,吃美食

这才恍然大悟,原来这就是用法的。

这就是apply、call、bind的用法,童鞋们可能看就懂的,但自己做起来却觉得困惑的,我只能说多看多做,就熟能生巧了,祝早日征服这些~(手动滑稽)

到此为止了,好累呀~求点赞~

献上参考链接:
1、https://juejin.im/post/59bfe84351882531b730bac2#heading-0 这个比较详细的,不懂的话,可以再看看这个
2、https://www.cnblogs.com/coco1s/p/4833199.html

你可能感兴趣的:(从call、apply、bind引发的思考)