JavaScript: The Definitive Guide, Sixth Editio javaScript权威指南(第6版) pdf 文字版-文字版, javascript电子书, 和javascript 有关的电子书:

9.2 Classes and Constructors

9.2 Classes and Constructors


Example 9-1 demonstrates one way to define a JavaScript class. It is not the idiomatic way to do so, however, because it did not define a constructor. A constructor is a function designed for the initialization of newly created objects. Constructors are invoked using the new keyword as described in §8.2.3 . Constructor invocations using new automatically create the new object, so the constructor itself only needs to initialize the state of that new object. The critical feature of constructor invocations is that the prototype property of the constructor is used as the prototype of the new object. This means that all objects created with the same constructor inherit from the same object and are therefore members of the same class. Example 9-2 shows how we could alter the range class of Example 9-1 to use a constructor function instead of a factory function:

Example 9-2. A Range class using a constructor

// range2.js: Another class representing a range of values.

// This is a constructor function that initializes new Range objects. // Note that it does not create or return the object. It just initializes this.

9.2 Classes and Constructors | 201

function Range(from, to) {

// Store the start and end points (state) of this new range object.

// These are noninherited properties that are unique to this object.

this.from = from;

this.to = to; }

// All Range objects inherit from this object. // Note that the property name must be "prototype" for this to work. Range.prototype = {

// Return true if x is in the range, false otherwise

// This method works for textual and Date ranges as well as numeric.

includes: function(x) { return this.from <= x && x <= this.to; },

// Invoke f once for each integer in the range.

// This method works only for numeric ranges.

foreach: function(f) {

for(var x = Math.ceil(this.from); x <= this.to; x++) f(x);

},

// Return a string representation of the range

toString: function() { return "(" + this.from + "..." + this.to + ")"; } };

// Here are example uses of a range object var r = new Range(1,3); // Create a range object r.includes(2); // => true: 2 is in the range r.foreach(console.log); // Prints 1 2 3 console.log(r); // Prints (1...3)

It is worth comparing Example 9-1 and Example 9-2 fairly carefully and noting the differences between these two techniques for defining classes. First, notice that we renamed the range()factory function to Range()when we converted it to a constructor. This is a very common coding convention: constructor functions define, in a sense, classes, and classes have names that begin with capital letters. Regular functions and methods have names that begin with lowercase letters.

Next, notice that the Range() constructor is invoked (at the end of the example) with the new keyword while the range() factory function was invoked without it. Exam ple 9-1 uses regular function invocation ( §8.2.1 ) to create the new object and Exam ple 9-2 uses constructor invocation ( §8.2.3 ). Because the Range()constructor is invoked with new, it does not have to call inherit() or take any action to create a new object. The new object is automatically created before the constructor is called, and it is accessible as the this value. The Range() constructor merely has to initialize this. Constructors do not even have to return the newly created object. Constructor invocation automatically creates a new object, invokes the constructor as a method of that object, and returns the new object. The fact that constructor invocation is so different from regular function invocation is another reason that we give constructors names that start with capital letters. Constructors are written to be invoked as constructors, with the new keyword, and they usually won’t work properly if they are invoked as regular functions. A naming convention that keeps constructor functions distinct from regular functions helps programmers to know when to use new.

Another critical difference between Example 9-1 and Example 9-2 is the way the prototype object is named. In the first example, the prototype was range.methods. This was a convenient and descriptive name, but arbitrary. In the second example, the prototype is Range.prototype, and this name is mandatory. An invocation of the Range() constructor automatically uses Range.prototype as the prototype of the new Range object.

Finally, also note the things that do not change between Example 9-1 and Exam ple 9-2 : the range methods are defined and invoked in the same way for both classes.

欢迎转载,转载请注明来自一手册:http://yishouce.com/book/1/27673.html
友情链接It题库(ittiku.com)| 版权归yishouce.com所有| 友链等可联系 admin#yishouce.com|粤ICP备16001685号-1