|  | 'use strict'; | 
|  |  | 
|  | /* eslint no-invalid-this: 1 */ | 
|  |  | 
|  | var ERROR_MESSAGE = 'Function.prototype.bind called on incompatible '; | 
|  | var slice = Array.prototype.slice; | 
|  | var toStr = Object.prototype.toString; | 
|  | var funcType = '[object Function]'; | 
|  |  | 
|  | module.exports = function bind(that) { | 
|  | var target = this; | 
|  | if (typeof target !== 'function' || toStr.call(target) !== funcType) { | 
|  | throw new TypeError(ERROR_MESSAGE + target); | 
|  | } | 
|  | var args = slice.call(arguments, 1); | 
|  |  | 
|  | var bound; | 
|  | var binder = function () { | 
|  | if (this instanceof bound) { | 
|  | var result = target.apply( | 
|  | this, | 
|  | args.concat(slice.call(arguments)) | 
|  | ); | 
|  | if (Object(result) === result) { | 
|  | return result; | 
|  | } | 
|  | return this; | 
|  | } else { | 
|  | return target.apply( | 
|  | that, | 
|  | args.concat(slice.call(arguments)) | 
|  | ); | 
|  | } | 
|  | }; | 
|  |  | 
|  | var boundLength = Math.max(0, target.length - args.length); | 
|  | var boundArgs = []; | 
|  | for (var i = 0; i < boundLength; i++) { | 
|  | boundArgs.push('$' + i); | 
|  | } | 
|  |  | 
|  | bound = Function('binder', 'return function (' + boundArgs.join(',') + '){ return binder.apply(this,arguments); }')(binder); | 
|  |  | 
|  | if (target.prototype) { | 
|  | var Empty = function Empty() {}; | 
|  | Empty.prototype = target.prototype; | 
|  | bound.prototype = new Empty(); | 
|  | Empty.prototype = null; | 
|  | } | 
|  |  | 
|  | return bound; | 
|  | }; |