资讯专栏INFORMATION COLUMN

ES5 call,apply,bind方法总结(包括理解this的指向问题)

nanchen2251 / 1966人阅读

总结call,apply,bind方法的理解使用和区别。

call,apply,bind这三个方法在JavaScript中是用来改变函数调用的this指向。那么改变函数this指向有什么用呢?我们先来看一段代码

var a= {
    name:"harden",
    fn:function () {
        console.log(this.name);
    }
}
var b = a.fn;
a.fn();//harden
b();//undefined

调用a.fn方法后得到了harden,但在b方法中我想得到harden,为什么却是undefined呢?原因是方法在执行的时候才能确定this到底指向谁,实际上this指向的是最终调用函数的对象。这里当b执行时,实际是window调用了fn函数,那么fn中的this就指向window。
在开始讲call,apply,bind方法前,一起来总结一下this的指向问题。

理解JavaScript中的this指向问题。

总体来说this指向可以概括为一句话:this指向在函数的定义时是不确定的,只有函数执行时才能确定this到底指向谁,实际上this的最终指向的是那个调用它的对象。但是这个说法在函数被很多对象包裹的时候并不成立,请看下面例子。
简单来说就是:谁(哪个对象)调用的这个函数,那么这个函数中的this就指向这个对象。

例一

 function a(){
        var name= "harden";
        console.log(this.name); //undefined
        console.log(this); //Window
    }
    a();

因为this最终指向调用他的对象,在上述代码中其实是widow触发的这个方法,那么this就指向window,window中并没有定义a,那么就打印出undefined。
例二:

var a = {
    name:"harden",
    fn:function() {
        console.log(this.name);//harden
        console.log(this);//指向a(可以自己跑一下)
    }
}
a.fn()

这里的this指向a,因为这里的fn函数是通过a.fn()执行的,那么this自然指向a。
说到这我就有疑问了,如果我用 window.a.fn()执行函数,this不就指向window了吗?然后并不是这样的,请看下一个例子。补充一点:window是js的全局对象。
例三:

var a = {
    name:"harden",
    b:{
        name:"james",
        fn:function() {
            console.log(this.name);//james
            console.log(this);//指向b
        }
    }
}
a.b.fn()

我们看到最终是a调用的方法,那为什么this会指向b呢?现在总结三句话,来完全理解this的指向问题:

情况一:如果一个函数中有this,但是它没有被上一级的对象所调用,那么this指向的就是window(除去严格模式外)。
情况二:如果一个函数中有this,这个函数有被上一级的对象所调用,那么this指向的就是上一级的对象。
情况三:如果一个函数中有this,这个函数中包含多个对象,尽管这个函数是被最外层的对象所调用,this指向的也只是它上一级的对象,例子3可以证明。

构造函数中的this:

 function Fn(){
       this.name = "harden";
   }
   var a = new Fn();
   console.log(a.name); //harden

这里的a可以点出name,因为new关键字会改变this的指向。为什么new关键字会改变this呢,我自己有两种看法:
1.在new的过程中会创建一个实例对象,通过apply等方法 通过 Fn.apply({}) 使this指向这个空对象,最后把fn方法中的材料加工完后返回给a。

当this遇到return的时候:

function fn()  
   {  
       this.user = "harden";  
       return {};  
   }
   var a = new fn;  
   console.log(a.user); //undefined
   
   function fn()  
   {  
       this.user = "harden";  
       return function(){};
   }
   var a = new fn;  
   console.log(a.user); //undefined
   
   function fn()  
   {  
       this.user = "harden";  
       return 1;
   }
   var a = new fn;  
   console.log(a.user); //harden
   
   function fn()  
   {  
       this.user = "harden";  
       return undefined;
   }
   var a = new fn;  
   console.log(a.user); //harden

总结一下:如果返回值是一个对象,那么this指向的就是那个返回的对象,如果返回值不是一个对象那么this还是指向函数的实例。还有一点就是返回null,null也是对象,但是因为他的特殊性,返回后this还是指向函数本身的实例。理解JavaScript中的指向问题
理解完JavaScript中的指向问题,那么回到正题:

call,apply,bind方法总结

1.call

a = { name: "harden" }
function b () {
    console.log(this.name);
}
b.call(a);//harden
b()//undefined

b.call(a)用字面意思来讲就是:把函数b添加到对象a的环境中,使函数中的this指向对象a。
call与apply不同的地方就是传参不同。
2.apply

a = { name: "harden" }
function b (data1,data2) {
    console.log(data1,data2);
}
b.call(a,"a1","a2");//a1 a2
b.apply(a,["a1","a2"]);//a1 a2

3.bind

a = { name: "harden" }
    function b () {
        console.log(this.name);
    }
    b.bind(a);//不会执行函数
    var aaa = b.bind(a);
    aaa()//harden

bind不会立即调用函数,是把函数返回,bind通常用它来指定回调函数的this。
关于call, apply, bind方法的区别与内部实现

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/104908.html

相关文章

  • 从一道面试题,到“我可能看了假源码”

    摘要:返回的绑定函数也能使用操作符创建对象这种行为就像把原函数当成构造器。同时,将第一个参数以外的其他参数,作为提供给原函数的预设参数,这也是基本的颗粒化基础。 今天想谈谈一道前端面试题,我做面试官的时候经常喜欢用它来考察面试者的基础是否扎实,以及逻辑、思维能力和临场表现,题目是:模拟实现ES5中原生bind函数。也许这道题目已经不再新鲜,部分读者也会有思路来解答。社区上关于原生bind的研...

    Carson 评论0 收藏0
  • 从一道面试题,到“我可能看了假源码”

    摘要:返回的绑定函数也能使用操作符创建对象这种行为就像把原函数当成构造器。同时,将第一个参数以外的其他参数,作为提供给原函数的预设参数,这也是基本的颗粒化基础。 今天想谈谈一道前端面试题,我做面试官的时候经常喜欢用它来考察面试者的基础是否扎实,以及逻辑、思维能力和临场表现,题目是:模拟实现ES5中原生bind函数。也许这道题目已经不再新鲜,部分读者也会有思路来解答。社区上关于原生bind的研...

    rockswang 评论0 收藏0
  • 从一道面试题,到“我可能看了假源码”

    摘要:返回的绑定函数也能使用操作符创建对象这种行为就像把原函数当成构造器。同时,将第一个参数以外的其他参数,作为提供给原函数的预设参数,这也是基本的颗粒化基础。 今天想谈谈一道前端面试题,我做面试官的时候经常喜欢用它来考察面试者的基础是否扎实,以及逻辑、思维能力和临场表现,题目是:模拟实现ES5中原生bind函数。也许这道题目已经不再新鲜,部分读者也会有思路来解答。社区上关于原生bind的研...

    jlanglang 评论0 收藏0
  • bind()、call()、apply()理解及用法

    摘要:首先,我们判断是否存在方法,然后,若不存在,向对象的原型中添加自定义的方法。指向调用它的对象。总之三个的使用区别都是用来改变函数的对象的指向的第一个参数都是要指向的对象都可以利用后续参数传参是返回对应函数,便于稍后调用,是立即调用 apply和call都是为了改变某个函数运行时的上下文而存在的(就是为了改变函数内部this的指向),Function对象的方法,每个函数都能调用; 使用a...

    hoohack 评论0 收藏0
  • 可能遇到假面试题:不用callapply方法模拟实现ES5bind方法

    摘要:来自朋友去某信用卡管家的做的一道面试题,用原生模拟的方法,不准用和方法。他们的用途相同,都是在特定的作用域中调用函数。不同之处在于,方法传递给调用函数的参数是逐个列出的,而则是要写在数组中。 本文首发我的个人博客:前端小密圈,评论交流送1024邀请码,嘿嘿嘿?。 来自朋友去某信用卡管家的做的一道面试题,用原生JavaScript模拟ES5的bind方法,不准用call和bind方法。 ...

    李世赞 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<