Javascript Object Oriented Programming (Part 1): Encapsulation
Taken from: http://www.ruanyifeng.com/blog/2010/05/object-oriented_javascript_encapsulation.html Javascript Object Oriented Programming (1): Encapsulation Author: Ruan Yifeng Javascript is an object-based language where almost everything you encounter is an object. However, it is not a true object-oriented programming (OOP) language because its syntax does not include classes. So, what should we do if we want to encapsulate “property” and “method” into one object, or even generate an instance object from the prototype object? one The original pattern for generating objects assumes that we treat cats as objects with two attributes: “name” and “color”. Var Cat={name: ‘’, color: ‘’} Now, we need to generate two instance objects based on this prototype object. Var cat1={}; //Or var cat1=new Object (); Cat1. name=”Big Hair”; cat1. color=”Yellow”; var cat2={}; cat2. name=”Two Hair”; cat2. color=”Black”; Alright, this is the simplest encapsulation. However, this writing method has two drawbacks: first, if multiple instances are generated, it will be very troublesome to write; second, there is no way to see any connection between instances and prototypes We can write a function to improve the original pattern and solve the problem of code duplication. //using Literal Notation function Cat(name,color){ return { name:name, color:color } } Then generate an instance object, which is equivalent to calling functions: var cat1=Cat (“Big Hair”, “Yellow”); var cat2=Cat (“Two Hair”, “Black”); the problem with this method is still that there is no inherent connection between cat1 and cat2, which cannot reflect that they are instances of the same prototype object. three In order to solve the problem of generating instances from prototype objects, Javascript provides a Constructor pattern. The so-called ‘constructor’ is actually a regular function that uses the ‘this’ variable internally. By using the new operator on the constructor, an instance can be generated, and the ‘this’ variable will be bound to the instance object. For example, the prototype object of a cat can now be written as follows: function Cat(name,color){ this.name=name; this.color=color; } We can now generate instance objects. Var cat1=new Cat (“Big Hair”, “Yellow”); var cat2=new Cat (“Second Hair”, “Black”); alert (cat1. name);//Big Hair alert (cat1. color); //At this point, cat1 and cat2 will automatically contain a constructor attribute pointing to their constructors. Alert (cat1. constructor==Cat); //true alert(cat2.constructor == Cat); //True Javascript also provides an instanceof operator to validate the relationship between prototype objects and instance objects. Alert (cat1 instance of Cat); //true alert(cat2 instanceof Cat); //True 4. The problem with constructor mode is that constructor methods are very useful, but there is a memory waste issue. Please see, we are now adding an invariant attribute “type” (type) to the Cat object, and adding a method eat (eat mouse). So, the prototype object Cat becomes like this: function Cat(name,color){ this.name = name; this.color = color; this.type = “ Feline animals “; this. eat=function() {alert (“ eating mice “);};} Using the same method, generate instances: var cat1=new Cat (“ big fur “,” yellow “); var cat2=new Cat (“ two fur “,” black “); alert (cat1. type);//Feline animal cat1. eat(); //Eating mice may seem fine on the surface, but in reality, there is a major drawback to doing so. That is, for each instance object, the type attribute and the eat () method are identical. Every time an instance is generated, it must occupy more memory for the duplicate content. This is neither environmentally friendly nor efficient. Alert (cat1.eat==cat2.eat); //Can false allow the type attribute and eat() method to be generated only once in memory, and then all instances point to that memory address? The answer is yes. five The Prototype pattern in Javascript specifies that each constructor has a prototype property that points to another object. All properties and methods of this object will be inherited by the instance of the constructor. This means that we can directly define those invariant properties and methods on the prototype object. function Cat(name,color){ this.name = name; this.color = color; } Cat.prototype.type = “ Feline animals “; Cat. prototype. eat=function() {alert (“ eating mice “)}; then, generate instances. var cat1=new Cat (“ big fur “,” yellow “); var cat2=new Cat (“ two fur “,” black “); alert (cat1. type);//Feline animal cat1. eat(); //When eating mice, the type attribute and eat() method of all instances are actually a memory address pointing to the prototype object, thus improving running efficiency. Alert (cat1.eat==cat2.eat); //True 6. Validation method for Prototype pattern 6.1 isPrototypeOf() This method is used to determine the relationship between a prototype object and an instance. Alert (Cat. prototype. isPrototypeOf (cat1)); //true alert(Cat.prototype.isPrototypeOf(cat2)); //True 6.2 hasOwnProperty () Each instance object has a hasOwnProperty () method, which is used to determine whether a property is a local property or inherits from a property of the prototype object. Alert (cat1. hasOwnProperty (“name”)); // true alert(cat1.hasOwnProperty(“type”)); //The false 6.3 in operator can be used to determine whether an instance contains a certain property, whether it is a local property or not. Alert (“name” in cat1); // true alert(“type” in cat1); //The true in operator can also be used to traverse all properties of an object. For (var prop in cat1) {alert (“cat1 [“+prop+”]=”+cat1 [prop]);} (End)