javascript Function.prototype.bind()的模拟实现

前言

Javascript提供的内置函数Function.prototype.call(),Function.prototype.apply(),Function.prototype.bind()允许我们显示的绑定函数执行时的this,其原理使用了元编程技术,这种技术的背后是JS引擎根据变量,函数,对象的内置属性和元属性来决定执行方式。而模拟实现只是近似模拟与内置函数相同的行为,但远没有内置函数精妙,也不可作为解释内置函数的理论依据。能让Javascript跑起来的是JS引擎,只有懂JS引擎的工作原理才能让我们探视到内置函数的真面目,这也是我们深入了解后要检视的领域。

我们入门时需要学习什么?我们能够学习到什么?任何知识的学习像一个爬楼梯的过程,爬的越高,越心旷神怡,醍醐灌顶。我们入门时需要学会的是一种推导能力,用已学知识推导新知识;一种想象能力,想象那些可能性,然后大胆尝试,找到答案。

1. bind()原理

一个函数执行需要具备3个已知条件:函数引用(必须),this绑定(可选),arguments(可选)。而内置函数bind恰恰使用3个属性记录这3个东西。baz是bind()返回的硬绑定函数,baz.name记录了目标函数的名字,[[TargetFunction]]属性记录目标函数,[[BoundThis]]记录目标函数执行时绑定的this,[[BoundArgs]]记录目标函数执行时绑定的实参。

javascript Function.prototype.bind()的模拟实现_第1张图片

2. 自定义myBind模拟Bind()功能

		Function.prototype.myBind = function (oThis){
			//debugger;
			if(typeof this!=="function") {
				throw new TypeError("Function.prototype.myBind-what" + "is trying to be bound is not callable")
			};

			//局部变量aArgs存储myBind函数的实参
			var aArgs = Array.prototype.slice.call(arguments,1),

			fToBind = this,
			fNOP = function (){},//圣杯模式,用于创建fBound函数原型的中间函数
			fBound = function () {
				return fToBind.apply( 
					(
					//fNOP.prototype在New fBound()构造的实例的原型链上
					this instanceof fNOP && oThis ? this: oThis),

					//拼接myBind函数的实参和硬绑定函数fBound的实参后,传递给目标函数fToBind
					aArgs.concat(Array.prototype.slice.call(arguments)
					));
				 };

			//圣杯模式
			fNOP.prototype = this.prototype;
			fBound.prototype = new fNOP();
			//fBound.prototype.constructor = fBound;
			//fBound.prototype.uber = this.prototype;
			return fBound;
		};

		debugger;
		function foo(a,b) {
			this.a = a;
			this.b = b;
		}

		var obj1 = {};
		var baz = foo.myBind(obj1,2);
		baz(3);
		console.log(obj1);//{a:2,b:3}

		var obj2 = new baz(4);//fBound {a:2,b:4}
		console.log(obj2);

允许new进行覆盖的部分是这里:

this instanceof fNOP && oThis ? this : oThis

// .....和

fNOP.prototype = this.prototype;

fBound.prototype = new fNOP();

 

你可能感兴趣的:(Javascript)