代码信息来自于http://ejohn.org/apps/learn/。
当我们将一个对象的点击事件绑定到一个事件触发元素时会发生什么?
<ul id="results">
</ul>
<script>
var Button = {
click: function(){
this.clicked = true;
}
}; var elem = document.createElement("li");
elem.innerHTML = "Click me!";
elem.onclick = Button.click;
document.getElementById("results").appendChild(elem); elem.onclick();
console.log( elem.clicked, "clicked属性被设置在点击的元素上面了" );
</script>
因为elem.onclick(),调用onclick时,this指向调用它的对象,也就是elem,所以发生错误。
我们需要固定上下文为原先的对象
function bind(context, name){
return function(){
return context[name].apply(context, arguments);
};
} var Button = {
click: function(){
this.clicked = true;
}
}; var elem = document.createElement("li");
elem.innerHTML = "Click me!";
elem.onclick = bind(Button, "click");
document.getElementById("results").appendChild(elem); elem.onclick();
console.log( Button.clicked, "点击属性被设置在了原先的对象上面" );
修改方法以适应所有的函数
Function.prototype.bind = function(object){
var fn = this;
return function(){
return fn.apply(object, arguments);
};
}; var Button = {
click: function(){
this.clicked = true;
}
}; var elem = document.createElement("li");
elem.innerHTML = "Click me!";
elem.onclick = Button.click.bind(Button);
document.getElementById("results").appendChild(elem); elem.onclick();
console.log( Button.clicked, "点击属性被设置在原先对象上面" );
最终目标,考虑到带参数的函数
Function.prototype.bind = function(){
var fn = this, args = Array.prototype.slice.call(arguments), object = args.shift();
return function(){
return fn.apply(object,
args.concat(Array.prototype.slice.call(arguments)));
};
}; var Button = {
click: function(value){
this.clicked = value;
}
}; var elem = document.createElement("li");
elem.innerHTML = "Click me!";
elem.onclick = Button.click.bind(Button, false);
document.getElementById("results").appendChild(elem); elem.onclick();
console.log( Button.clicked === false, "属性被设置在原先对象上面" )