1. 程式人生 > >javascript 軟化繫結

javascript 軟化繫結

1. 被忽略的this

如果你傳遞null或者undefined作為call,apply,或bind的this繫結引數,那麼這些值會被忽略掉,取而代之的是預設繫結規則將適用於這個呼叫。在嚴格模式下(被調函式內部使用strict模式), this等於undefined, 在非嚴格模式下,this指向global物件(在瀏覽器中是window)。

2. 防止this繫結退回到預設繫結的措施

2.1 空物件 {}

2.2 DMZ物件 Object.create(null)

如果想讓使用的函式不關心this,可以傳遞一個空物件作為thisArgs, 但空物件的原型指向Object.prototype,在Object.prototype上新增的任何屬性都會影響到大多數物件,因為絕大多數物件原型鏈終端都是Object.prototype,為了隔離這個副作用,可以傳遞一個完全為空的物件Object.create(null), 任何對this的隱藏或意外的使用將會被限制在這個空物件中。

2.3 軟化繫結

防止退回到預設繫結,意外的修改global物件,同時保持函式可以通過隱含繫結或顯式繫結來手動繫結this。

		if(!Function.prototype.softBind) {
			Function.prototype.softBind = function (obj) {
				var fn = this;
					curried = [].slice.call(arguments,1),
					bound = function bound() {
						return fn.apply( (!this || (typeof window !== "undefined" && this === window)
								|| ( typeof global !== "undefined" && this === global)
							) ? obj : this,
							curried.concat.apply(curried,arguments)
						);
					};
					bound.prototype = Object.create(fn.prototype);
					return bound;
			};	
		}

		function foo() {
			console.log("name:" + this.name);
		}

		var obj = {name:"obj"},
			obj2 = {name:"obj2"},
			obj3 = {name:"obj3"};

		var fooOBJ = foo.softBind(obj);
		fooOBJ();//name: obj
		obj2.foo = foo.softBind(obj);
		obj2.foo();//name: obj2
		fooOBJ.call(obj3);
		setTimeout(obj2.foo,10);//name: obj 退回到軟繫結