大鹏一日同风起,扶摇直上九万里。这篇文章主要讲述call,apply,bind相关的知识,希望能为你提供帮助。
在javascript中,call
、apply
和bind
是Function
对象自带的三个方法,都是为了改变函数体内部
this
的指向。
apply 、 call 、bind
三者第一个参数都是
this
要指向的对象,也就是想指定的上下文;
apply 、 call 、bind
三者都可以利用后续参数传参;
bind 是返回对应
函数,便于稍后调用;apply 、call
则是立即调用 。
例子:
1.
function fruits() {} fruits.prototype = { color: ‘red‘, say: function() { console.log(‘My color is‘ + this.color); } } var apple = new fruits; apple.say(); // 此时方法里面的this 指的是fruits // 结果: My color is red
但是如果我们有一个对象
banana= {color : ‘yellow‘}
,我们不想重新定义 say 方法,那么我们可以通过 call 或 apply 用 apple 的 say 方法:banana = { color: ‘yellow‘ } apple.say.call(banana); //此时的this的指向已经同过call()方法改变了,指向的是banana,this.color就是banana.color=‘yellow‘; //结果是My color is yellow apple.say.apply(banana); //同理,此时的this的指向已经同过apply()方法改变了,指向的是banana,this.color就是banana.color =‘yellow‘; //My color is yellow // 如果传入的是 null:apple.say.apply(null); // null是window下的,此时,this 就指向了window ,但是window下并没有clolr这个属性,因此this.clolr就是window.color=undefined; //My color is undefined
2.对于 apply、call 二者而言,作用完全一样,只是接受 参数 的方式不太一样。call 是把参数按顺序传递进去,而 apply 则是把参数放在数组 里。
var array1 = [12,‘foo‘,{name:‘Joe‘},-2458]; var array2 = [‘Doe‘ , 555 , 100]; Array.prototype.push.call(array1, array2); // 这里用 call 第二个参数不会把 array2 当成一个数组,而是一个元素 //等价于array1.push(‘‘‘Doe‘ , 555 , 100’’); //array1.length=5; Array.prototype.push.apply(array1, array2); // 这里用 apply 第二个参数是一个数组 // 等价于:array1.push(‘Doe‘ , 555 , 100); //array1.length=7;
3.类(伪)数组使用数组方法
var divElements = document.getElementsByTagName(‘div‘); //虽然 divElements 有length属性,但是他是一个伪数组,不能使用数组里面的方法 Array.isArray(divElements); // false var domNodes = Array.prototype.slice.call(document.getElementsByTagName(‘div‘)); // 将数组对象Array里的this指向伪数组document.getElementsByTagName(‘div‘), //slice() 方法可从已有的数组中返回选定的元素,不传参数是,返回整个数组 Array.isArray(domNodes); // true
4. 验证一个对象的类型可以用:
Object.prototype.toString.call(obj)
5.bind()
方法,MDN 的解释是:bind()
方法会创建一个
新函数,称为绑定函数,当调用这个绑定函数时,绑定函数会以创建它时传入
bind()
方法的第一个参数
作为
this
,传入
bind()
方法的
第二个以及以后的参数加上绑定函数运行时本身的参数按照顺序作为原函数的参数来调用原函数。
var bar = function(){ console.log(this.x); } var foo = { x:3 } bar(); // undefined var func = bar.bind(foo); //此时this已经指向了foo,但是用bind()方法并不会立即执行,而是创建一个新函数,如果要直接调用的话 可以 bar.bind(foo)()func(); // 3
6.在 javascript 中,多次
bind()
是无效的。更深层次的原因,
bind()
的实现,相当于使用函数在内部包了一个
call / apply
,第二次
bind()
相当于再包住第一次
bind()
,故第二次以后的
bind
是无法生效的。var bar = function(){ console.log(this.x); } var foo = { x:3 } var sed = { x:4 } var func = bar.bind(foo).bind(sed); func(); //3var fiv = { x:5 } var func = bar.bind(foo).bind(sed).bind(fiv); func(); //3
7.
apply、call、bind
三者相比较,之间又有什么异同呢?何时使用
apply、call
,何时使用
bind
呢。简单的一个例子:var obj = { x: 81, }; var foo = { getX: function() { return this.x; } } console.log(foo.getX.bind(obj)()); //81 console.log(foo.getX.call(obj)); //81 console.log(foo.getX.apply(obj)); //81
【call,apply,bind】参考:
- 深入浅出 妙用Javascript中apply、call、bind
- Function.prototype.bind()
- Function.prototype.call()
- Function.prototype.apply()
推荐阅读
- Android-Binder
- spring 通用mapper的一些注解
- 安卓活动的启动模式
- Android tabLayout+recyclerView实现锚点定位
- 阿里Android客户端一面经历
- 安卓六大布局
- Create an Android library
- 2获取APP CPU占用率
- ionic真机调试Android报错 - could not read ok from ADB Server * failed to start daemon * error: cannot conn