解读Javascript中的Function.prototype.bind
首先贴上MSDN上标准的Polyfill:
1 if (!Function.prototype.bind) {
2 Function.prototype.bind = function(oThis) {
3 if (typeof this !== 'function') {
4 // closest thing possible to the ECMAScript 5
5 // internal IsCallable function
6 throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
7 }
8
9 var aArgs = Array.prototype.slice.call(arguments, 1),
10 fToBind = this,
11 fNOP = function() {},
12 fBound = function() {
13 return fToBind.apply(this instanceof fNOP
14 ? this
15 : oThis,
16 aArgs.concat(Array.prototype.slice.call(arguments)));
17 };
18
19 if (this.prototype) {
20 // Function.prototype doesn't have a prototype property
21 fNOP.prototype = this.prototype;
22 }
23 fBound.prototype = new fNOP();
24
25 return fBound;
26 };
27 }
下面将上述代码逐行分析。
第一行判断Function的原型中是否有该函数, 因为bind函数并不是每个浏览器都支持,下面列出浏览器的支持情况:

第3行 if (typeof this !== 'function')用来判断调用bind函数的对象是否为函数,注意在整个bind函数作用域中this指代调用它的对象,且该对象必须为函数,通过typeof函数来检测。
第9行var aArgs = Array.prototype.slice.call(arguments, 1)中,arguments为传入bind函数的参数对象,由于其并不是数组,而是一种伪数组对象,但是可以使用数组的slice方法,由于bind函数的第一个参数为绑定的函数,故slice方法从1开始获取参数。
举例: someFunc.bind(oThis, arg1, arg2) ,则slice方法取到的就是[arg1, arg2]。
第12行fBound函数,为最终bind函数返回的新函数,通过apply方法将fToBind函数的上下文改为oThis。
第16行 aArgs.concat(Array.prototype.slice.call(arguments))),这行代码将bind函数中的参数和执行bind函数返回的函数传入的参数进行合并,最终传给实际调用的函数fToBind来使用。
第21行 fNOP.prototype = this.prototype; 将fToBind中的原型对象赋给一个没有原型的空函数,再通过fBound.prototype = new fNOP(); 进行原型函数继承,因为apply方法只能继承构造方法,最终返回的fBound匿名函数继承了fToBind对象的构造方法和原型方法,且上下文为oThis,从而实现了绑定。
实际上 anotherFunc =someFunc.bind(oThis, arg1, arg2);中的anotherFunc即为fBound, anotherFunc(args)即执行fBound(args)。

浙公网安备 33010602011771号