Discuss the ways to implement classes in JavaScript
There are many ways to create objects in JavaScript, so the way to create objects is very flexible. So, which way is the most appropriate way to create objects? Construction
pattern, prototype pattern or object literal pattern?
But what exactly are these modes?
Before we start to explain, let us clearly introduce the basic knowledge about javascript.
Is it possible to implement object-oriented programming in javascript?
The answer is possible, javascript can create objects! Such objects can contain data and methods that can manipulate the data, and can even contain other objects. It has no classes but has constructors; it has no class inheritance mechanism, but inheritance can be achieved through prototypes.
Now it seems that we have understood the necessary components to create objects and implement object-based programming in javascript.
We all know that javascript has private variables. A variable defined through the "var" keyword can only be accessed within the function body and cannot be accessed outside the function. So, what happens if
we don’t define variables by using the “var” keyword? We will not discuss this issue in depth now. It may be accessed through "this". I will talk about this issue in detail at another time.
Now back to the previous question. Which method is the most appropriate way to create objects?
Let us use the knowledge we already know and try it out by creating a Person object.
[javascript]
var Person = {
firstName : 'John',
lastName : 'Cody',
fullName : '',
message : '',
createFullName : function () {
using using using using using using through out using off ‐ ‐ ‐ ‐ ‐‐‐‐‐ , },
getMessage )
Person.lastName = ' Flowers'
Person.changeMessage('welcome');
var message = Person.getMessage(); // welcome Eli Flowers
alert(message);
This is the literal pattern of the object. This is very close to how we usually create objects. If you don't need to care about private/wrapped members, and you know that no instances of this object will be created. Then this method will suit you very well. Public members can do everything private members can do, right? However, this is not a class, but an object. It cannot be instanced and cannot be inherited.
Let’s try something else:
[javascript]
var Person = function() {
this.firstName = 'John';
this.lastName = 'Cody';
var fullName = ';
' ' + _that.lastName;
}
this.changeMessage = function (msg) {
this.message = msg;
}
this.getMessage = function () {
creatingFullName(); message + ' ' + fullName;
}
}
var person1 = new Person();
person1.firstName = 'Eli';
person1.lastName = 'Flowers'
person1. changeMessage('welcome');
var message = person1.getMessage(); // welcome Eli Flowers
alert(message);
This is an instance of the constructor pattern (Constructor Pattern). So, is this a class or an object? It should be considered both. We can treat it as an object Person when requesting
To use. After all, it is just a function. However, it is possible to create new instances using the "new" keyword.
When using this method, we need to always remember the following points:
1. Whenever this function is called, it has a special variable called "this" and it can be in the global scope use. The global scope depends on the scope of the function itself.
2. Whenever an instance of this function is created through the "new" keyword, the "this" variable points to the function itself, and this "new" operation will affect the code in the function body
be executed. This is also the construction pattern.
3. Any variables attached to the "this" variable will become public properties and any variables defined through the "var" keyword will be private properties.
4. A function attached to "this" is called a privileged function. It can access all private variables and functions and variables attached to "this".
5. Private functions can access other private variables and private functions.
6. Private functions cannot directly access variables and functions attached to "this". We can do this by creating a private variable "_that" and assigning it the value "this".
7. Any private variables and functions are available to other private functions and other functions attached to "this". This is entirely possible within the scope of JavaScript.
8. A variable: not through the "var" keyword, nor attached to the "this" variable to obtain global scope. For example, for the scope of a custom function. Need
to understand the knowledge of scope and cluster again.
This has achieved most of what we want, but sometimes the two entry variables "this" and "that" can easily cause confusion to people. Especially for those who have always insisted on pure private ownership, it is easier to be confused.
Let’s try it with a little modification.
[javascript]
var Person = function () {
//private
var firstName = 'John';
var lastName = 'Cody';
var fullName = '';
var message = ';
' //public setters
var setMessage = function (msg ) {
message =
var setLastName = function (lName) {
lastName = lName; "
//functions exposed public
return {
setFirstName: setFirstName,
setLastName: setLastName,
setMessage: setMessage,
.
var person1 = new Person(); person1.setFirstName(' Eli'); person1.setLastName('Flowers'); person1.setMessage('welcome'); var message = person1.getMessage(); // welcome Eli Flowers alert(message); This is a Revealing Pattern. Many thanks to Christian Heilmann. The way to use this pattern is to use the "getters" and "setters" of the request as properties. Many of us have found this figure from traditional Java programming and it is obvious that implementing it is not complicated. This is also a situation similar to when a class inherits from an interface. Most aspects of this model are implemented well, with only one very minor problem. Every time an instance of a class is created. This newly created object gets a copy of variables and functionsCopy. Now, there is no problem in copying variables. We hope that the data of each object belongs to the object itself. So, what about the member functions? They just manipulate data
. So, why do you need to copy them?
This is the advantage of Prototype. In all instances, everything is created as a prototype and can be shared with each other. All we need to do is create a public function based on the prototype.
[javascript]
var Person = function () {
//private
var welcomeMessage = 'welcome';
var fullName = '';
var firstName = '';
var lastName = "";
var createFullName = function () {
Person.prototype.setFirstName('asdsad');
fullName = firstName + ' ' + lastName;
};
//constructor
var Person = function () { }; //will be created evrytime
//public
Person.prototype = {
getFullName: function () {
createFullName();
return welcomeMessage + ' ' + fullName;
},
setFirstName: function (fName) {
1stName = fName; (lName) {
lastName = )
var person1 = new Person();
person1.setFirstName ('Eli');
person1.setLastName('Flowers');
person1.ChangeMessage('welcome');
var message = person1.getFullName() ; // welcome asdsad Flowers
alert(message);
A problem with the prototype pattern is that it cannot access private variables and private functions. It is because of this problem that we will introduce closures and always organize the creation of classes The code exists so that
it doesn’t get messy globally. All are within the scope of the Person class.
Another problem is that every time an instance is created, all the code is executed, including prototype binding. For some of us, it's simply a matter of efficiency.
One way to deal with this problem is to only bind the prototype when the expected public function is not available.
This will cause the prototype binding operation to be performed only when the first instance is created, and after that all other instances will only be checked. Unfortunately, this still cannot solve the problem we mentioned in the above example, because we can only create a new function to generate a closure to achieve the effect of this class. In this case, at least we reduce
some memory usage.
Wait, there is another problem is that private functions cannot directly access prototype functions.
Why do you need private functions and private variables? I know you must want to achieve the encapsulation of the class, and want to ensure that the attributes or internal data in the class will not be suddenly modified or modified by other internal programs, or any other operations...
You should remember that you cannot compile javascript code into binary, which may be annoying to you to a certain extent, so that the code is always available. So, if
anyone wants to mess with the code, whether you are truly private or not, whether you give the code to other members of the team or sell it, they can mess with the code. Realizing
privatization may help a little bit.
Another technique used by other programmers is to use convention naming, prefixing anything you want to make private with an underscore "_" to specify that it should be private.
[javascript]
(function () {
var Person = function () {
this._fullName = '';
this.welcomeMessage = '';
this.firstName = '';
this.lastName = "";
_that = this;
this._createFullName = function () {
this.ChangeMessage('Namaste');
this._fullName = this.firstName + ' ' + this.lastName;
};
}
//Shared Functions for Code optimization
Person.prototype = {
constructor: Person,
getFullName: function () {
this._createFullName();
return this.welcomeMessage + ' ' + this._fullName;
},
ChangeMessage: function (mesg) {
this.welcomeMessage = mesg;
}
}
this.Person = Person;
})();
var person1 = new Person();
person1.firstName = 'Eli';
person1.lastName = 'Flowers';
person1.ChangeMessage('Welcome');
var message = person1.getFullName(); // Namaste Eli Flowers
alert(message);
我不是说你不应该考虑 “private” 或者类似的知识。你是代码的设计者,所以你将知道怎么来管理并且知道怎么做才是最好的。根据你的
需求,你可以使用任何一种设计模式或者多个设计模式组合一起使用。
无论你决定采用哪种设计模式,始终记住做尽量少的事情,不要在全局作用范围内实现闭包,尽量减少内存泄露,以及优化代码,并且组织好
代码。所以,尽量多了解些作用域,闭包以及 “this” 的表现行为。
最后,祝编程愉快!
译后感
经常使用 javascript,对于它的印象一直都是直接拷贝过来就可以用的。最近使用 extjs,它的类框架非常好用。从这样文章也明白在
javascript 中实现类的各种方式,以及在文章最后讨论了类中私有成员的实现情况。