1 var ERROR_MESSAGE = 'Function.prototype.bind called on incompatible ';
2 var slice = Array.prototype.slice;
3 var toStr = Object.prototype.toString;
4 var funcType = '[object Function]';
6 module.exports = function bind(that) {
7 var target = this;
8 if (typeof target !== 'function' || toStr.call(target) !== funcType) {
9 throw new TypeError(ERROR_MESSAGE + target);
10 }
11 var args = slice.call(arguments, 1);
13 var bound;
14 var binder = function () {
15 if (this instanceof bound) {
16 var result = target.apply(
17 this,
18 args.concat(slice.call(arguments))
19 );
20 if (Object(result) === result) {
21 return result;
22 }
23 return this;
24 } else {
25 return target.apply(
26 that,
27 args.concat(slice.call(arguments))
28 );
29 }
30 };
32 var boundLength = Math.max(0, target.length - args.length);
33 var boundArgs = [];
34 for (var i = 0; i < boundLength; i++) {
35 boundArgs.push('$' + i);
36 }
38 bound = Function('binder', 'return function (' + boundArgs.join(',') + '){ return binder.apply(this,arguments); }')(binder);
40 if (target.prototype) {
41 var Empty = function Empty() {};
42 Empty.prototype = target.prototype;
43 bound.prototype = new Empty();
44 Empty.prototype = null;
45 }
47 return bound;
48 };