call、apply、bind的理解与区别

在JavaScript中,call、apply和bind是Function对象自带的三个方法,都是为了改变函数体内部 this 的指向。

bind 是返回对应 函数,便于稍后调用;apply 、call则是立即调用 

call 是把参数按顺序传递进去,而 apply 则是把参数放在数组 里。


类(伪)数组使用数组方法

Javascript中存在一种名为伪数组的对象结构。比较特别的是 arguments 对象,还有像调用 getElementsByTagName , document.childNodes 之类的,它们返回NodeList对象都属于伪数组。不能应用 Array下的 push , pop 等方法

vardivElements = document.getElementsByTagName('div');//虽然 divElements 有length属性,但是他是一个伪数组,不能使用数组里面的方法

Array.isArray(divElements);

vardomNodes = Array.prototype.slice.call(document.getElementsByTagName('div'));// 将数组对象Array里的this指向伪数组document.getElementsByTagName('div'),

//slice() 方法可从已有的数组中返回选定的元素,不传参数是,返回整个数组

Array.isArray(domNodes);// true


验证一个对象的类型可以用:

Object.prototype.toString.call(obj)

原因:

这是因为toString为Object的原型方法,而Array ,function等类型作为Object的实例,都重写了toString方法。不同的对象类型调用toString方法时,根据原型链的知识,调用的是对应的重写之后的toString方法(function类型返回内容为函数体的字符串,Array类型返回元素组成的字符串.....),而不会去调用Object上原型toString方法(返回对象的具体类型),所以采用obj.toString()不能得到其对象类型,只能将obj转换为字符串类型;因此,在想要得到对象的具体类型时,应该调用Object上原型toString方法。


在 Javascript 中,多次bind()是无效的。更深层次的原因,bind()的实现,相当于使用函数在内部包了一个call / apply,第二次bind()相当于再包住第一次bind(),故第二次以后的bind是无法生效的。

当传入参数的个数是不确定的时候,这个时候就可以考虑使用 apply 或者 call,注意这里传入多少个参数是不确定的,所以使用apply是最好的

functionlog(){

  console.log.apply(console, arguments);

};

log(1);    //1

log(1,2); 

接下来的要求是给每一个 log 消息添加一个"(app)"的前辍,比如:

log("hello world");    //(app)hello world

  该怎么做比较优雅呢?这个时候需要想到arguments参数是个伪数组,通过 Array.prototype.slice.call 转化为标准数组,再使用数组方法unshift,像这样:

functionlog(){

  varargs = Array.prototype.slice.call(arguments);

  args.unshift('(app)');

  console.log.apply(console, args);

};

区别是,当你希望改变上下文环境之后并非立即执行,而是回调执行的时候,使用 bind() 方法。而 apply/call 则会立即执行函数。

当函数通过Function对象的原型中继承的方法 call() 和 apply() 方法调用时, 其函数内部的this值可绑定到 call() & apply() 方法指定的第一个对象上, 如果第一个参数不是对象,JavaScript内部会尝试将其转换成对象然后指向它

再总结一下:

apply 、 call 、bind 三者都是用来改变函数的this对象的指向的;

apply 、 call 、bind 三者第一个参数都是this要指向的对象,也就是想指定的上下文;

apply 、 call 、bind 三者都可以利用后续参数传参;

bind 是返回对应函数,便于稍后调用;apply 、call 则是立即调用 。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容