Instance Explanation of Implementing Object Encapsulation in JavaScript Programming

  • 2021-06-29 10:14:58
  • OfStack

1.prototype object
Disadvantages of 1.1 constructors
JavaScript generates new objects through constructors, so constructors can be considered templates for objects.The properties and methods of the instance object can be defined inside the constructor.


function Cat (name, color) {
 this.name = name;
 this.color = color;
}

var cat1 = new Cat(' Big hair ', ' white ');

cat1.name // ' Big hair '
cat1.color // ' white '

The Cat function in the code above is a constructor that defines the name and color properties internally, which are generated by all instance objects.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 hair ', ' white ');
var cat2 = new Cat('2 hair ', ' 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 new instance creates a new meow method.This is both unnecessary and a waste of system resources, since all meow methods behave the same and should be shared entirely.

1.2 Role of the prototype attribute
In the JavaScript language, each object has a corresponding prototype object, called an prototype object.All properties 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 provides another way to define instance objects.As we know, a constructor is a function as well as an object. It also has its own properties and methods, with one prototype attribute pointing to another object, which is commonly referred to as an prototype object.This object is very special, as long as the properties and methods defined on it can be shared by all instance objects.That is, when the constructor generates an instance object, an prototype attribute is automatically assigned to the instance object.


function Animal (name) {
 this.name = name;
}

Animal.prototype.color = "white";

var cat1 = new Animal(' Big hair ');
var cat2 = new Animal('2 hair ');

cat1.color // 'white'
cat2.color // 'white'

The code above adds an color attribute to the prototype object of the constructor Animal.As a result, the instance objects cat1 and cat2 both have this attribute.

More specifically, as soon 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 property of the prototype object to yellow, and the value of the color property of the two instance objects changes immediately.This is because the instance object does not actually have the color attribute, which is the color attribute that reads the prototype object.That is, when the instance object itself does not have a property or method, it goes to the prototype object of the constructor to find that property or method.This is what makes the prototype object special.

If an instance object has a property or method of its own, it will not go to the prototype object to look for that property or method.


cat1.color = 'black';

cat2.color // 'yellow'
Animal.prototype.color // "yellow";

The code above changes the color property of the instance object cat1 to black so that it no longer has to read the color property from the prototype object, which still has the value yellow.

In short, the role of the prototype object is to define the properties and methods shared by all the instance objects, so it is also called the prototype of the instance object, which can be thought of as deriving from the prototype object.


Animal.prototype.walk = function () {
 console.log(this.name + ' is walking.');
};

The code above defines an walk method on the Animal.protype object that can be called on all Animal instance objects.

1.3 Prototype Chain
Since all objects of JavaScript have constructors and all constructors have prototype properties (all functions actually have prototype properties), all objects have their own prototype prototype objects.

Therefore, the properties and methods of an object may be defined either on its own or on its prototype object (like the walk method in the code above).Since the prototype itself is an object and has its own prototype, it forms a chain of prototypes (prototype chain).For example, the a object is the prototype of the b object, the b object is the prototype of the c object, and so on.Since the most sourced objects are generated from the Object constructor (using the new Object () command), if you go upstream one layer at a time, the prototypes of all objects can ultimately go back to Object.prototype.So does Object.prototype have a prototype?The answer can be yes or no, because the prototype of Object.prototype is null without any attributes or methods.


Object.getPrototypeOf(Object.prototype)
// null

The code above indicates that the prototype of the Object.prototype object is null, and since null has no attributes, the prototype chain ends there.

The purpose of the Prototype Chain is that when reading an object's properties, the JavaScript engine first looks for the properties of the object itself. If it cannot be found, it looks for its prototype. If it cannot be found, it looks for its prototype.By analogy, if Object.prototype is not found up to the top level, then undefined is returned.

For example, if a function's prototype property points to an array, that means the function can be used as a constructor of the array because the instance object it generates can call array methods through the prototype property.


function MyArray (){}

MyArray.prototype = new Array();
MyArray.prototype.constructor = MyArray;

var mine = new MyArray();
mine.push(1, 2, 3);

mine.length // 3
mine instanceof Array // true

The mine in the code above is an instance object of MyArray, and since the prototype property of MyArray points to an array, mine can invoke array methods that 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 mine.


mine instanceof Array

//  Equivalent to 

(Array === MyArray.prototype.constructor) ||
(Array === Array.prototype.constructor) ||
(Array === Object.prototype.constructor )

The code above illustrates the nature of the instanceof operator, which in turn compares to the constructor property of all the prototype objects of the instance object (see section 1 for an introduction to this property), returning true if one conforms, false otherwise.

1.4 constructor attribute
The prototype object has an constructor attribute, which by default points to the constructor in which the prototype object resides.


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 Cat(name, color) {
 this.name = name;
 this.color = color;
 this.meow = function () {
 console.log('mew, mew, mew...');
 };
}

var cat1 = new Cat(' Big hair ', ' white ');
var cat2 = new Cat('2 hair ', ' black ');

cat1.meow === cat2.meow
// false

0

The code above indicates that p is an instance object of the constructor P, but p itself does not have the contructor attribute, which in fact reads the P.prototype.constructor attribute on the prototype chain.

The purpose of the constructor attribute is to distinguish which constructor the prototype object is defined on.


function Cat(name, color) {
 this.name = name;
 this.color = color;
 this.meow = function () {
 console.log('mew, mew, mew...');
 };
}

var cat1 = new Cat(' Big hair ', ' white ');
var cat2 = new Cat('2 hair ', ' black ');

cat1.meow === cat2.meow
// false

1

The code above indicates that, using the constructor attribute, the constructor for the variable f is F, not RegExp.

2.Object.getPrototypeOf method
The Object.getPrototypeOf method returns the prototype of an object.


function Cat(name, color) {
 this.name = name;
 this.color = color;
 this.meow = function () {
 console.log('mew, mew, mew...');
 };
}

var cat1 = new Cat(' Big hair ', ' white ');
var cat2 = new Cat('2 hair ', ' black ');

cat1.meow === cat2.meow
// false

2

3. Object.create method
The Object.create method is used to generate new objects and can replace the new command.It accepts an object as a parameter and returns a new object, which fully inherits the properties 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 code above, the Object.create method generates o2 on the basis of o1.At this time, o1 became the prototype of o2, that is, o2 inherits the methods of all the properties of o1.

The Object.create method is essentially the same as the code below. If an older browser does not support the Object.create method, you can deploy it yourself with the code below.


function Cat(name, color) {
 this.name = name;
 this.color = color;
 this.meow = function () {
 console.log('mew, mew, mew...');
 };
}

var cat1 = new Cat(' Big hair ', ' white ');
var cat2 = new Cat('2 hair ', ' black ');

cat1.meow === cat2.meow
// false

4

The code above indicates that the Object.create method essentially creates a new constructor, F, then points the prototype attribute of F to the object o as a prototype, and returns an instance of F, thereby enabling the instance to inherit the o attribute.

The new objects generated in the following three ways are equivalent.


function Cat(name, color) {
 this.name = name;
 this.color = color;
 this.meow = function () {
 console.log('mew, mew, mew...');
 };
}

var cat1 = new Cat(' Big hair ', ' white ');
var cat2 = new Cat('2 hair ', ' black ');

cat1.meow === cat2.meow
// false

5

If you want to generate an object that does not inherit any properties, such as the toString and valueOf methods, you can set the Object.create parameter to null.


function Cat(name, color) {
 this.name = name;
 this.color = color;
 this.meow = function () {
 console.log('mew, mew, mew...');
 };
}

var cat1 = new Cat(' Big hair ', ' white ');
var cat2 = new Cat('2 hair ', ' black ');

cat1.meow === cat2.meow
// false

6

The code above indicates that if the object o is prototyped as null, it does not have some properties defined on the Object.prototype object, such as the valueOf method.

When using the Object.create method, you must provide an object prototype or you will get an error.


function Cat(name, color) {
 this.name = name;
 this.color = color;
 this.meow = function () {
 console.log('mew, mew, mew...');
 };
}

var cat1 = new Cat(' Big hair ', ' white ');
var cat2 = new Cat('2 hair ', ' black ');

cat1.meow === cat2.meow
// false

7

The new object generated by the Object.create method dynamically inherits the prototype.Adding or modifying any method on the prototype will immediately be 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 affects the newly generated object.

In addition to the prototype of the object, the Object.create method accepts the second parameter, which represents the attributes object describing the attribute in the same format as the Object.defineProperties method.The object properties it describes are added to the new object.


function Cat(name, color) {
 this.name = name;
 this.color = color;
 this.meow = function () {
 console.log('mew, mew, mew...');
 };
}

var cat1 = new Cat(' Big hair ', ' white ');
var cat2 = new Cat('2 hair ', ' black ');

cat1.meow === cat2.meow
// false

9

Since the Object.create method does not use a constructor, it is not possible to use the instanceof operator to determine which instance of the constructor the object is.In this case, the following isPrototypeOf method can be used to interpret which object the prototype is.

4. isPrototypeOf method
The isPrototypeOf method is used to determine whether one object is a prototype of another.


var o1 = {};
var o2 = Object.create(o1);
var o3 = Object.create(o2);

o2.isPrototypeOf(o3) // true
o1.isPrototypeOf(o3) // true

The code above indicates that isProtypeOf returns true as long as an object is in the prototype chain.

5.1 simple examples


var ClassDemo = function () {

 // static state private variable 
 var private_static_var = 'aaaa';

 // static state private Method 
 var private_static_func = function (key) { 
  return key + private_static_var;
 }

 //private Method, the key is 1 parameter self To pass in 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(a.public_func('world hello'));

There is no easy way to implement the private variable and the public static variable/method, but encapsulating them to this extent is enough


Related articles: