So far I saw three ways for creating an object in JavaScript. Which way is best for creating an object and why?
I also saw that in all of these examples the keyword
I guess it depends on what you want. For simple objects, I guess you could use the second methods. When your objects grow larger and you're planning on using similar objects, I guess the first method would be better. That way you can also extend it using prototypes.
Example:
function Circle(radius) {
this.radius = radius;
}
Circle.prototype.getCircumference = function() {
return Math.PI * 2 * this.radius;
};
Circle.prototype.getArea = function() {
return Math.PI * this.radius * this.radius;
}
I am not a big fan of the third method, but it's really useful for dynamically editing properties, for example var foo='bar'; var bar = someObject[foo];
.
While many people here say there is no best way for object creation, there is a rationale as to why there are so many ways to create objects in JavaScript, as of 2019, and this has to do with the progress of JavaScript over the different iterations of EcmaScript releases dating back to 1997.
Prior to ECMAScript 5, there were only two ways of creating objects: the constructor function or the literal notation ( a better alternative to new Object()). With the constructor function notation you create an object that can be instantiated into multiple instances (with the new keyword), while the literal notation delivers a single object, like a singleton.
// constructor function
function Person() {};
// literal notation
var Person = {};
Regardless of the method you use, JavaScript objects are simply properties of key value pairs:
// Method 1: dot notation
obj.firstName = 'Bob';
// Method 2: bracket notation. With bracket notation, you can use invalid characters for a javascript identifier.
obj['lastName'] = 'Smith';
// Method 3: Object.defineProperty
Object.defineProperty(obj, 'firstName', {
value: 'Bob',
writable: true,
configurable: true,
enumerable: false
})
// Method 4: Object.defineProperties
Object.defineProperties(obj, {
firstName: {
value: 'Bob',
writable: true
},
lastName: {
value: 'Smith',
writable: false
}
});
In early versions of JavaScript, the only real way to mimic class-based inheritance was to use constructor functions. the constructor function is a special function that is invoked with the 'new' keyword. By convention, the function identifier is capitalized, albiet it is not required. Inside of the constructor, we refer to the 'this' keyword to add properties to the object that the constructor function is implicitly creating. The constructor function implicitly returns the new object with the populated properties back to the calling function implicitly, unless you explicitly use the return keyword and return something else.
function Person(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
this.sayName = function(){
return "My name is " + this.firstName + " " + this.lastName;
}
}
var bob = new Person("Bob", "Smith");
bob instanceOf Person // true
There is a problem with the sayName method. Typically, in Object-Oriented Class-based programming languages, you use classes as factories to create objects. Each object will have its own instance variables, but it will have a pointer to the methods defined in the class blueprint. Unfortunately, when using JavaScript's constructor function, every time it is called, it will define a new sayName property on the newly created object. So each object will have its own unique sayName property. This will consume more memory resources.
In addition to increased memory resources, defining methods inside of the constructor function eliminates the possibility of inheritance. Again, the method will be defined as a property on the newly created object and no other object, so inheritance cannot work like. Hence, JavaScript provides the prototype chain as a form of inheritance, making JavaScript a prototypal language.
If you have a parent and a parent shares many properties of a child, then the child should inherit those properties. Prior to ES5, it was accomplished as follows:
function Parent(eyeColor, hairColor) {
this.eyeColor = eyeColor;
this.hairColor = hairColor;
}
Parent.prototype.getEyeColor = function() {
console.log('has ' + this.eyeColor);
}
Parent.prototype.getHairColor = function() {
console.log('has ' + this.hairColor);
}
function Child(firstName, lastName) {
Parent.call(this, arguments[2], arguments[3]);
this.firstName = firstName;
this.lastName = lastName;
}
Child.prototype = Parent.prototype;
var child = new Child('Bob', 'Smith', 'blue', 'blonde');
child.getEyeColor(); // has blue eyes
child.getHairColor(); // has blonde hair
The way we utilized the prototype chain above has a quirk. Since the prototype is a live link, by changing the property of one object in the prototype chain, you'd be changing same property of another object as well. Obviously, changing a child's inherited method should not change the parent's method. Object.create resolved this issue by using a polyfill. Thus, with Object.create, you can safely modify a child's property in the prototype chain without affecting the parent's same property in the prototype chain.
ECMAScript 5 introduced Object.create to solve the aforementioned bug in the constructor function for object creation. The Object.create() method CREATES a new object, using an existing object as the prototype of the newly created object. Since a new object is created, you no longer have the issue where modifying the child property in the prototype chain will modify the parent's reference to that property in the chain.
var bobSmith = {
firstName: "Bob",
lastName: "Smith",
sayName: function(){
return "My name is " + this.firstName + " " + this.lastName;
}
}
var janeSmith = Object.create(bobSmith, {
firstName : { value: "Jane" }
})
console.log(bobSmith.sayName()); // My name is Bob Smith
console.log(janeSmith.sayName()); // My name is Jane Smith
janeSmith.__proto__ == bobSmith; // true
janeSmith instanceof bobSmith; // Uncaught TypeError: Right-hand side of 'instanceof' is not callable. Error occurs because bobSmith is not a constructor function.
Prior to ES6, here was a common creational pattern to utilize function constructors and Object.create:
const View = function(element){
this.element = element;
}
View.prototype = {
getElement: function(){
this.element
}
}
const SubView = function(element){
View.call(this, element);
}
SubView.prototype = Object.create(View.prototype);
Now Object.create coupled with constructor functions have been widely used for object creation and inheritance in JavaScript. However, ES6 introduced the concept of classes, which are primarily syntactical sugar over JavaScript's existing prototype-based inheritance. The class syntax does not introduce a new object-oriented inheritance model to JavaScript. Thus, JavaScript remains a prototypal language.
ES6 classes make inheritance much easier. We no longer have to manually copy the parent class's prototype functions and reset the child class's constructor.
// create parent class
class Person {
constructor (name) {
this.name = name;
}
}
// create child class and extend our parent class
class Boy extends Person {
constructor (name, color) {
// invoke our parent constructor function passing in any required parameters
super(name);
this.favoriteColor = color;
}
}
const boy = new Boy('bob', 'blue')
boy.favoriteColor; // blue
All in all, these 5 different strategies of Object Creation in JavaScript coincided the evolution of the EcmaScript standard.
Of course there is a best way.Objects in javascript have enumerable and nonenumerable properties.
var empty = {};
console.log(empty.toString);
// . function toString(){...}
console.log(empty.toString());
// . [object Object]
In the example above you can see that an empty object actually has properties.
Ok first let's see which is the best way:
var new_object = Object.create(null)
new_object.name = 'Roland'
new_object.last_name = 'Doda'
//etc
console.log("toString" in new_object) //=> false
In the example above the log will output false.
Now let's see why the other object creation ways are incorrect.
//Object constructor
var object = new Object();
console.log("toString" in object); //=> true
//Literal constructor
var person = {
name : "Anand",
getName : function (){
return this.name
}
}
console.log("toString" in person); //=> true
//function Constructor
function Person(name){
this.name = name
this.getName = function(){
return this.name
}
}
var person = new Person ('landi')
console.log("toString" in person); //=> true
//Prototype
function Person(){};
Person.prototype.name = "Anand";
console.log("toString" in person); //=> true
//Function/Prototype combination
function Person2(name){
this.name = name;
}
Person2.prototype.getName = function(){
return this.name
}
var person2 = new Person2('Roland')
console.log("toString" in person2) //=> true
As you can see above,all examples log true.Which means if you have a case that you have a for in
loop to see if the object has a property will lead you to wrong results probably.
Note that the best way it is not easy.You have to define all properties of object line by line.The other ways are more easier and will have less code to create an object but you have to be aware in some cases. I always use the "other ways" by the way and one solution to above warning if you don't use the best way is:
for (var property in new_object) {
if (new_object.hasOwnProperty(property)) {
// ... this is an own property
}
}
Majorly there are 3 ways of creating Objects-
Simplest one is using object literals.
const myObject = {}
Though this method is the simplest but has a disadvantage i.e if your object has behaviour(functions in it),then in future if you want to make any changes to it you would have to change it in all the objects.
So in that case it is better to use Factory or Constructor Functions.(anyone that you like)
Factory Functions are those functions that return an object.e.g-
function factoryFunc(exampleValue){
return{
exampleProperty: exampleValue
}
}
Constructor Functions are those functions that assign properties to objects using "this" keyword.e.g-
function constructorFunc(exampleValue){
this.exampleProperty= exampleValue;
}
const myObj= new constructorFunc(1);
There is various way to define a function. It is totally based upon your requirement. Below are the few styles :-
var person = new Object();
person.name = "Anand",
person.getName = function(){
return this.name ;
};
var person = {
name : "Anand",
getName : function (){
return this.name
}
}
function Person(name){
this.name = name
this.getName = function(){
return this.name
}
}
function Person(){};
Person.prototype.name = "Anand";
function Person(name){
this.name = name;
}
Person.prototype.getName = function(){
return this.name
}
var person = new function(){
this.name = "Anand"
}
You can try it on console, if you have any confusion.
There are a many ways to create your objects in JavaScript. Using a constructer function to create an object or object literal notation is using alot in JavaScript. Also creating an instance of Object and then adding properties and methods to it, there are three common ways to do create objects in JavaScript.
Constructer functions
There are built-in constructer functions that we all may use them time to time, like Date(), Number(), Boolean() etc, all constructer functions start with Capital letter, in the meantime we can create custom constructor function in JavaScript like this:
function Box (Width, Height, fill) {
this.width = Width; // The width of the box
this.height = Height; // The height of the box
this.fill = true; // Is it filled or not?
}
and you can invoke it, simply using new(), to create a new instance of the constructor, create something like below and call the constructor function with filled parameters:
var newBox = new Box(8, 12, true);
Object literals
Using object literals are very used case creating object in JavaScript, this an example of creating a simple object, you can assign anything to your object properties as long as they are defined:
var person = {
name: "Alireza",
surname: "Dezfoolian"
nose: 1,
feet: 2,
hands: 2,
cash: null
};
Prototyping
After creating an Object, you can prototype more members to that, for example adding colour to our Box, we can do this:
Box.prototype.colour = 'red';