这段时间一直看 JavaScript 高级程序设计, 然后就翻到 call,apply,bind 的介绍, 突然有 "社交恐惧症" 感, 不太想打招呼. 可我既然买来这本书, 还立志要成为一个优 (zhuang) 秀(bi)的前端开发者, 可不能被这些屈服了啊~
6af89bc8gw1f8ub3qow2tj203902gq2x.jpg
要知道 call,apply,bind 对很多人来说是一个比较晦涩的用法, 包括我, 以前很多次看到这个, 甚至常出现在面试题, 但我觉得这些太晦涩的, 就选择视而不见的. 正如 "今天你对我爱理不理, 明天我让你高攀不起" 这句话, 捂脸 ing, 但我一定要高攀得起 (会打自己的脸么) 好啦, 该正经了~
6af89bc8gw1f8t5k9h5tzj20jg0hrdgm.jpg
this
要理解 call,apply,bind, 首先要知道 this. 书上是这样介绍的:
this 引用的是函数执行的环境对象(当在网页的全局作用域中调用函数时, this 对象引用的就是 Windows)
好比说我有一个函数, 谁拿我的函数来调用, 我就认谁当爸爸, 爸爸就是 this. 我们来看看例子:
例 1:
- Windows.name="window";
- function fun(){
- let name="I am fun";
- console.log(this.name);
- }
- fun(); //Windows
打印出 "window", 而不是 "I am fun", 为什么呢? 关键在于 <font color="#dd0000">this</font>, 因为 fun()被调用的是全局对象 Windows, 所以 this 指向 Windows, 然后 Windows 的 name 的值就是 "window", 所以打印出 < font color="#dd0000">Windows</font>~然后我们再小小的改动下, 看例 2
例 2:
- Windows.name="window";
- function fun(){
- this.name="I am fun";
- console.log(this.name);
- }
- fun(); //I am fun
把 <font color="#dd0000">let</font> 改成 <font color="#dd0000">this.</font>, 此时 this 就是指向 Windows, 而 Windows 也有 name 的属性, 就被 this.name 的值覆盖了, 所以打印出 < font color="#dd0000">I am fun</font>~
这就是全局作用域调用函数的说法, 然后我们来看看对象调用函数, 什么叫对象调用函数, 首先要知道什么叫对象, 有基础的人应该知道了叭, 下面我们来看看例子:
例 1:
- Windows.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, 所以打印出 <font color="#dd0000">obj</font>~
假如 obj 没有 name, 会怎样呢?
例 2:
- obj={
- // name:'obj',
- fun:function(){
- console.log(this.name);
- }
- }
- obj.fun();//undefined
this 仍然指向 obj, 而 obj 没有 name 的属性, 所以打印出 <font color="#dd0000">undefined</font>~
这下可以明白了 this 的作用叭, 还是不明白的话, 看来我还得提高文笔水平和表达能力~没明白的话, 文章结尾会献出参考链接, 有些人写的比我好~
Unknown.jpg
apply,call,bind
看到这个, 别觉得头疼哈~别以为了有了 es6, 就不用这些了. 毕竟我们中国使用的技术情况, 你懂的~apply,call,bind 的作用就是改变 this, 嗯, 怎么讲呢? 先看看书上的说法~
用途都是在特定的作用域中调用函数, 实际上等于 < font color="#dd0000">设置函数体内 this 对象的值</font>
就好比说一个导游 (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 本身), 所以才会打印出 < font color="#dd0000"> 静安寺 </font>, 然后用 apply,this 的指向就发生变化, 改为指向 traveller 对象, 而 traveller 的 name 是 "城隍庙", 所以才会打印出 < font color="#dd0000"> 城隍庙</font>
然后我们再小小的改下, 如果旅者没说明要去哪儿:
例 2:
- let toristGuide={
- name:'静安寺',
- fun:function(){
- console.log('要去的地方:'+this.name);
- }
- }
- let traveller={
- }
- toristGuide.fun();//"要去的地方: 静安寺"
- toristGuide.fun.apply(traveller);// 要去的地方: undefined
嘿, 即使旅者没说啥, 也会根据旅者的打印出 < font color="#dd0000">undefined</font>, 毕竟 "顾客为上"
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
来源: http://www.jianshu.com/p/30a93ed2021b