


What is Javascript Prototype ?
What Is a Constructor in JavaScript?
To get to know about prototypes, let’s talk about constructors first.
The Constructor function in JavaScript is a function that returns a reference to the object that created the instance object. For example, if your object is an instance of an array, its constructor function refers to the array. This constructor always points to the function itself.
let a = [];
a.constructor === Array; // true
Let’s say there’s a function named Tree. You create a new object, using Tree function:
function Tree() {
this.name = 'Tree';
}
const tree = Tree();
console.dir(tree); // undefined
In the example above, nothing has been stored in tree
because Tree doesn’t return any values. In JavaScript, a constructor function is a function object that is only called when the function, Tree, is called with the new
keyword.
const tree = new Tree();
console.dir(tree);



We can see the property name
is set after we called Tree with the new
keyword. Then what happened when we call a function with new
?
Basically, there are two ways of creating an object by calling a function. The first method is one everybody who knows JavaScript would probably know — just call it like this below.
tree();
Once you call it like that, then the new lexical environment of the function, Tree, will be created, and the JavaScript engine will execute all of the codes inside the tree
from the top to the bottom. If there’s a return statement, then tree
returns that specific value(s). If there are none, then undefined
is returned by default.
However, with new
keyword, there are a few steps that the engine takes.
- Create an empty object,
{}
, and assign it tothis
. - Assign all of the values to
this
that are expressed like this inside the function.this.name = 'Tree'
- return
this
and store it to a variable that takes the return value ofnew Tree()
.
So, if you call a function with new
, the code works like this.
function Tree() {
this = {};
this.name = 'Tree';
return this;
}
How can I know whether the function is called with `new`?
Since ECMAScript 2015, a new feature came out; new.target
. This is a dead-simple feature to let you know if the function is called with new
or not. new.target
returns a reference to the constructor of the function.
function Tree() {
if (!new.target) {
console.log('Need new !!!');
}
}
Tree(); // Need new !!!
new Tree(); // Tree {}
I understand what constructor is, but why does it matter?
So, if we call Tree with new
, then the result looks like this.
function Tree() {
this.name = 'Tree';
this.age = 13;
}
const tree = new Tree();
// same as
const tree = {
name: 'Tree';
age: 13
};
But, imagine that we want to create 10 more trees. If we have to create an object with a literal object every single time, isn’t it a pain in the neck?
Simply put every variables or method in a constructor function and create a new object by calling with new
. It is not only good to maintain the code, but it’s also reusable.
What is a Prototype?
Let’s talk about the prototype. A prototype is a shared property amongst all the instances of a function object. When a function is invoked with new
, a new property called prototype
is generated then set to this
. One interesting thing is that the constructor of the function itself is a default property of the prototype object. And every object, except for the object created by Object.create(null)
, has its prototype object.



This is what you can see when you make a new instance of Tree. If you aren’t familiar with prototype in JavaScript, just remember this: prototype is merely an object whose property, named constructor, refers to the function that it belongs to.
function Tree(name) {
this.name = name;
}
Tree.prototype.sayName = function() {
console.log(this.name);
}
const tree1 = new Tree('Maple');
const tree2 = new Tree('Bamboo');
tree1.sayName(); // Maple
tree2.sayName(); // Bamboo
Although Tree doesn’t have sayName
function as its property, tree1
and tree2
have sayName
.



This is a full picture of the prototype chains of Tree. I know, it looks so confusing. I will explain it one by one.
- Tree has
prototype
property that is for sharing properties, such as variables and functions, with all of the instances that inherit properties from Tree. - As I mentioned earlier,
prototype
is just an object that containsconstructor
function inside, that we talked about earlier in this post. Andconstructor
points to the function itself. Tree’sprototype
hasconstructor
that links toTree
function. - Every object includes a certain property named
[[prototype]]
. It goes by__proto__
in most browsers. What[[prototype]]
indicates is theprototype
property of an object that the function inherits properties from. For example, look at the picture. Tree’s[[prototype]]
refers toFunction.prototype
because Tree is an instance of Function. - The highest
prototype
isObject.prototype
.Object.prototype
doesn’t refer to anything. SoObject.prototype.__proto__
isnull
. - When a variable or a method is called or referred, JavaScript looks for it by looking through all of the prototypes from the very bottom to the very top until it finds what it looks for or it reaches out
null
fromObject.prototype
. This process is calledPrototype Chain
.
tree1.sayName(); // Maple
tree1
doesn’t have sayName
as its property.
tree1.hasOwnProperty('sayName'); // false
When sayName
is called, JavaScript looks for it within the scope of tree1
, but it can’t find it. Then JavaScript looks for [[prototype]]
of tree1
that connects to Tree.prototype
. JavaScript can find sayName
within the scope of Tree.prototype
, and execute it. If there wasn’t sayName
in Tree.prototype
, then JavaScript, again, looks for [[prototype]]
of Tree
that connects to Function.prototype
. JavaScript keeps doing this until it finds what it was looking for or until it reaches null
.
Can I add methods in the prototype even though I already created an object with `new`?
Absolutely. Look at the example.
function Tree(name) {
this.name = name;
}
Tree.prototype.sayName = function() {
console.log(this.name);
}
const tree1 = new Tree('Maple');
const tree2 = new Tree('Bamboo');
tree1.sayName(); // Maple
tree2.sayName(); // Bamboo
// add another method later
Tree.prototype.sayBye = function() {
console.log(`Bye bye, ${this.name}`);
}
tree1.sayBye(); // Bye bye, Maple
tree2.sayBye(); // Bye bye, Bamboo
You can add or remove variables or functions in Tree’s prototype anytime you want. All of its instances will dynamically refer to the updated prototype when they try to access it.
Can I replace the prototype?
Sure. You can reassign it with a new prototype object.
function Tree(name) {
this.name = name;
}
Tree.prototype.sayName = function() {
console.log(this.name);
}
const tree1 = new Tree('Maple');
const tree2 = new Tree('Bamboo');
tree1.sayName(); // Maple
tree2.sayName(); // Bamboo
Tree.prototype = {
sayName: function() {
console.log(`Bye bye, ${this.name}`)
}
}
const tree3 = new Tree('Ginkgo');
tree1.sayName(); // Maple
tree2.sayName(); // Bamboo
tree3.sayName(); // Bye bye, Ginkgo
As you can see in the result, the prototype of Tree has been changed with a different one, and I made tree3
. But the fun part is tree1
and tree2
still point out the previous sayName
function that prints this.name
, while tree3
points out the new sayName
. So this is what you should make sure of before you replace the existing prototype with a new one. Because the existing instances still refer to the original prototype, they won’t work as you expect. Furthermore, GC, Garbage Collector, will not clean the original prototype since it’s still referred by someone else, tree1
and tree2
in this case. So it isn’t considered a best practice to change the prototype.
Conclusion
A prototype is a very beautiful feature in JavaScript since it allows many objects to share data with each other. But, you should be careful to handle the prototype because if you change the prototype, already-created instances have to be updated manually, and it would be easy to make a side-effect. Next post, I will talk about inheritance in JavaScript using the prototype.



Debouncing in Javascript
In 2011, an issue popped up on the Twitter website: when you were scrolling down your Twitter feed, it became slow and unresponsive. John Resig published a blog post about the problem where it was explained how bad of an idea it is to directly attach expensive functions to the scroll
event. The suggested solution by John (at that time) was a loop running every 250ms, outside of the onScroll event
. That way the handler is not coupled to the event. With this simple technique, we can avoid ruining the user experience. These days there are slightly more sophisticated ways of handling events like Debounce, Throttle etc.
So what exactly is Debounce ?
This function is built in order to limit the amount of times a function is called — scroll events, mousemove events, and keypress events are all great examples of events that we might want to capture, but can be quite taxing if we capture them every single time they fire. In order to combat this, we implement debounce and throttle functions. We won’t discuss the throttle function in this post, but a debounce function will wait until the last time the function is called and then fire after a predetermined amount of time or once the event firing becomes inactive.
For those in camp TL;DR, here’s a demo!
See the Pen Mouse/Touch Move Debounce & Throttle visualisation w/ React + Pixi 🤓👀 by Jhey (@jh3y) on CodePen.
A debounce is a higher-order function, which is a function that returns another function (named executedFunction
here for clarity). This is done to form a closure around the func
and wait
function parameters and the timeout
variable so that their values are preserved. The following is a definition of each variable:
func
: The function that you want to execute after the debounce timewait
: The amount of time you want the debounce function to wait after the last received action before executingfunc
. For our typeahead example, it would be the amount of time to wait after the last key press.timeout
: The value used to indicate a running debounce.
We can use a debounce doing:
var returnedFunction = debounce(function() {
// All the taxing stuff you do
}, 250);
window.addEventListener('resize', returnedFunction);
Since debounce returns a function, the executedFunction
from the first example and the returnedFunction
function from the second example are the same function. Every time the window is resized, it will execute executedFunction
/returnedFunction
.
Our executedFunction
spreads over the parameters (...args)
to allow for the debounce function to receive any number of parameters to pass to the callback.
We declare a callback function named later
which is the function that’s executed after the end of the debounce timer. This is what will be called after the setTimeout
expires.
Next, we clearTimeout
which had prevented the callback from being executed and thus restarts the debounce. Then we (re-)declare timeout
which starts the debounce waiting period. If the full wait
time elapses before another event, then we execute the later
callback function. The timeout
is set to null
which means the debounce has ended. This executes func(...args)
.
There is a more advanced version of this where we can pass an immediate
flag to debounce
. Currently we always wait until the end of the debounce to execute the callback, but with immediate
, you can change it such that the function executes at the leading edge and won’t allow you to execute again until it has delayed calling long enough to deplete the timer.
Here’s a commented version of the function as well.Here’s a commented version of the function as well.
// Originally inspired by David Walsh (https://davidwalsh.name/javascript-debounce-function)
// Returns a function, that, as long as it continues to be invoked, will not
// be triggered. The function will be called after it stops being called for
// `wait` milliseconds.
const debounce = (func, wait) => {
let timeout;
// This is the function that is returned and will be executed many times
// We spread (...args) to capture any number of parameters we want to pass
return function executedFunction(...args) {
// The callback function to be executed after
// the debounce time has elapsed
const later = () => {
// null timeout to indicate the debounce ended
timeout = null;
// Execute the callback
func(...args);
};
// This will reset the waiting every function execution.
// This is the step that prevents the function from
// being executed because it will never reach the
// inside of the previous setTimeout
clearTimeout(timeout);
// Restart the debounce waiting period.
// setTimeout returns a truthy value (it differs in web vs Node)
timeout = setTimeout(later, wait);
};
};
Common scenarios for a debounce are resize
, scroll
, and keyup/keydown
events. In addition, you should consider wrapping any interaction that triggers excessive calculations or API calls with a debounce.