Examples of object encapsulation in JavaScript programming, and examples of javascript
1. prototype object
1.1 constructor disadvantages
JavaScript generates new objects through constructors, so constructors can be considered as Object Templates. The attributes and methods of the instance object can be defined within the constructor.
Function Cat (name, color) {this. name = name; this. color = color;} var cat1 = new Cat ('taobao', 'White '); cat1.name // 'taobao' cat1. color // 'White'
The Cat function in the code above is a constructor. The name and color attributes are defined in the function. All instance objects generate these two attributes. However, this is a waste of system resources because attributes cannot be shared between object instances of the same constructor.
Function Cat (name, color) {this. name = name; this. color = color; this. meow = function () {console. log ('mew, mew, mew... ') ;};} var cat1 = new Cat ('Big Mao', 'White '); var cat2 = new Cat ('second Mao', 'black '); cat1.meow === cat2.meow // false
In the code above, cat1 and cat2 are instances of the same constructor. However, their meow methods are different, that is, each time you create an instance, a new meow method is created. This is unnecessary and a waste of system resources, because all meow methods share the same behavior and should be completely shared.
1.2 role of the prototype attribute
In JavaScript, each object has a prototype object. All attributes and methods defined on the prototype object can be inherited by the derived object. This is the basic design of the JavaScript Inheritance Mechanism.
In addition to this method, JavaScript also provides another method for defining instance objects. We know that a constructor is a function, an object, and its own attributes and methods. One prototype attribute points to another object, which is generally called a prototype object. This object is very special. As long as the attributes and methods defined on it can be shared by all instance objects. That is, when the constructor generates an instance object, a prototype attribute is automatically assigned to the instance object.
Function Animal (name) {this. name = name;} Animal. prototype. color = "white"; var cat1 = new Animal ('hairy '); var cat2 = new Animal ('ermao'); cat1.color // 'white' cat2. color // 'white'
The code above adds a color attribute to the prototype object of the constructor Animal. As a result, the instance objects cat1 and cat2 both carry this attribute.
More specifically, as long as the prototype object is modified, the changes are immediately reflected in the instance object.
Animal.prototype.color = "yellow";cat1.color // 'yellow'cat2.color // 'yellow'
The code above changes the value of the color attribute of the prototype object to yellow, and the value of the color attribute of the two instance objects changes immediately. This is because the instance object does not actually have the color attribute and reads the color attribute of the prototype object. That is to say, when the instance object itself does not have a certain attribute or method, it will go to the prototype object of the constructor to find this attribute or method. This is a special feature of the prototype object.
If the instance object itself has an attribute or method, it will not search for this attribute or method from the prototype object.
cat1.color = 'black';cat2.color // 'yellow'Animal.prototype.color // "yellow";
The code above changes the color attribute of the Instance Object cat1 to black, so that it does not need to read the color attribute from the prototype object, and the latter value is still yellow.
All in all, the role of a prototype object is to define the attributes and Methods shared by all instance objects, so it is also called the prototype object, and the instance object can be seen as derived from the prototype object.
Animal.prototype.walk = function () { console.log(this.name + ' is walking.');};
The above Code defines a walk Method on the Animal. protype object. This method can be called on all Animal instance objects.
1.3 prototype chain
Because all objects in JavaScript have constructors, and all constructors have prototype attributes (in fact, all functions have prototype attributes), all objects have their own prototype objects.
Therefore, the attributes and methods of an object may be defined on its own, or on its prototype object (like the walk Method in the code above ). The prototype chain is formed because the prototype chain itself is an object and has its own prototype chain ). For example, object a is the prototype of object B, object B is the prototype of Object c, and so on. Because of tracing, the most source Object is generated from the Object constructor (using the new Object () Command). Therefore, if the Object is traced back layer by layer, all Object prototypes can be traced back to the Object. prototype. Does Object. prototype have a prototype? The answer is either yes or no, because the prototype of Object. prototype does not have any null attributes or methods.
Object.getPrototypeOf(Object.prototype)// null
The code above indicates that the prototype Object prototype is null. Since null does not have any attributes, the prototype chain ends here.
The role of "prototype chain" is that when reading an object's attributes, the JavaScript engine first looks for the attributes of the object. If it cannot be found, it searches for its prototype, if you still cannot find the prototype, you can find the prototype. Similarly, if the Object. prototype at the top is still not found, undefined is returned.
For example, if the prototype attribute of a function points to an array, it means that the function can be used as an array constructor, because all instance objects generated by the function can call the array method through the prototype attribute.
function MyArray (){}MyArray.prototype = new Array();MyArray.prototype.constructor = MyArray;var mine = new MyArray();mine.push(1, 2, 3);mine.length // 3mine instanceof Array // true
The above code mine is an instance object of MyArray. Because the prototype attribute of MyArray points to an array, mine can call the array method (these methods are actually defined on the prototype object of the array ). As for the last line of the instanceof expression, we know that the instanceof operator is used to compare whether an object is an instance of a constructor, And the last line is an instance of Array.
Mine instanceof Array // equivalent to (Array = MyArray. prototype. constructor) | (Array = Array. prototype. constructor) | (Array = Object. prototype. constructor)
The above code illustrates the essence of the instanceof operator, which is compared with the constructor attributes of all prototype objects of the Instance Object in sequence (for details about this attribute, refer to the next section, true is returned if one of them meets the condition. Otherwise, false is returned.
1.4 constructor attributes
The prototype object has a constructor attribute, which defaults to the constructor of the prototype object.
function P() {}P.prototype.constructor === P// true
Since the constructor attribute is defined on the prototype object, it means that it can be inherited by all instance objects.
function P() {}var p = new P();p.constructor// function P() {}p.constructor === P.prototype.constructor// truep.hasOwnProperty('constructor')// false
The code above indicates that p is the Instance Object of constructor P, but p itself does not have the contructor attribute. This attribute is actually the P. prototype. constructor attribute on the prototype chain.
The constructor attribute is used to determine which constructor the prototype object is defined on.
function F(){};var f = new F();f.constructor === F // truef.constructor === RegExp // false
The code above indicates that the constructor attribute is used to determine that the constructor of variable f is F rather than RegExp.
2. Object. getPrototypeOf Method
The Object. getPrototypeOf method returns the prototype of an Object.
// The prototype of the empty Object is Object. prototypeObject. getPrototypeOf ({}) === Object. prototype // true // the prototype of the Function is Function. prototypefunction f () {} Object. getPrototypeOf (f) === Function. prototype // true // assume that F is the constructor and f is the Instance Object //, then the prototype of F is f. prototypevar f = new F (); Object. getPrototypeOf (f) = F. prototype // true
3. Object. create method
The Object. create method is used to generate a new Object, which can replace the new command. It accepts an object as a parameter and returns a new object, which fully inherits the attributes of the former, that is, the former becomes the prototype of the latter.
var o1 = { p: 1 };var o2 = Object.create(o1);o2.p // 1
In the above Code, the Object. create method generates o2 Based on o1. In this case, o1 becomes the prototype of o2, that is, o2 inherits all the attributes of o1.
The Object. create method is basically equivalent to the following code. If the old-fashioned browser does not support the Object. create method, you can use the following code to deploy it yourself.
if (typeof Object.create !== "function") { Object.create = function (o) { function F() {} F.prototype = o; return new F(); };}
The code above indicates that Object. in essence, the create method creates a constructor F, then directs the prototype attribute of F to the prototype object o, and finally returns an instance of F, so that the instance inherits the o attribute.
The new objects generated in the following three methods are equivalent.
var o1 = Object.create({});var o2 = Object.create(Object.prototype);var o3 = new Object();
If you want to generate an Object that does not inherit any attributes (such as the toString and valueOf methods), you can set the Object. create parameter to null.
var o = Object.create(null);o.valueOf()// TypeError: Object [object Object] has no method 'valueOf'
The code above indicates that if the prototype of the Object o is null, it does not have some attributes defined on the Object. prototype Object, such as the valueOf method.
The Object prototype must be provided when the Object. create method is used. Otherwise, an error is returned.
Object.create()// TypeError: Object prototype may only be an Object or null
The new Object generated by the Object. create method dynamically inherits the prototype. Adding or modifying any method on the prototype is immediately reflected on the new object.
var o1 = { p: 1 };var o2 = Object.create(o1);o1.p = 2;o2.p// 2
The code above indicates that modifying the object prototype will affect the newly generated object.
In addition to the Object prototype, the Object. create method can also accept the second parameter, indicating the attributes Object describing the attribute. The format used in the Object. defineProperties method is the same. The property of the object described by it will be added to the new object.
var o = Object.create(Object.prototype, { p1: { value: 123, enumerable: true }, p2: { value: "abc", enumerable: true }});o.p1 // 123o.p2 // "abc"
Because the Object. create method does not use constructors, you cannot use the instanceof operator to determine which constructor the Object is. In this case, you can use the isPrototypeOf method below to determine which object the prototype is.
4. isPrototypeOf Method
The isPrototypeOf method is used to determine whether an object is a prototype of another object.
var o1 = {};var o2 = Object.create(o1);var o3 = Object.create(o2);o2.isPrototypeOf(o3) // trueo1.isPrototypeOf(o3) // true
The code above indicates that isProtypeOf returns true if an object is in the prototype chain.
5. A simple example
Var ClassDemo = function () {// static private variable var private_static_var = 'aaa'; // static private method var private_static_func = function (key) {return key + private_static_var ;} // private method. The key is to pass this var private_func = function (self, key) {return private_static_func (key + self. id);} var _ class = function (id) {// constructor this. id = id; // public variable} // public method_class. prototype. public_func = function (key) {return private_func (this, key);} return _ class;} (); var a = new ClassDemo ('Hello World'); alert (. public_func ('World hello '));
There is no simple way to implement private variables and public static variables/methods, but it is sufficient to encapsulate them to this extent.