Enforcing Function Context

2456 ワード

What happens when we try to bind an object's method to a click handler?
 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();
 assert( elem.clicked, "The clicked property was accidentally set on the element" ); 
We need to keep its context as the original object.
 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();
 assert( Button.clicked, "The clicked property was correctly set on the object" ); 
Add a method to all functions to allow context enforcement.
 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();
 assert( Button.clicked, "The clicked property was correctly set on the object" ); 
Our final target (the .bind method from Prototype.js).
 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();
 assert( Button.clicked === false, "The clicked property was correctly set on the object" );