1.應用案例:
var Mouse = function () {
// Look! no that = this!
this.position = [0, 0];
if (document.addEventListener) {
document.addEventListener('mousemove', ?); //this.move?
} else if (document.attachEvent) {
document.attachEvent("onmousemove", ?); //this.move?怎麼放進去
}
};
Mouse.prototype.move = function (arg1,arg2,event) {
event = window.event || event;
var x = event.pageX || event.offsetX,
y = event.pageY || event.offsetY;
this.position = position = [x, y];
this.log(arg1,arg2);
};
Mouse.prototype.log = function (arg1, arg2) {
console.log(arg1+","+arg2);
console.log(this.position);
};
new Mouse();
www.2cto.com
上面你知道'?'號那裡要幹嘛了嗎?我想給document的mousemove綁定我的move方法,但是遇到難題了,這樣的話,Mouse.prototype.move
裡的this就不會指向Mouse的對象,相信大家經常碰到這種問題.也許你早知道了怎麼解決,但是有更快更簡單的方法嗎?答案是:
Function.prototype.bind()這個神奇的玩意,但是ie6 7 8都不支援,一般現代瀏覽器都支援了,我們接下來要做的就是模仿他,
這麼好的方法當然要模仿它,怎麼模仿見下面nothing的原創方法
(function () {
var proxy = function (fn, target) {
var proxy = function () {
if (2 < arguments.length) { //存在被代理的函數有參數的時候
var privateArgs = Array.prototype.slice.call(arguments, 2);
//從第二個開始取出來,[this,綁定的對象,參數列表]
return function () {
var args = Array.prototype.slice.call(arguments);
-->這裡的arguments與外面的不是同一個,這個是被代理的函數內部的arguments對象,
比如這裡的move函數的 arguments[0]=[object Event]就是這個事件內部的e參數
Array.prototype.unshift.apply(args, privateArgs);
-->這裡在加上傳進來的參數,就實現了,和原生bind一樣的參數形式
//->而且這裡是把私人的參數放到前面的比如a=new Mouse();a.move(1,2);
//如果這個move方法沒有參數,意思就是prototype.move=fn(){arguments} ,
//而我傳進來了參數,參數的arguments.length=3,
//arguments[0]=1,arguments[1]=2,arguments[2]=[object event].
return fn.apply(target, args);
}
//這裡之所以搞複雜了,是因為,在被代理的函數可以直接存取arguments,比如我不給被代理的函數傳參數,而直接使用
//這樣這個arguments就會包含與原生Function.prototype.bind的arguments一樣的對象,
//這裡代碼深奧,是因為你沒理解這裡原生的bind裡面的arguments是什麼,知道了,就知道為什麼綁定我自己的arguments
//做這麼多,主要目的就是使你被代理的函數內部的arguments與function.prototype.bind裡的arguments對象包含的東西一致
}
return function () {
return fn.apply(target, arguments);
}
}
return proxy.apply(null, arguments);
};
/*支援原生的使用原生的*/
Function.prototype.bind = Function.prototype.bind ||
function (target) { //這裡的this指代要被代理的函數
if (1 < arguments.length) {
var args = Array.prototype.slice.call(arguments, 1); //取出參數列表
args.unshift(this, target); //這個args最終變成了[this,綁定的對象,參數列表]
return proxy.apply(null, args);
-->估計大家會跟17樓犯一樣的錯誤,這裡之所以這麼複雜的操作arguments對象,只是為了能保證傳進proxy函數中,保證arguments對象不失效
}
return proxy(this, target);
};
})();
www.2cto.com
以上代碼為什麼我要一直return回來代理,因為這樣你才能這樣調用this.move.bind(this,1,2)()然後這裡會立即執行函數!
有了以上代碼,我們就可以輕鬆的實現了"?"號這裡要寫什麼代碼了,^_^,簡單吧
if (document.addEventListener) {
document.addEventListener('mousemove', this.move.bind(this,1,2));
} else if (document.attachEvent) {
document.attachEvent("onmousemove", this.move.bind(this,1,2));
}
www.2cto.com
是不是以後凡是碰到要添加事件,然後調用的方法的this又想指向其他對象,這樣是不是很簡單呢..
看到大家對以上代碼有點難理解,來個簡單點得
var a = function () {
console.log(arguments[0]); //1
console.log(arguments[1]); //2
console.log(this.key1);
//這樣綁定參數的話,我的參數列出來才能和原生的bind一樣,就這麼簡單,
};
var b = {
key1: "value1"
};
a.bind(b, 1, 2)();
www.2cto.com
反駁17樓同學的代碼錯誤,我想這是很多人會犯的錯誤,代碼如下
Function.prototype.bind = function (target) {
var self = this;
return function () {
return self.apply(target, arguments); //這裡的arguments根本傳不進來
}
}
var a = function () {
console.log(arguments.length); //這樣bind的話,arguments參數失效
//arguments.length=0.
console.log(this.key1);
};
var b = {
key1: "value1"
};
a.bind(b, [1, 2], 3)(); //從這裡可以看出,期望的arguments.length=2
//這也是我為什麼苦口婆心的操作arguments參數
//我知道這裡大部分人都會覺得對的,但是你錯了,17樓的同學你還得在思考下
不帶注釋的源碼,
(function () {
var proxy = function (fn, target) {
var proxy = function () {
if (2 < arguments.length) {
var privateArgs = Array.prototype.slice.call(arguments, 2);
return function () {
var args = Array.prototype.slice.call(arguments);
Array.prototype.unshift.apply(args,privateArgs);
return fn.apply(target, args);
}
}
return function () {
return fn.apply(target, arguments);
}
}
return proxy.apply(null, arguments);
};
/*支援原生的使用原生的*/
Function.prototype.bind = Function.prototype.bind ||
function (target) {
if (1 < arguments.length) {
var args = Array.prototype.slice.call(arguments, 1);
args.unshift(this, target);
return proxy.apply(null, args);
}
return proxy(this, target);
};
})();
www.2cto.com
如若需要轉載本文,請附上連結
http://www.cnblogs.com/nothingbrother/