Introduction
JavaScript (JS) is a prototype-based scripting language that is dynamic, weakly typed and has first-class functions. At present JavaScript is becoming a more and more popular language. It was originally implemented as part of web browsers so that client-side scripts may interact with the user, control the browser, but now it can be used to write code for server side (Node.Js) or even can be used in databases to write queries (NoSQL).
JavaScript is a very flexible programming language. It can be easily extended with new features which are used in other programming languages.
As it was mentioned before, JavaScript is a prototype based scripting language. A prototype is an object and every created function automatically gets a prototype property that points to a new blank object. In earlier versions of JavaScript created objects were vulnerable, because they could be modified at any time accidentally or on purpose. In some cases it’s an advantage, but when it comes to writing libraries it is a hude disadvantage.
Situation changed when ECMAScript 5 version was released. It included many cool features, which allow to have flexibilty and create more reliable and steady libraries. It allows to implement open/close principle: “A module should be open for extension but closed for modifications”. It means that if client programmer wants to extend an existing object he must create his own derived object.
JavaScript is a very flexible programming language. It can be easily extended with new features which are used in other programming languages.
As it was mentioned before, JavaScript is a prototype based scripting language. A prototype is an object and every created function automatically gets a prototype property that points to a new blank object. In earlier versions of JavaScript created objects were vulnerable, because they could be modified at any time accidentally or on purpose. In some cases it’s an advantage, but when it comes to writing libraries it is a hude disadvantage.
Situation changed when ECMAScript 5 version was released. It included many cool features, which allow to have flexibilty and create more reliable and steady libraries. It allows to implement open/close principle: “A module should be open for extension but closed for modifications”. It means that if client programmer wants to extend an existing object he must create his own derived object.
How to define a class in JavaScript?
There are no classes in JavaScript, because JavaScript is not a type based language like java or C#. Classes can be emulated in JavaScript. They are useful when you need to write complex applications.
First of all let’s create a class using JavaScript basic features and then optimize the same code with class4js library.
One of most important ECMAScript 5 addition was ‘strict mode’, which actually removes features from the language, making the program simpler and less error-prone. If you want to exploit the full potential of JavaScript, all written code should work in strict mode.
‘use strict’; // You codes goes here...
In order to create a class, function which will represent a type and will act as constructor of that type should be declared.
var Shape = function () { this.__x = 0; this.__y = 0; };
Now let’s create a prototype for the function. Then the function is instantiated and all properties from prototype are copied to new a instance.
Shape.prototype = Object.create(Object.prototype, { x: { get: function () { return this.__x; }, set: function (value) { this.__x = value; }, enumerable: true, configurable: false }, y: { get: function () { return this.__y; }, set: function (value) { this.__y = value; }, enumerable: true, configurable: false }, moveTo: { value: function (x, y) { this.x = x; this.y = y; }, writable: false, enumerable: true, configurable: false }, draw: { value: function () { console.log("Drawing shape at: (" + this.x + ", " + this.y + ")"); }, writable: false, enumerable: true, configurable: false } });
Object property descriptor has these optional keys:
- writable - true if and only if the value associated with the property may be changed with an assignment operator
- enumerable - true if and only if this property shows up during enumeration of the properties on the corresponding object
- configurable - true if and only if the type of this property descriptor may be changed and if the property may be deleted from the corresponding object
When the new type is defined it’s can be locked.
Object.seal(Shape); Object.seal(Shape.prototype);
When the object is locked, it can not be modified. In case of trying to do so, an error will be raised.
Object.defineProperty(obj, "prop", { value: 17 }); // throws an error
After all defined function can be instantiated.
var shape = new Shape(); Object.seal(shape); shape.x = 50; shape.y = 50; shape.moveTo(120, 85); shape.draw(); // Drawing shape at: (120, 85) console.log(shape instanceof Shape); // true
Here is the final result.
‘use strict’; var Shape = function () { this.__x = 0; this.__y = 0; }; Shape.prototype = Object.create(Object.prototype, { x: { get: function () { return this.__x; }, set: function (value) { this.__x = value; }, enumerable: true, configurable: false }, y: { get: function () { return this.__y; }, set: function (value) { this.__y = value; }, enumerable: true, configurable: false }, moveTo: { value: function (x, y) { this.x = x; this.y = y; }, writable: false, enumerable: true, configurable: false }, draw: { value: function () { console.log("Drawing shape at: (" + this.x + ", " + this.y + ")"); }, writable: false, enumerable: true, configurable: false } }); Object.seal(Shape); Object.seal(Shape.prototype); var shape = new Shape(); Object.seal(shape); shape.x = 50; shape.y = 50; shape.moveTo(120, 85); shape.draw(); // Drawing shape at: (120, 85) console.log(shape instanceof Shape); // true
This code can be easily optimized with class4js library.
‘use strict’; var Shape = $class({ __construct__: function () { this.__x = 0; this.__y = 0; }, x: { get: function () { return this.__x; }, set: function (value) { this.__x = value; } }, y: { get: function () { return this.__y; }, set: function (value) { this.__y = value; } }, moveTo: function (x, y) { this.__x = x; this.__y = y; }, draw: function () { console.log("Drawing shape at: (" + this.x + ", " + this.y + ")"); } }); var shape = new Shape({ x: 50, y: 50}); shape.moveTo(120, 85); shape.draw(); // Drawing shape at: (120, 85) console.log($is(shape, Shape)); // true
Features
Here you can get main keywords of class4js. To get more details, documentation should be visited.
- $class - it is used to define class
- $abstract_class - it is used to define abstract class
- $static_class - it is used to define static class
- $enum - it is used to define enum
- $interface - it is used to define interface
- $is - it is used to check type
- $create - it is used to create object
- $init - it is used to initialize object
- $module - it is used to define module
- $namespace - it is used to define namespace
- $extend - it is used to define method to exiting type
- $super - it is used to access parent's method
Conclusion
class4js module emulates classes and their related features introducing new sugar syntax. This syntax allows to write less code, to have better code reuse and allows to protect your library from undesirable modifications which can break your code. Another class4js advantage is that the library is written in JavaScript and doesn’t have any dependencies, and doesn’t need any extra tools to maintain it. Just include to your project and use it.