A Unique Night

What is The Rocky Horror Picture show? If you are looking for something new and unique to do on a Saturday night you should consider attending one of the monthly Rocky Horror Picture Show shows put…

Smartphone

独家优惠奖金 100% 高达 1 BTC + 180 免费旋转




An introduction of OO JavaScript

Understand how to implement Object-Orient (OO) programming with Vanilla JS is still very important and useful in the post-es6 era.

If you are a JS veteran, it really wastes your time to find it nothing new and I am doing my best to alert you as early as possible.

If you are a JS beginner without strong OO language background, such as C++, Java or .Net, you will be a bit lost because the comparisons between Object-Orient programming(OOP) language and JavaScript here expect you are familiar with some OOP languages, but you may still find some interesting and useful, if you haven’t dug into OO implementation with JavaScript before.

If you are good at OO programming and start working on some JS project with ES6 and TypeScript, you will find yourself understand the framework better than before, after you know how to implement the OOP with plain Vanilla JS.

It is only an introduction, so it won’t cover every OO concept or implementation with Vanilla JS, also I have to say the code demonstrated here is just one of the implementations instead of the best practice. Please don’t use the code in your project without proper test.

Before we jump into OOP in JavaScript, let’s talk about ES6 a bit first. When you found ES6 has class, extends keywords at the first time, did you ever say “Wow, how cool it is” and feel very excited? but the truth is ES6 does not change existing prototype-based inheritance to the object-oriented inheritance model at all, those keywords are just sugar syntax.

As you know, so many browsers in the world still only support Vanilla JS up to ES5, or even part of ES5 features. That is why your ES6 application always needs transpiler to make it work. Once ES6 is transpiled, you will find your favorite class becomes a specific function, and the extends you learned from other OO language becomes a special implementation of prototype in Vanilla JS. That is why I say knowing the tricks of Object-Oriented implementation with Vanilla JS will help you better comprehend many other JS frameworks.

For someone without strong OO background, I quote the wiki’s definition here: Object-oriented programming (OOP) is a programming paradigm based on the concept of “objects”, which may contain data, in the form of fields, as known as attributes or properties; and actions, in the form of functions, as known as methods. Also, some similar objects will be abstracted to a given “class”, aka “type”.

For example, a car is an object. The color and model of the car are attributes. Then accelerate to 60km/h, brake to 0km/h, and turn left or right of the car are the actions. All the cars can be abstracted as “Car” type or class, because all the cars have the same attributes and actions. From this sample, you can see OOP makes the code very close to the real world. That is why OOP can be widely accepted and easily understood, meanwhile, it is so popular as an industrial paradigm applied to thousands of business application development in the world.

As other programming language, JavaScript (ECMAScript) standard defines six built-in data types. Five are primitives, including boolean, null, undefined, number, string, and object.

The object type of JavaScript is one of the most mysterious features. In JavaScript, most things are objects, so we can create our own object to encapsulate relevant functions and variables into efficient object, and act as handy data container. Here let’s look into the JavaScript’s object theory and syntax in detail, then check out how to create your own objects. Now we are going to unfold the Object this powerful magic box.

There are a couple ways to create variable as object.

Object type gives developers so much power and flexibility to customize their own data type. All JavaScript objects inherit the properties and methods from their prototype. The Object.prototype is on the top of the prototype chain. All JavaScript objects (Date, Array, RegExp, Function, ….) inherit from the Object.prototype.

Object has properties and method. The methods of object are the actions that can be performed on objects, they are powerful tools for developers. Let’s see how we can create object with properties and methods.

I am sure you must notice the same method defined in every object. It is clumsy to repeat the same method for every object we created. Can we make it better to just define the method once? The answer is Yes. Use an object constructor to create an object prototype. Any new object inherit the same prototype will have the same properties and methods.

Do you remember the example I used to explain the OOP before? The “Car” type above is known as customized type. In many OOP language we call such a type as class, but in JavaScript function is the first citizen, and it performs as class in other language. In C++ or Java, you will create a new object by initializing a class. For JavaScript, you will create a new object by calling a function. Let’s see how to simplify previous code by a simple function.

After you run the code, you should get same result as before. If you compare two blocks of code, you may think the difference between two samples are not such big. Let’s image if you need to create 20 objects and every object with 20 methods, then you totally need to write 20 X 20 = 400 methods. Object’s prototype is powerful, but we need to be careful when we use it, especially the `this` prototype. We need discuss this a bit more in detail.

Now you should understand why we say the class in ES6 is a specific function, and you should be able to create a function as customized type on your own. It is time to move to explore the extends keyword, another important feature in OO programming — inheritance.

Before we explore how to implement the inheritance with Vanilla JS, let me show you a sample by utilizing the function and prototype, which we have demonstrated in the above codes. If you have never implement the inheritance before and you just review the code without execution and test, I believe you think those code for inheritance should work as you expect. Let’s check out the demo.

But once you run and test it, you will surprise the result is incorrect. It really frustrated many developers with OOP background. The code above looks fine, but it doesn’t work as any other OOP language you are familiar with. It is a historical problem. Back to 20 years ago, when Brendan Eich created JavaScript for Netscape, he was told to make JavaScript look like Java, even there is no built-in OO mechanism at the beginning. The syntax looks like an odd way of doing class-based OOP without real classes, and leaves the programmer wondering why they didn’t implement proper class-based OOP. Literally JavaScript keeps using constructor, which obscured JavaScript’s true prototypal nature. It turns out many developers don’t know how to use it properly and efficiently, including myself at the early stage.

Let’s look into code again. As the most developer, I believe you can smell there is something wrong with the prototype and constructor function at a glance. Your guess is correct. Function is the first-class citizen in JavaScript world, but it’s not really a class. We need to understand the constructor creates an empty object, then sets the prototype of empty object to the prototype property of the constructor, then set constructor function with `this` pointing to the newly-created object, and finally returns the object.

If you haven’t checked out the implementation of constructor function before, you will get a bit more confused after you see above definition. Let’s us create a simple sample and take a close look why the constructor and prototype will cause this problem.

If we draw a diagram of above code, you will see what is happening behind the scene. Since the prototype property is a reference, changing the prototype object’s properties at the runtime will affect all objects using the prototype.

According to diagram you can clearly see the prototype-based mechanism in the JavaScript. After we figure out what happens, you may say it is easy to fix. We just need to create new prototype for each object, and clone the properties and methods from supper class. Yes, you are right, but that is not I want to recommend to you, in particular when you want to build your own framework from scratch, we have to see the trade-off if the framework really needs inheritance, and if it is good for maintenance with inheritance.

Let’s say we truly need the inheritance feature, In my opinion I will suggest not to just inherit the properties, instead of methods/actions for better long-term maintenance, but don’t worry, I will go through the classical inheritance and prototypal inheritance in the coming section, actually there is another way to inherit methods/actions via interface in OOP. By implementing the interface we can ensure the object will act as we want. The strategy is duck typing, if you know Python or Ruby you will find that type checking is quite familiar. We will discuss all these one by one later on. Now let’s see how to inherit the properties, we just need to find out the proper way to solve the problem of properties inheritance.

After you run and test, you perhaps will ask: “what? how does this code work? It looks share the same prototype with `this`”? Actually the problem is the special object `this` in JavaScript, which is one of the most misunderstood parts of JavaScript. If you want to dig into this topic, you can find more detailed explanation in the book “JavaScript: The Good Parts”. Today the this still confuses many other JS developers. If you have experience with other JavaScript framework. You will find many samples which use `that` , `self`, `vm` to replace the built-in `this`. e.g. `var that = {}`, `var self = {}`,etc. Let’s see the other version of above sample code.

After I rewrite a few lines of code, you will find it is much easier to figure out what happens behind the scene. Now you maybe still want to implement inheritance as other OO language C++, Java or .Net. Then let’s take a look the classical inheritance, which is much more close to other OO language. In classical inheritance it’s impossible (or at least very difficult) to choose which properties you want to inherit. They use virtual base classes and interfaces to solve the diamond problem. It is much more complicated.

Many programmers who come from a traditional OO background argue that classical inheritance is more powerful than prototypal inheritance. The truth is that prototypal inheritance supports inheriting from multiple prototypes. It means one object inherits different attributes and methods from multiple other objects.

Either classical or prototypal, is designed to reduce the redundancy of the code. Using prototypal inheritance in the code which requires multiple inheritance sometimes will be incredible efficient. Perhaps you may raise your concern about multiple inheritance immediately, if you have strong OOP background, but we are not going to explore that part in this introduction.

One of the most important advantages of prototypal inheritance is that you can add new properties to prototypes after they are created. It allows you to add new methods to a prototype which will be automatically made available to all the objects which delegate to that prototype. Also, it allows you to add new methods to a prototype which will be automatically made available to all the objects which delegate to that prototype. It is not possible in classical inheritance because once a class is created you can’t modify it at the runtime. This is probably the greatest advantage of prototypal inheritance over classical inheritance.

In many OO programming languages, there are a few similar advanced concepts, such as package, module, namespace, etc. which are the definite lack of such hierarchical structure in JavaScript. There are quite a lot of benefits from module, package or namespace. The most obvious one is keeping you from naming conflict within the project, particularly when you are going to build some big application with a team of developers, or build multiple systems (components) across your whole entire enterprise.

Since JavaScript has no built-in support of module, package or namespace, its global variable has been a well-known nasty issue, which confounds many developers, sometimes it costs a big price for unintentional bad practice. As a JavaScript developer, we have to pay attention to such bad practices. For example, we should not pollute the context, since it will potentially break existing functions or other third party frameworks which have been introduced in your application, vice versa. And we need to stick with good practices, such as, reusable component, which improves the productivity. It is convenient for further enhancement or maintenance as well.

There is no module concept in JavaScript, but it is dead simple to create a module in JavaScript. One of the most widely used design patterns in JavaScript is the module pattern. Module pattern in JavaScript is built on the JavaScript’s feature — closure.

The module pattern makes use of one of the nicer features of JavaScript — closures — in order to give you some control of the privacy of your methods so that other applications cannot access private data or override it. Literally many frameworks you have used are coded within the closure.

From the code above, the JavaScript can easily implement the encapsulation as OOP language. Closure is the basic the module pattern, and module is the base of namespace. Maybe you will wonder why we need module and namespace, it seems the closure is good enough to control, manage and encapsulate the APIs. If we take a second thought we will realize the closure object is still a global variable, it does not prevent us from the global variable issue. There is a simple solution as quick fix, i.e. we can simply make a very long, unique and ridiculous name to avoid the conflict, but it is not a nice solution. Then module turns out as a better way to solve this problem.

Module is not rock science. Actually it is no brainer as closure and quite easy to implement.

You may say “What is the difference between closure and module? They are the same”. Yes, you can say that. The little difference is the augments during auto initialization. By having a function argument “undefined” (Please don’t be confused by the built-in type undefined, and the argument name does not matter, it can be changed to anything else. ) which you don’t pass a parameter to, you could make sure you have a variable which really is undefined. This technique ensures that it will work as expected, in case it will be excluded to unintentional amendment by other library or plugin. Once we create our module, we can simply extend the module with the same technique.

Now let’s go further to explore the namespace, which is based on module technique. Namespace gives you the ability to have public and private properties and methods, meanwhile, it solves the global issue in a better manner.

The demo code doesn’t use the Object Literal notation, so it allows you to use $ inside your code without worrying about crashing with other libraries, moreover, it allows your library to grow across files using the “window.hhons = window.hhons || {}”. The pattern like this you will see in some libraries, widgets, and plugins.

The sample above gives you an idea how to use module and namespace to build your own framework. Now you will have a comprehensive understanding the benefits from module and namespace. As you see, they provide you much more flexibility to add new module for enhancement, inject customized service, or even replace the module, and they provide a better structure to organize and manage the APIs, furthermore, your code will be much more readable.

There are some disadvantages of module and namespace, when your source code blows up, it will be more and more complicated, especially if you need to load and mix different modules in a proper order from different files. Mock test or unit test will need a bit more effort as well. There is no pattern or design as Silver Bullet, but rather you should examine the pros and cons of each pattern to address your situation.

Finally, we comes to the interface subject. An interface works as a contract to remind the programmers what methods a given class implements, which makes it easier to use. Interfaces also stabilize the ways in which different classes can communicate.

The interface implementation in JavaScript always involves another method invocation, so it comes with the sort of concern of the performance. Another drawback is that it is impossible to force other developers to respect the existing interfaces created by someone else. You can mitigate this problem by using coding conventions and helper classes, which check a given class implements an interface manually, but it will never entirely go away. The whole team must agree to use them; otherwise much of their value is lost.

JavaScript does not come with built-in support for interfaces, and there is no Interface keyword, so any method you use to implement this will be very different from other OO languages. JavaScript uses what’s called duck typing. (If it walks like a duck, and quacks like a duck, as far as JS cares, it’s a duck.) For instance, there is a “Duckable” interface, which has three methods: quack(), walk(), and fly(). If your object has quack(), walk(), and fly() methods, it will be qualified as a “Duckable” instance of “Duckable” interface.

JavaScript needs an interface object to ensure if the new instance implements the same action as interface object.

So far we have gone through a few important and useful OOP concepts and implementation in JavaScript, which I think it will help the JS novice to understand the tricks of OO design and programming within the JS world. As I mentioned at the very beginning, this article won’t cover all OO programming, also the knowledge and tricks here won’t let you grasp OO technique thoroughly in JavaScript, but it may be the start of your journey to quest the wonderland of OO design and pattern in JavaScript.

Add a comment

Related posts:

FTC Attempts To Create Guidelines For AI Developers and Deployers

The FTC published a recent blog and an article discussing the emerging threat of the AI fake problem, which refers to the use of artificial intelligence behind the screen to create or spread…

The Chair Piece

One month ago I took a devastating fall. I ended up tearing my MCL, ACL, meniscus, and fractured my femur head. These combination of injuries are very rare, and might I say very painful. Coming out…

I need bottom partial dentures. That

I need bottom partial dentures. That’s it. I don’t need anything else and won’t need anything in the near future. Do I need insurance ? I need bottom partial dentures. That’s it. I don’t need…