/**
* A well-designed periodic executor
* First create a PeriodicalExecuter type by Class.create(),
* and then set the prototype using the object literal syntax.
*
* What needs special explanation is the rgisterCallback method, which calls the function prototype method bind defined above and passes itself as a parameter.
* The reason why this is done is because setTimeout always takes the window object as the current object by default, that is, if the registerCallback method is defined as follows:
* registerCallback: function() {
* setTimeout(this. onTimerEvent, this.frequency * 1000);
* }
* Then, the this.onTimeoutEvent method fails to execute because it cannot access the this.currentlyExecuting property.
* After using bind, this method can correctly find this, which is the current instance of PeriodicalExecuter.
*/
var PeriodicalExecuter = Class .create();
PeriodicalExecuter.prototype = {
initialize: function(callback, frequency) {
this.callback = callback;
this.frequency = frequency;
this.currentlyExecuting = false;
this.registerCallback();
},
registerCallback: function() {
setTimeout(this.onTimerEvent.bind(this), this.frequency * 1000 );
},
onTimerEvent: function() {
if (!this.currentlyExecuting) {
try {
this.currentlyExecuting = true;
this.callback ();
} finally {
this.currentlyExecuting = false;
}
}
this.registerCallback();
}
}
Specifically what is done behind Class.create(), let’s take a look at the implementation of Class.
/**
* Create a type. Note that its attribute create is a method and returns a constructor.
* is generally used as follows
* var X = Class.create(); returns a type, similar to a Class instance in java.
* To use the X type, you need to continue to use new X() to obtain an instance, just like java's Class.newInstance() method.
*
* The returned constructor will execute the method named initialize, where initialize is the name of the Ruby object's constructor method.
* The initialize method has not been defined at this time. When creating a new type in subsequent code, a corresponding method with the same name will be established.
*/
var Class = {
create: function() {
return function() {
this.initialize.apply(this, arguments);
}
}
}
Class.create actually returns a function, so what does it do when new is used? Refer to MDN
When the code new foo(...) is executed, the following things happen:
A new object is created, inheriting from foo.prototype.
The constructor function foo is called with the specified arguments and this bound to the newly created object. new foo is equivalent to new foo(), i.e. if no argument list is specified, foo is called without arguments.
The object returned by the constructor function becomes the result of the whole new expression. If the constructor function doesn't explicitly return an object, the object created in step 1 is used instead. (Normally constructors don't return a value, but they can choose to do so if they want to override the normal object creation process.)
When new, the returned function will be executed, that is, this.initialize.apply(this, arguments); at this time, this is the newly generated object, which means The initialization work of all objects is delegated to the initialize function.
-------
Why do you need to bind your initialize method to yourself here? ?