Objects

25 298 0
Objects

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

Thông tin tài liệu

Chapter 8. Objects Chapter 3 explained that objects are one of the funda are also one of the most important. This chapter describes JavaScript objects in mental data types in JavaScript. etail. Basic usage of objects, described in the next section, is straightforward, but as we'll see in later sections, objects have more complex uses and behaviors. Properties ultiple values into a single unit and followed by the name of an create an newly created tructor initializes an // The current date and sents December 31, They d 8.1 Objects and Objects are composite data types: they aggregate m allow us to store and retrieve those values by name. Another way to explain this is to say that an object is an unordered collection of properties, each of which has a name and a value. The named values held by an object may be primitive values like numbers and strings, or they may themselves be objects. 8.1.1 Creating Objects Objects are created with the new operator. This operator must be a constructor function that serves to initialize the object. For example, we c roperties) like this:empty object (an object with no p var o = new Object( ); JavaScript supports other built-in constructor functions that initialize objects in other, less trivial, ways. For example, the Date( ) cons ime:object that represents a date and t var now = new Date( ); time var new_years_eve = new Date(2000, 11, 31); // Repre 2000 Later in this chapter, we'll see that it is possible to define custom constructor methods to initialize newly created objects in any way you desire. Object literals provide another way to create and initialize new objects. As we saw in Chapter 3, an object literal allows us to embed an object description literally in JavaScrip code in much the same way that we embed textual data into JavaScri t pt code as quoted d list of property specifications ion in an object literal consists of e followed by a colon and the property value. For example: var circle = { x:0, y:0, radius:2 } var homer = { strings. An object literal consists of a comma-separate nclosed within curly braces. Each property specificate the property nam name: "Homer Simpso age: 34, n", The object literal syntax is defined by the ECMAScript v3 specification and implemented normally use the . operator to access the value of an object's properties. The value on the left of the . should be a reference to an object (usually just the name of the the r perty p in object o with o.p or to the property radius in the object circle with circle.radius. Object properties work like variables: you can from them. For example: ject. book.title = "JavaScript: The Definitive Guide" ct( ); ntroduction to JavaScript"; ook.chapter1.pages = 19; book.chapter2 = { title: "Lexical Structure", pages: 6 }; .chapter2.title); out this example is that you can create a new property of married: true, occupation: "plant operator", email: "homer@simpsons.com" }; in JavaScript 1.2 and later. 8.1.2 Setting and Querying Properties You variable that contains the object reference). The value on the right of the . should be name of the property. This must be an identifier, not a string or an expression. Fo example, you would refer to the pro store values in them and read values // Create an object. Store a reference to it in a variable. var book = new Object( ); // Set a property in the ob // Set some more properties. Note the nested objects. book.chapter1 = new Obje ook.chapter1.title = "Ib b // Read some property values from the object. alert("Outline: " + book.title + "\n\t" + "Chapter 1 " + book.chapter1.title + "\n\t" + "Chapter 2 " + book An important point to notice ab an object simply by assigning a value to it. Although we declare variables with the var keyword, there is no need (and no way) to do so with object properties. Furthermore, once you have created an object property by assigning a value to it, you can change the value of the property at any time simply by assigning a new value: book.title = "JavaScript: The Rhino Book" 8.1.3 Enumerating Properties The for/in loop discussed in Chapter 6 provides a way to loop through, or enumerate, the properties of an object. This can be useful when debugging scripts or when working wit b hose names you do not know in adv c an obje function DisplayPropertyNames(obj) { mes); r, and defined properties, it does not enumerate certain ethods. .4 Undefined Properties ords, a ing the undefined h o jects that may have arbitrary properties w an e. The following code shows a function you can use to list the property names of ct: var names = ""; for(var name in obj) names += name + "\n"; alert(na } Note that the loop does not enumerate properties in any specific ordefor/in hough it enumerates all user-alt predefined properties or m 8.1 If you attempt to read the value of a property that does not exist (in other w property that has never had a value assigned to it), you end up retriev value (introduced in Chapter 3). You can use the delete operator to delete a property of an object: We saw previously that you c a new object in JavaScript by using t( pes pl you are writing a program that manipulates rectangles, y ight want to represent l type, or class, of object. Each object of this Rectangle class operty and a height property, since those are the essential defining characteristics of rectangles. delete book.chapter2; Note that deleting a property does not merely set the property to undefined; it actually removes the property from the object. The for/in loop demonstrates this difference: it enumerates properties that have been set to the undefined value, but it does not enumerate deleted properties. 8.2 Constructors an create and initialize the new operator in conjunction with a predefined constructor function such as Objec ), Date( ), or Function( ). These predefined constructors and the built-in object ty they create are useful in many instances. However, in object-oriented programming, it is also common to work with custom object types defined by your program. For exam e, if ou m rectangles with a specia would have a width pr To create objects with properties such as width and height already defined, we need to write a constructor to create and initialize these properties in a new object. A construct is a JavaScript function with two special features: x It is invoked through the or w operator. x It is passed a reference to a newly created, empty object as the value of the this ord, and it is responsible for performing appropriate initialization for that new object. ne keyw Example 8-1 shows how the constructor function for a Rectangle object might be defined and invoked. xample 8-1. A Rectangle object constructor function "this". function Rectangle(w, h) this.width = w; this.height = h; can i ize each new object appropriately. defining an appropriate constructor function constructor are now guaranteed to have width and height properties. This means that we can write programs that rely es a lize the object w E // Define the constructor. // Note how it initializes the object referred to by { } // Invoke the constructor to create two Rectangle objects. // We pass the width and height to the constructor, // so it nitial var rect1 = new Rectangle(2, 4); var rect2 = new Rectangle(8.5, 11); Notice how the constructor uses its arguments to initialize properties of the object referred to by the this keyword. Keep in mind that a constructor function simply initializes the specified object; it does not have to return that object. We have defined a class of objects simply by - all objects created with the Rectangle( )- initialized on this fact and treat all Rectangle objects uniformly. Because every constructor defin class of objects, it is stylistically important to give a constructor function a name that indicates the class of objects it creates. Creating a rectangle with new Rectangle(1,2) is a lot more intuitive than with new init_rect(1,2), for example. Constructor functions typically do not have return values. They initia passed as the value of this and return nothing. However, a constructor is allowed to return an object value, and, if it does so, that returned object becomes the value of the ne expression. In this case, the object that was the value of this is simply discarded. 8.3 Methods A method is nothing more than a JavaScript function that is invoked through an object Recall that functions are data values and that there is nothing s al ab . peci out the names with which they are defined -- a function can be assigned to any variable, or even to any o.m = f; if m( ) expects two arguments, we might invoke it like this: voked yword within the body of the method. For example, o with the this this keyword should begin to clarify why we use methods at all. n the object , but the the ions are al keyword refers to the global object. Thus, ns and methods. The real difference lies in property of an object. If we have a function f and an object o, we can define a method named m with the following line: Having defined the method m( ) of the object o, we invoke it like this: o.m( ); Or, o.m(x, x+2); Methods have one very important property: the object through which a method is in becomes the value of the this ke when we invoke o.m( ), the body of the method can refer to the object keyword. The discussion of the Any function that is used as a method is effectively passed an extra argument -- the object through which it is invoked. Typically, a method performs some sort of operation on that object, so the method invocation syntax is a particularly elegant way to express the fact that a function is operating on an object. Compare the following two lines of code: rect.setSize(width, height); setRectSize(rect, width, height); These two lines may perform exactly the same operation o rect method invocation syntax in the first line more clearly indicates the idea that it is object rect that is the primary focus, or target, of the operation. (If the first line does not seem a more natural syntax to you, you are probably new to object-oriented programming. With a little experience, you will learn to love it!) While it is useful to think of functions and methods differently, there is not actually as much difference between them as there initially appears to be. Recall that funct values stored in variables and that variables are nothing more than properties of a glob a function, you are actually invoking a method of the object. Thus, when you invoke global object. Within such a function, the this rence between functiothere is no technical diffe design and intent: methods are written to operate som use the ehow on the this object, while this object. ed through an example. Example 8- functions usually stand alone and do not The typical usage of methods is more clearly illustrat 2 returns to the Rectangle objects of Example 8-1 and shows how a method that operates ked. s keyword, so it doesn't make sense to f; it needs instead to be made a method of some " and "height" properties defined. return this.width * this.height; 5 on Rectangle objects can be defined and invo Example 8-2. Defining and invoking a method // This function uses the thi // invoke it by itsel // object that has "width function compute_area( ) { } // Create a new Rectangle object, using the constructor defined earlier. var page = new Rectangle(8.5, 11); // Define a method by assigning the function to a property of the object. page.area = compute_area; // Invoke the new method like this: var a = page.area( ); // a = 8.5*11 = 93. One shortcoming is evident in Example 8-2: before you can invoke the area( ) method for the rect object, you must assign that method to a property of the object. While we can invoke the area( ) method on the particular object named page, we can't invoke it on any other Rectangle objects without first assigning the method to them. This quickly becomes tedious. Example 8-3 defines some additional Rectangle methods and show how they can automatically be assigned to all Rectangle objects with a constructor function. s Example 8-3. Defining methods in a constructor // First, define some functions that will be used as methods. his.height *= 2; } is.height /= 2; } this.height = h; function Rectangle_area( ) { return this.width * this.height; } function Rectangle_perimeter( ) { return 2*this.width + 2*this.height; } function Rectangle_set_size(w,h) { this.width = w; this.height = h; } function Rectangle_enlarge( ) { this.width *= 2; t function Rectangle_shrink( ) { this.width /= 2; th // Then define a constructor method for our Rectangle objects. // The constructor initializes properties and also assigns methods. function Rectangle(w, h) { // Initialize object properties. this.width = w; // Define methods for the object. this.area = Rectangle_area; this.perimeter = Rectangle_perimeter; this.set_size = Rectangle_set_size; this.enlarge = Rectangle_enlarge; this.shrink = Rectangle_shrink; } // Now, when we create a rectangle, we can immediately invoke methods on it: var r = new Rectangle(2,2); var a = r.area( ); r.enlarge( ); var p = r.perimeter( ); The technique shown in Example 8-3 also has a shortcoming. In this example, the Rectangle( ) constructor sets seven properties of each and every Rectangle object it r cts ass. initializes, even though five of those properties have constant values that are the same fo every rectangle. Each property takes up memory space; by adding methods to our Rectangle class, we've more than tripled the memory requirements of each Rectangle object. Fortunately, JavaScript has a solution to this problem: it allows an object to inherit properties from a prototype object. The next section describes this technique in detail. 8.4 Prototypes and Inheritance We've seen how inefficient it can be to use a constructor to assign methods to the obje it initializes. When we do this, each and every object created by the constructor has identical copies of the same method properties. There is a much more efficient way to specify methods, constants, and other properties that are shared by all objects in a cl JavaScript objects "inherit" properties from a prototype object. [1] Every object has a prototype; all of the properties of the prototype object appear to be properties of any objects for which it is a prototype. That is, each object inherits properties from its prototype. [1] Prototypes were introduced in Java he prototype of an object is defined by the constructor function that was used to create and initialize the object. All functions in JavaScript have a property that es Script 1.1; they are not supported in the now obsolete JavaScript 1.0. T prototype refers to an object. This prototype object is initially empty, but any properties you define in it will be inherited by all objects created by the constructor. A constructor defines a class of objects and initializes properties, such as width and height, that are the state variables for the class. The prototype object is associated with the constructor, so each member of the class inherits exactly the same set of properti from the prototype. This means that the prototype object is an ideal place for methods and other constant properties. Note that inheritance occurs automatically, as part of the process of looking up a proper value. Properties are ty ly ount of memory required by each object, since the object can inherit many of its properties. The second tially one property p of an object o, JavaScript first checks to see if o has a property named p. If it otype object of o has a property named p. This is work. to set the property of the prototype. Now you have changed t when you om its a new property p directly in o. Now that o has hen p e of p p o "shadows" or "hides" the Figure not copied from the prototype object into new objects; they mere appear as if they were properties of those objects. This has two important implications. First, the use of prototype objects can dramatically decrease the am implication is that an object inherits properties even if they are added to its prototype after the object is created. Each class has one prototype object, with one set of properties. But there are poten many instances of a class, each of which inherits those prototype properties. Because prototype property can be inherited by many objects, JavaScript must enforce a fundamental asymmetry between reading and writing property values. When you read does not, it next checks to see if the prot hat makes prototype-based inheritancew When you write the value of a property, on the other hand, JavaScript does not use the prototype object. To see why, consider what would happen if it did: suppose you try to set the value of the property o.p when the object o does not have a property named p. Further suppose that JavaScript goes ahead and looks up the property p in the prototype object of o and allows you the value of p for a whole class of objects -- not at all what you intended. Therefore, property inheritance occurs only when you read property values, no bject o that inherits that property frwrite them. If you set the property p in an o you create prototype, what happens is that its own property named p, it no longer inherits the value of p from its prototype. W you read the value of p, JavaScript first looks at the properties of o. Since it finds t and never finds the valudefined in o, it doesn't need to search the prototype objec ined there. We sometimes say that the property in def property p in the prototype object. Prototype inheritance can be a confusing topic. 8-1 illustrates the concepts we've discussed here. Figure 8-1. Objects and prototypes Because prototype properties are shared by all objects of a class, it generally makes sense to use them only to define properties that are the same for all objects within the class. es you at represent circles. The prototype object for this class is Circle.prototype, [2] This makes prototypes ideal for defining methods. Other properties with constant valu (such as mathematical constants) are also suitable for definition with prototype properties. If your class defines a property with a very commonly used default value, might define this property and its default value in a prototype object. Then, the few objects that want to deviate from the default value can create their own private, unshared copies of the property and define their own nondefault values. Let's move from an abstract discussion of prototype inheritance to a concrete example. Suppose we define a Circle( ) constructor function to create objects th so we can define a ) constructor but have not yet used it to create any Circle objects, we'd define the constant property pi like this: constant available to all Circle objects like this: [2] The prototype object of a constructor is created automatically by JavaScript. In most versions of JavaScript, every function is automatically given an empty prototype object, just in case it is used as a constructor. In JavaScript 1.1, however, the prototype object is not created until the function is used as a constructor for the first time. This means that if you require compatibility with JavaScript 1.1, you should create at least one object of a class before you use the prototype object to assign methods and constants to objects of that class. So, if we have defined a Circle( //First create and discard a dummy object; forces prototype object creation. new Circle ( ); //Now we can set properties in the protot Circle.prototype.pi = 3.14159' ype. Circle.prototype.pi = 3.14159; Example 8-4 shows our Circle example fully fleshed out. The code defines a Circle class by first defining a Circle( ) constructor to initialize each individual object and then setting properties of ss. Example 8-4. Defining a Circle .x = x; // The X-coordinate of the center of the circle Script 1.1. // First declare a function, then assign it to a prototype property. // Define another method. This time we use a function literal to define t to a prototype property all in one step. Circle.prototype to define methods and constants shared by all instances of the cla class with a prototype object // Define a constructor method for our class. // Use it to initialize properties that will be different for // each individual Circle object. function Circle(x, y, r) { this this.y = y; // The Y-coordinate of the center of the circle this.r = r; // The radius of the circle } // Create and discard an initial Circle object. // This forces the prototype object to be created in Java new Circle(0,0,0); // Define a constant: a property that will be shared by // all circle objects. Actually, we could just use Math.PI, // but we do it this way for the sake of instruction. Circle.prototype.pi = 3.14159; // Define a method to compute the circumference of the circle. // Note the use of the constant defined above. function Circle_circumference( ) { return 2 * this.pi * this.r; } Circle.prototype.circumference = Circle_circumference; // the function and assign i Circle.prototype.area = function( ) { return this.pi * this.r * this.r; } // The Circle class is defined. // Now we can create an instance and invoke its methods. var c = new Circle(0.0, 0.0, 1.0); var a = c.area( ); var p = c.circumference( ); [...]... strings JavaScript objects are actually implemented internally as associative arrays The notation for accessing properties makes them seem like the static objects of C++ and Java, and they work perfectly well in that capacity But they also have the powerful ability to associate values with arbitrary strings In this respect, JavaScript objects are much more like Perl arrays than C++ or Java objects Chapter... internal type information about built-in objects This default toString( ) method always returns a string of the form: [object class] class is the internal type of the object and usually corresponds to the name of the constructor function for the object For example, Array objects have a class of "Array", Function objects have a class of "Function", and Date objects have a class of "Date" The built-in... "Date" The built-in Math object has a class of "Math", and all Error objects (including instances of the various Error subclasses) have a class of "Error" Client-side JavaScript objects and any other objects defined by the JavaScript implementation have an implementation-defined class (such as "Window", "Document", or "Form") Userdefined objects, such as the Circle and Complex classes defined earlier in...8.4.1 Prototypes and Built-in Classes It is not only user-defined classes that have prototype objects Built-in classes, such as String and Date, have prototype objects too, and you can assign values to them.[3] For example, the following code defines a new method that is available for all String objects: [3] In JavaScript 1.1 and later // Returns true if the last character is c String.prototype.endsWith... properties In other words, if there are 10 objects of a given class, there are 10 copies of each instance property In our Circle class, for example, every Circle object has a property r that specifies the radius of the circle In this case, r is an instance property Since each object has its own copy of the instance properties, these properties are accessed through individual objects If c is an object that is... naming it Circle_area Circle.prototype.area = Circle_area; // Here's another function It takes two Circle objects as arguments and // returns the one that is larger (i.e., has the larger radius) function Circle_max(a,b) { if (a.r > b.r) return a; else return b; } // Since this function compares two Circle objects, it doesn't make sense as // an instance method operating on a single Circle object But we don't... the modularity and reusability of code Objects in JavaScript may have any number of properties, and properties may be dynamically added to an object This is not the case in strictly typed languages such as Java and C++ In those languages, each object has a predefined set of properties,[5] where each property is of a predefined type When we are using JavaScript objects to simulate object-oriented programming... (or JavaScript object) named portfolio 8.7 Object Properties and Methods As we discussed earlier, all objects in JavaScript inherit from the Object class While more specialized classes, such as the built-in String class or a user-defined Complex class, define properties and methods of their own, all objects, whatever their class, also support the properties and methods defined by the Object class Because... string, and when a function is converted to a string, we obtain the source code for the function The idea behind toString( ) is that each class of objects has its own particular string representation, so it should define an appropriate toString( ) method to convert objects to that string form Thus, when you define a class, you should define a custom toString( ) method for it so that instances of the class... operate on an object JavaScript does not have a formal notion of a class, but, as we've seen, it approximates classes with its constructors and their prototype objects In both JavaScript and class-based object-oriented languages, there may be multiple objects of the same class We often say that an object is an instance of its class Thus, there may be many instances of any class Sometimes we use the term . Chapter 8. Objects Chapter 3 explained that objects are one of the funda are also one of the most important. This chapter describes JavaScript objects in. values like numbers and strings, or they may themselves be objects. 8.1.1 Creating Objects Objects are created with the new operator. This operator must

Ngày đăng: 05/10/2013, 13:20

Tài liệu cùng người dùng

  • Đang cập nhật ...

Tài liệu liên quan