85 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			85 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
|  | 'use strict'; | ||
|  | 
 | ||
|  | /* eslint no-invalid-this: 1 */ | ||
|  | 
 | ||
|  | var ERROR_MESSAGE = 'Function.prototype.bind called on incompatible '; | ||
|  | var toStr = Object.prototype.toString; | ||
|  | var max = Math.max; | ||
|  | var funcType = '[object Function]'; | ||
|  | 
 | ||
|  | var concatty = function concatty(a, b) { | ||
|  |     var arr = []; | ||
|  | 
 | ||
|  |     for (var i = 0; i < a.length; i += 1) { | ||
|  |         arr[i] = a[i]; | ||
|  |     } | ||
|  |     for (var j = 0; j < b.length; j += 1) { | ||
|  |         arr[j + a.length] = b[j]; | ||
|  |     } | ||
|  | 
 | ||
|  |     return arr; | ||
|  | }; | ||
|  | 
 | ||
|  | var slicy = function slicy(arrLike, offset) { | ||
|  |     var arr = []; | ||
|  |     for (var i = offset || 0, j = 0; i < arrLike.length; i += 1, j += 1) { | ||
|  |         arr[j] = arrLike[i]; | ||
|  |     } | ||
|  |     return arr; | ||
|  | }; | ||
|  | 
 | ||
|  | var joiny = function (arr, joiner) { | ||
|  |     var str = ''; | ||
|  |     for (var i = 0; i < arr.length; i += 1) { | ||
|  |         str += arr[i]; | ||
|  |         if (i + 1 < arr.length) { | ||
|  |             str += joiner; | ||
|  |         } | ||
|  |     } | ||
|  |     return str; | ||
|  | }; | ||
|  | 
 | ||
|  | module.exports = function bind(that) { | ||
|  |     var target = this; | ||
|  |     if (typeof target !== 'function' || toStr.apply(target) !== funcType) { | ||
|  |         throw new TypeError(ERROR_MESSAGE + target); | ||
|  |     } | ||
|  |     var args = slicy(arguments, 1); | ||
|  | 
 | ||
|  |     var bound; | ||
|  |     var binder = function () { | ||
|  |         if (this instanceof bound) { | ||
|  |             var result = target.apply( | ||
|  |                 this, | ||
|  |                 concatty(args, arguments) | ||
|  |             ); | ||
|  |             if (Object(result) === result) { | ||
|  |                 return result; | ||
|  |             } | ||
|  |             return this; | ||
|  |         } | ||
|  |         return target.apply( | ||
|  |             that, | ||
|  |             concatty(args, arguments) | ||
|  |         ); | ||
|  | 
 | ||
|  |     }; | ||
|  | 
 | ||
|  |     var boundLength = max(0, target.length - args.length); | ||
|  |     var boundArgs = []; | ||
|  |     for (var i = 0; i < boundLength; i++) { | ||
|  |         boundArgs[i] = '$' + i; | ||
|  |     } | ||
|  | 
 | ||
|  |     bound = Function('binder', 'return function (' + joiny(boundArgs, ',') + '){ 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; | ||
|  | }; |