This article introduces to you the analysis of encapsulation in JS object-oriented programming. It has certain reference value. Friends in need can refer to it. I hope it will be helpful to you.
Our well-known object-oriented languages such as C and Java all have the concept of classes. Classes are type templates of instances. For example, Student
represents the type of student, not Represents any specific student, and the instance is a specific object created based on this type, such as zhangsan
, lisi
. The object generated by the class embodies the transformation from abstract template to concrete Process, this is called Class-based object-oriented approach, and JavaScript does not have the concept of classes, it is Prototype-based object-oriented approach (Although Es6 adds class
, The essence is to encapsulate the prototype method). To sum up, the following two points are:
In the class-based object-oriented approach, objects (objects) rely on classes (classes) to generate.
In the prototype-based object-oriented approach, objects are constructed by relying on constructors and prototypes.
The first feature of object-oriented language is undoubtedly encapsulation. In JS, the process of encapsulation is to "wrap" some properties and methods into objects, then we How to encapsulate properties and methods, or how to create objects (hereinafter, we will talk about creating objects)? The following is explained in a step-by-step manner:
Object literal--> Factory pattern--> Constructor--> Prototype pattern--> Constructor prototype model
There are two primitive ways to create objects in JS:
Object literal
var person = { name: "leon", age: "20", greeting: function() { alert('Hi!'); } }
Add attribute methods to Object
instances
var person = new Object(); person.name = "leon"; person.age = "20"; person.greeting = function() { alert('Hi!'); };
Advantages: Simple code
Disadvantages: Creating multiple objects will generate a lot of code, which is troublesome to write, and there is no concept of instances and prototypes.
Solution: Factory pattern.
The factory pattern is a well-known design pattern in the programming field, which abstracts the process of creating specific objects. Create a function in JS and put the process of creating new objects, adding object properties, and returning objects into this function. Users only need to call the function to generate objects without paying attention to the details of object creation. This is called the factory pattern:
function createPerson(name, age) { var person = new Object(); person.name = name; person.age = age; person.greeting = function() { alert('Hi!'); }; } var person1 = createPerson("leon", "20");
Advantages: The factory pattern solves the problem of duplication of code for creating objects using object literals. The same API can be used to create similar objects.
Disadvantages: Because the object is created by calling a function, the type of the object cannot be identified.
Solution: Constructor function
The only difference between the constructor function and other functions in JS is that The way it is called is different. Any function can be used as a constructor as long as it is called through the new
operator. Let’s look at the following example:
function Person(name, age) { this.name = name; this.age = age; this.greeting = function() { alert('Hi!'); }; // return this; } var person1 = new Person("leon", "20"); var person2 = new Person("jack", "21");
Through the constructor new
An instance goes through four steps:
Create a new object;
Bind this
in the constructor to the new object;
Add properties and methods to the new object;
Return a new object (JS engine will add return this;
by default).
The objects created through the constructor have a constructor
attribute, which is a pointer to the constructor itself, so the type of the object can be detected. :
alert(person1.constructor === Person) //true alert(person1 instanceof Person) // true
But there is still a problem:
alert(person1.greeting == person2.greeting) //false
greeting()
is defined in the same constructor, but functions with the same name on different instances are not equal, This means that the memory spaces of the two functions with the same name are inconsistent, that is, the method in the constructor must be recreated on each instance. This is obviously not cost-effective.
Advantages: Solve similar object creation problems and can detect object types.
Disadvantages: The constructor method needs to be created once on each instance.
Solution: Prototype mode.
Finally talked about the prototype pattern. Each constructor in JS has a prototype
attribute, which is a pointer. Points to the prototype object, which contains the properties and methods shared by all instances of this constructor. There is a <em>proto</em>
attribute in the instance object, which points to the prototype object, that is, constructor.prototype == prototype object == object._proto_
, then the object You can get the properties and methods in the prototype object. At the same time, all objects have a constructor
attribute, and the constructor
of the prototype object points to its corresponding constructor.
使用原型,就意味着我们可以把希望实例共享的属性和方法放到原型对象中去,而不是放在构造函数中,这样每一次通过构造函数new
一个实例,原型对象中定义的方法都不会重新创建一次。来看下面的例子:
function Person() { } Person.prototype.name = "leon"; Person.prototype.age = "20"; Person.prototype.greeting = function() { alert('Hi!'); }; var person1 = new Person(); var person2 = new Person(); alert(person1.name); //"leon" alert(person2.name); //"leon" alert(person1.greeting == person2.greeting); //true
优点:与单纯使用构造函数不一样,原型对象中的方法不会在实例中重新创建一次,节约内存。
缺点:使用空构造函数,实例 person1 和 person2 的 name
都一样了,我们显然不希望所有实例属性方法都一样,它们还是要有自己独有的属性方法。
解决办法:构造函数+原型模式组合使用。
另外 JS 中还定义了一些与原型相关的属性,这里罗列一下:
Object.getPrototypeOf()
,取得实例的原型对象。
Object.getPrototypeOf(person1);
isPrototypeOf()
,判断是不是一个实例的原型对象。
Person.prototype.isPrototypeOf(person1);
hasOwnProperty()
,检测一个属性是否存在于实例中
person1.hasOwnProperty("name");
in
,判断一个属性是否存在于实例和原型中。
"name" in person1;
最后一种方式就是组合使用构造函数和原型模式,构造函数用于定义实例属性,而共享属性和方法定义在原型对象中。这样每个实例都有自己独有的属性,同时又有对共享方法的引用,节省内存。
function Person(name, age) { this.name = name; this.age = age; } Person.prototype = { constructor: Person, nationality: "China", greeting: function() { alert(this.name); } } var person1 = new Person("leon", "20"); var person2 = new Person("jack", "21"); alert(person1.greeting == person2.greeting) //true
上面代码中用对象字面量的形式重写了原型对象,这样相当于创建了一个新的对象,那么它的constructor
属性就会指向Object
,这里为了让它继续指向构造函数,显示的写上了constructor: Person
这种构造函数与原型模式混成的模式,是目前在 JS 中使用最为广泛的一种创建对象的方法。
相关文章推荐:
The above is the detailed content of Analysis of encapsulation in JS object-oriented programming. For more information, please follow other related articles on the PHP Chinese website!