在 javascript 中,call、apply和bind 都是为了改变某个函数运行时的上下文(context)而存在的,换句话说,就是为了改变函数体内部 this 的指向。
举个例子先:javascript
let person = { name:'Lucy', say:function () { console.log(this.name) } } person.say() // Lucy
若是咱们有个person一、person二、person3,想要调用person的say方法,又不想从新定义say方法,能够这样:java
let person1 = { name:'Lily' } let person2 = { name:'Jack' } let person3 = { name:'Cici' } person.say.call(person1) // Lily person.say.apply(person2) // Jack person.say.bind(person3)() // Cici
因此,能够看出 call、apply、bind 是为了动态改变 this 而出现的,当一个 object 没有某个方法(本栗子中person一、person二、person3没有say方法),可是其余的有,咱们能够借助call或apply或bind用其它对象的方法来操做。数组
对于call和apply而言,他们的做用是同样的,区别在于接收的参数不同,call 须要把参数按顺序传递进去,而 apply 则是把参数放在数组里,例如:app
let person = { name:'Lucy', say:function (a,b) { console.log(a+this.name+b) } } person.say('<','>') // <Lucy> let person1 = { name:'Lily' } let person2 = { name:'Jack' } let person3 = { name:'Cici' } person.say.call(person1,'<','>') // <Lily> person.say.apply(person2,['<','>']) // <Jack> person.say.bind(person3,'<','>')() // <Cici>
对于bind而言,咱们能够看到用bind调用函数,后面还须要一个括号。MDN的解释是:bind()方法会建立一个新函数,称为绑定函数,当调用这个绑定函数时,绑定函数会以建立它时传入 bind()方法的第一个参数做为 this,传入 bind() 方法的第二个以及之后的参数加上绑定函数运行时自己的参数按照顺序做为原函数的参数来调用原函数。也就是说,区别是,当你但愿改变上下文环境以后并不是当即执行,而是回调执行的时候,使用 bind() 方法。而 apply/call 则会当即执行函数。dom
一、数组之间追加函数
let arr1 = [1,2,3] let arr2 = [4,5,6] Array.prototype.push.apply(arr1,arr2) //[1,2,3,4,5,6]
二、获取数组中的最大值和最小值this
let numbers = [-1,10,20,101] let max = Math.max.call(Math,...numbers) // 101 let min = Math.min.apply(Math,numbers) // -1
number 自己没有 max 方法,可是 Math 有,咱们就能够借助 call 或者 apply 使用其方法。
三、验证是不是数组(前提是toString()方法没有被重写过)prototype
function isArray(obj){ return Object.prototype.toString.call(obj) === '[object Array]' }
四、类(伪)数组使用数组方法code
let domList = Array.prototype.slice.call(document.getElementsByTagName('*'))
Javascript中存在一种名为伪数组的对象结构。比较特别的是 arguments 对象,还有像调用 getElementsByTagName , document.childNodes 之类的,它们返回NodeList对象都属于伪数组。不能应用 Array下的 push , pop 等方法。可是咱们能经过 Array.prototype.slice.call 转换为真正的数组的带有 length 属性的对象,这样 domList 就能够应用 Array 下的全部方法了。对象
Function.prototype._bind = function(){ var self = this //原函数 var context = Array.prototype.shift.call(arguments) //this上下文 var args = Array.prototype.slice.call(arguments) //参数 return function(){ self.apply(context, args.concat([].slice.call(arguments))) } }