面向对象的JavaScript-007-Function.prototype.bind() 的4种作用

1.

  1 // Function.prototype.bind() 的作用
  2 
  3     // 1.Creating a bound function
  4     this.x = 9; 
  5     var module = {
  6       x: 81,
  7       getX: function() { return this.x; }
  8     };
  9 
 10     console.log(module.getX()); // 81
 11 
 12     var retrieveX = module.getX;
 13     console.log(retrieveX()); 
 14     // 9, because in this case, "this" refers
 15     // to the global object
 16 
 17     // Create a new function with 'this' bound to module
 18     // New programmers might confuse the
 19     // global var x with module's property x
 20     var boundGetX = retrieveX.bind(module);
 21     console.log(boundGetX()); // 81
 22 
 23     // 2.Partially applied functions
 24 
 25     // The next simplest use of bind() is to make a function with pre-specified initial arguments. These arguments (if any) follow the provided this value and are then inserted at the start of the arguments passed to the target function, followed by the arguments passed to the bound function, whenever the bound function is called.
 26     function list() {
 27       return Array.prototype.slice.call(arguments);
 28     }
 29 
 30     var list1 = list(1, 2, 3); // [1, 2, 3]
 31     console.log(list1);
 32     // Create a function with a preset leading argument
 33     var leadingThirtysevenList = list.bind(undefined, 37);
 34     console.log(leadingThirtysevenList);
 35     var list2 = leadingThirtysevenList(); 
 36     // [37]
 37     console.log(list2);
 38     var list3 = leadingThirtysevenList(1, 2, 3);
 39     // [37, 1, 2, 3]
 40     console.log(list3);
 41 
 42     // 3.With setTimeout
 43 
 44     //y default within window.setTimeout(), the this keyword will be set to the window (or global) object. When working with class methods that require this to refer to class instances, you may explicitly bind this to the callback function, in order to maintain the instance.
 45     function LateBloomer() {
 46       this.petalCount = Math.ceil(Math.random() * 12) + 1;
 47     }
 48 
 49     // Declare bloom after a delay of 1 second
 50     LateBloomer.prototype.bloom = function() {
 51       window.setTimeout(this.declare.bind(this), 1000);
 52     };
 53 
 54     LateBloomer.prototype.declare = function() {
 55       console.log('I am a beautiful flower with ' +
 56         this.petalCount + ' petals!');
 57     };
 58 
 59     var flower = new LateBloomer();
 60     flower.bloom();  
 61     // after 1 second, triggers the 'declare' method
 62 
 63     // 3.Bound functions used as constructors
 64     // Bound functions are automatically suitable for use with the new operator to construct new instances created by the target function. When a bound function is used to construct a value, the provided this is ignored. However, provided arguments are still prepended to the constructor call:
 65     function Point(x, y) {
 66       this.x = x;
 67       this.y = y;
 68     }
 69 
 70     Point.prototype.toString = function() { 
 71       return this.x + ',' + this.y; 
 72     };
 73 
 74     var p = new Point(1, 2);
 75     p.toString(); // '1,2'
 76 
 77     // not supported in the polyfill below,
 78 
 79     // works fine with native bind:
 80 
 81     var YAxisPoint = Point.bind(null, 0/*x*/);
 82 
 83 
 84     var emptyObj = {};
 85     var YAxisPoint = Point.bind(emptyObj, 0/*x*/);
 86 
 87     var axisPoint = new YAxisPoint(5);
 88     axisPoint.toString(); // '0,5'
 89 
 90     console.log(axisPoint instanceof Point); // true
 91     console.log(axisPoint instanceof YAxisPoint); // true
 92     console.log(new Point(17, 42) instanceof YAxisPoint); // true
 93 
 94     // Example can be run directly in your JavaScript console
 95     // ...continuing from above
 96 
 97     // Can still be called as a normal function 
 98     // (although usually this is undesired)
 99     console.log(YAxisPoint(13));
100 
101     console.log(emptyObj.x + ',' + emptyObj.y);
102     // >  '0,13'
103 
104     // 4.Creating shortcuts
105     var slice = Array.prototype.slice;
106 
107     // ...
108 
109     slice.apply(arguments);
110     // same as "slice" in the previous example
111     var unboundSlice = Array.prototype.slice;
112     var slice = Function.prototype.apply.bind(unboundSlice);
113 
114     // ...
115 
116     slice(arguments);
117 
118     // Polyfill
119     // The bind function is an addition to ECMA-262, 5th edition; as such it may not be present in all browsers. You can partially work around this by inserting the following code at the beginning of your scripts, allowing use of much of the functionality of bind() in implementations that do not natively support it.
120     if (!Function.prototype.bind) {
121       Function.prototype.bind = function(oThis) {
122         if (typeof this !== 'function') {
123           // closest thing possible to the ECMAScript 5
124           // internal IsCallable function
125           throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
126         }
127 
128         var aArgs   = Array.prototype.slice.call(arguments, 1),
129             fToBind = this,
130             fNOP    = function() {},
131             fBound  = function() {
132               return fToBind.apply(this instanceof fNOP
133                      ? this
134                      : oThis,
135                      aArgs.concat(Array.prototype.slice.call(arguments)));
136             };
137 
138         if (this.prototype) {
139           // Function.prototype doesn't have a prototype property
140           fNOP.prototype = this.prototype; 
141         }
142         fBound.prototype = new fNOP();
143 
144         return fBound;
145       };
146     }

 

posted @ 2016-05-24 16:05  shamgod  阅读(346)  评论(0编辑  收藏  举报
haha