Bind原理与源码分析
bind实例
function loadXMLDoc()
{
var fu = fun.bind(a,12,13)
fu()
}
function fun(n,n1){
console.log(this.name+'--'+n+'--'+n1)
}
let a = {name:'xa'}
bind原理
fn.bind(obj, args)
bind()方法会创建一个函数,这也是与call和apply的区别,不会立即执行,该函数的this指向了传入的第一个参数,当bind()的参数为空时,this指向全局对,象。如浏览器中的window。
**函数柯里化:**接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。
bind 采取函数柯里化,先接受this的对象,然后返回了一个接受其他参数的函数。
底层采取apply处理this的指向问题,bind原理就是返回函数的apply
Function.prototype.bind = function(ctx){
//判断是否有参数
ctx = ctx || window
//绑定该函数
var self = this
//参数数组
var args = Array.prototype.slice.call(arguments,1)
//返回一个新的函数闭包
var fun = function(){
self.apply(ctx,args)
}
return fun
}
bind源码
Function.prototype.bind = function(obj){
if(typeof this !== 'function'){
throw new Error('只有函数才能调用bind')
}
var self = this
//Array.prototype.slice.call(arguments)的作用为:强制转化arguments为数组格式,一般出现在框架活插件的源码中
var arg = Array.prototype.slice.call(arguments,1);
//要返回的函数
var newFun = function(){
//如果是new出来的,this指向它实例出来的对象,
//如果不是,那么this是指向绑定的obj对象。如果obj没有值,不传值或者是null,那么这个this是指向window的,
self.apply(this instanceof f ? this : obj ,args.concat(Array.prototype.slice.call(arguments)))
//判断this的值,判断到底是不是new出来的实例,通过instanceof 判断。
//简单解释下 instanceof ,假如a instanceof b,意思是a是不是b的实例,或者这样说:b的prototype是否在a的原型链上
}
//说明绑定过后的函数被new实例化之后,需要继承原函数的原型链方法,
//且绑定过程中提供的this被忽略(继承原函数的this对象),但是参数还是会使用
//主要是说,当new完之后 新创建出来的实例要继承原函数的原型,并且this指向新创建出来的实例对象(绑定的this将失效)
//但是为了防止返回函数的原型改变而影响原函数的原型
//过渡函数
var f = function(){};
f.prototype = this.prototype;
newFun.prototype = new f();
return newFun
}