bind方法是绑定在了Function.prototype上。这个方法会建立一个新的函数,当被调用时,会将其this关键字,设置为一个提供的值。数组
bind()会建立一个新的函数,成为绑定函数,目标函数和绑定函数有共同的函数体。新的目标函数被调用的时候,this就会绑定到bind()函数的第一个参数上,且该参数不能被重写。在函数调用的时候,也能够为目标函数增长新的参数,参数跟在第一个参数以后。app
var a = 'hello 222' var obj = { 'a':'hello 111', say:function(){ return this.a } } var otherSay = obj.say console.log(obj.say()) //hello 111 console.log(otherSay()) //hello 222
咱们都知道,this的指向取决于函数的调用而不是生命的位置,因此,otherSay()被调用的this指向全局对象,这时候a并非obj里边定义的。因此会输出'hello 222'。函数
咱们可使用bind来改变otherSay()的this指向。固然call和apply也能作到。可是bind和另外两个方法是不同的。this
var newSay = otherSay.bind(obj) console.log(newSay())
绑定函数newSay(),目标函数otherSay().用bind执行完操做后,两个函数共用一样一个执行环境,无论怎么调用,两个函数都有一样的this值。prototype
bind是绑定在了Function的原型上。它是ES5提出来的,用了ES3的apply做为背后的实现。code
Function.prototype.bind = function(obj){ var _self = this return function(){ return _self.apply(obj) } }
当新的目标函数被建立的时候,目标函数的this的值经过apply被设成了传入的参数的值。由于,咱们传入咱们想要的函数上下文,当函数调用的时候this就会指向了第一个参数。对象
函数柯里化的概念是只传给函数一部分参数就能调用他,让他返回一个新的函数去处理另外的参数。
function add(x){ return function(y){ return x+y } } var add1 = add(10) add1(20) //30 add1(-10) // 0
用bind()能够实现函数的柯里化get
function gender,age,name){ var salutation = gender === “male” ? “Mr” : "Ms" if(age > 25){ return "hello" + salutation + name } else{ return "hey" + name } }
这是一个很简单的函数,很好理解。原型
接下来,咱们使用柯里化greet()方法.bind()接收的第一个参数指定的this的值。回调函数
var greetMaleAdult = greet.bind(null,'name',44) greetMaleAdult('Peter') var greetChild = greet(null,'',12) greetChild('Bob')
使用bind函数,能够将greet函数柯里化,咱们只须要指定最后一个参数来执行柯里化以后的新函数,由于前边两个参数,d都在greet里边定义好了。
这两个方法放在一块儿将,由于两个函数基本上没有区别。
两个函数都是写到了Function.prototype上面。本质上这两个方法能够帮助咱们实现函数借用和指定函数的this值。apply()容许咱们传入一个参数数组来传给函数,供这个函数使用。
当咱们使用这两个函数的时候,传入的第一个参数做为this的目标指向。
var age = 11 function showAge(){ console.log(this.age) } var Man = { age:15 } showAge.apply(Man) // 当即返回15
咱们看到,加了一行代码,咱们改变了showAge中的this指向,开始的时候,全局函数showAge中的指向是全局对象,可是,咱们经过apply函数,把this指向了一个对象Man,这个时候,会当即返回函数的执行结果15
apply和bind不同的地方在于,bind不会当即返回结果,会返回一个新的函数,咱们调用这个函数,才会返回结果
var age = 11 function showAge(){ console.log(this.age) } var Man = { age:15 } showAge.bind(Man) // 并不会当即执行 showAge.bind(Man)() // 执行返回的函数,显示15
另外,在回调函数中,咱们也能够经过apply或者call方法手动设置this的指向。
var obj = { fullname:'not set', showName:function(firstname,lastname){ this.fullname = firstname + ' ' +lastname } } function getFullname(firstname,lastname,callback,callbackobj){ callback.call(callbackobj,firstname,lastname) } getFullname('zhang','heihei',obj.showName,obj) console.log(obj.fullname) // zhang heihei
call和apply的存在可让咱们借用其余对象的函数来处理。最典型的例子就是咱们能够经过函数借用来让类数组对象使用数据的方法。
var arrayLikeObj = { '0':'haha', '1':1, '2':true, '3':[1,2,3], length:4 } var newArr = Array.prototype.slice.call(arrayLikeObj,0) // ['haha',1,true,Array[3]] var index = Array.prototype.indexOf.apply(arrayLikeObj,1) //1
这样操做的好处就是既能够保留对象上的那些属性,又能够随时使用数组的方法。
三个函数的最大区别在于:bind函数是返回一个函数(内部实现也是用的apply)供后续调用,而call和apply是当即调用返回执行结果。
另外,在箭头函数中,apply和call会失效,由于,箭头函数的this是肯定的,是所在的执行上下文,而不是调用的时候的函数使用者。