JavaScript相關-Object Model

JavaScript is an object-based language based on prototypes, rather than being class-based. Because of this different basis, it can be less apparent how JavaScript allows you to create hierarchies of objects and to have inheritance of properties and their values. This chapter attempts to clarify the situation.

This chapter assumes that you are already somewhat familiar with JavaScript and that you have used JavaScript functions to create simple objects.

Class-based vs. prototype-based languages

Class-based object-oriented languages, such as Java and C++, are founded on the concept of two distinct entities: classes and instances.

  • A class defines all of the properties (considering methods and fields in Java, or members in C++, to be properties) that characterize a certain set of objects. A class is an abstract thing, rather than any particular member of the set of objects it describes. For example, the Employee class could represent the set of all employees.
  • An instance, on the other hand, is the instantiation of a class; that is, one of its members. For example, Victoria could be an instance of the Employee class, representing a particular individual as an employee. An instance has exactly the same properties of its parent class (no more, no less).

A prototype-based language, such as JavaScript, does not make this distinction: it simply has objects. A prototype-based language has the notion(概念) of a prototypical object, an object used as a template from which to get the initial properties for a new object. Any object can specify its own properties, either when you create it or at run time. In addition, any object can be associated as the prototype for another object, allowing the second object to share the first object’s properties.

Defining a class

n class-based languages, you define a class in a separate class definition. In that definition you can specify special methods, called constructors, to create instances of the class. A constructor method can specify initial values for the instance’s properties and perform other processing appropriate at creation time. You use the new operator in association with the constructor method to create class instances.

JavaScript follows a similar model, but does not have a class definition separate from the constructor. Instead, you define a constructor function to create objects with a particular initial set of properties and values. Any JavaScript function can be used as a constructor. You use the new operator with a constructor function to create a new object.

Subclasses and inheritance

In a class-based language, you create a hierarchy of classes through the class definitions. In a class definition, you can specify that the new class is a subclass of an already existing class. The subclass inherits all the properties of the superclass and additionally can add new properties or modify the inherited ones. For example, assume the Employee class includes only the name and dept properties, and Manager is a subclass of Employee that adds the reports property. In this case, an instance of the Manager class would have all three properties: name, dept, and reports.

JavaScript implements inheritance by allowing you to associate a prototypical object with any constructor function. So, you can create exactly the Employee — Manager example, but you use slightly different terminology(術語). First you define the Employee constructor function, specifying the name and dept properties. Next, you define the Manager constructor function, calling the Employee constructor and specifying the reports property. Finally, you assign a new object derived from Employee.prototype as the prototype for the Manager constructor function. Then, when you create a new Manager, it inherits the name and dept properties from the Employee object.

Adding and removing properties

In class-based languages, you typically create a class at compile time and then you instantiate instances of the class either at compile time or at run time. You cannot change the number or the type of properties of a class after you define the class. In JavaScript, however, at run time you can add or remove properties of any object. If you add a property to an object that is used as the prototype for a set of objects, the objects for which it is the prototype also get the new property.

Summary of differences

The following table gives a short summary of some of these differences. The rest of this chapter describes the details of using JavaScript constructors and prototypes to create an object hierarchy and compares this to how you would do it in Java.

Comparison of class-based (Java) and prototype-based (JavaScript) object systems

Class-based (Java) Prototype-based (JavaScript)
Class and instance are distinct entities. All objects can inherit from another object.
Define a class with a class definition; instantiate a class with constructor methods. Define and create a set of objects with constructor functions.
Create a single object with the new operator. Same.
Construct an object hierarchy by using class definitions to define subclasses of existing classes. Construct an object hierarchy by assigning an object as the prototype associated with a constructor function.???
Inherit properties by following the class chain. Inherit properties by following the prototype chain.
Class definition specifies all properties of all instances of a class. Cannot add properties dynamically at run time. Constructor function or prototype specifies an initial set of properties. Can add or remove properties dynamically to individual objects or to the entire set of objects.

The employee example

The remainder of this chapter uses the employee hierarchy shown in the following figure.
A simple object hierarchy with the following objects:

  • Employee has the properties name (whose value defaults to the empty string) and dept (whose value defaults to “general”).

  • Manager is based on Employee. It adds the reports property (whose value defaults to an empty array, intended to have an array of Employee objects as its value).

  • WorkerBee is also based on Employee. It adds the projects property (whose value defaults to an empty array, intended to have an array of strings as its value).

  • SalesPerson is based on WorkerBee. It adds the quota property (whose value defaults to 100). It also overrides the dept property with the value “sales”, indicating that all salespersons are in the same department

  • Engineer is based on WorkerBee. It adds the machine property (whose value defaults to the empty string) and also overrides the dept property with the value “engineering”.

Creating the hierarchy

There are several ways to define appropriate constructor functions to implement the Employee hierarchy. How you choose to define them depends largely on what you want to be able to do in your application.

This section shows how to use very simple (and comparatively inflexible) definitions to demonstrate how to get the inheritance to work. In these definitions, you cannot specify any property values when you create an object. The newly-created object simply gets the default values, which you can change at a later time.

In a real application, you would probably define constructors that allow you to provide property values at object creation time (see More flexible constructors for information). For now, these simple definitions demonstrate how the inheritance occurs.

The following Java and JavaScript Employee definitions are similar. The only difference is that you need to specify the type for each property in Java but not in JavaScript (this is due to Java being a strongly typed language while JavaScript is a weakly typed language).

JavaScript
function Employee() {
  this.name = '';
  this.dept = 'general';
}
Java
public class Employee {
   public String name = "";
   public String dept = "general";
}

The Manager and WorkerBee definitions show the difference in how to specify the next object higher in the inheritance chain. In JavaScript, you add a prototypical instance as the value of the prototype property of the constructor function. You can do so at any time after you define the constructor. In Java, you specify the superclass within the class definition. You cannot change the superclass outside the class definition.

JavaScript
function Manager() {
  Employee.call(this);
  this.reports = [];
}

Manager.prototype = Object.create(Employee.prototype);

function WorkerBee() {
  Employee.call(this);
  this.projects = [];
}

WorkerBee.prototype =  Object.create(Employee.prototype);
Java
public class Manager extends Employee {
   public Employee[] reports = new Employee[0];
}

public class WorkerBee extends Employee {
   public String[] projects = new String[0];
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章