Deep dive In Javascript Objects. Deep dive on Objects in Javascript
By: Mikael Araya
Tags: JavaScript, Javascript Development, Javascript Tips, Objects, ES6

Objects are an integral part of applications and are used everywhere But despite there ubiquity I think some of there capabilities that could make them even valuable are overlooked especially when it comes to javascript.

Javascript is an object-based scripting language and understanding the nature of the object especially becomes even more valuable to have control over the core language.

with the introduction of JavaScript classes, introduced in ECMAScript 2015, the definition of objects has become abstracted. none the less support of class declaration is just syntactic sugar and javascript is still prototype-based and doesn't add any feature in the existing model. So understanding what the class abstraction performs under the hood is still valuable.

Refer to the following link if you want a deeper understanding of the ECMAScript 2015 javascript class definition.

In this article, I’ll try to show most of the properties that relate to javascript object configuration and by the end of this article, I hope you will be more enlightened than you previously were in regards to javascript objects.

Introduction

Due to the dynamic nature of javascript creating an object is as simple as the code below.

var myObject = {};

the code above creates an object with a name myObject that extends the base Object class prototype with no properties. object prototypical is beyond the scope of this article but you can refer to this link if you want to understand more.

Now if you want to create an object with properties you can modify the above code like below

var myObject = {

firstProperty: '',

secondProperty: 100,

thirdProperty: []

}

Or add the properties after creating the object

var myObject = {};

myObject.firstProperty = '';

myObject.secondPropery = 100;

myObject.thirdProperty = [];

While the above statements are both valid ways of creating an object and initializing its properties, they hide all the configuration that happens in the background.

In the following section, we will explore all the configuration that is happening in the background at the moment of object creation and try to understand how we can use this configuration option to create objects that fit our requirements.

Javascript Objects 101

The generic definition of objects in computer science is value in memory that mostly have identifiers that reference them. In javascript objects can be seen as a collection of properties.

In javascript objects can be seen as a collection of properties.

Javascript Object Properties

Javascript objects have two properties.

Data properties — are properties that hold the actual value of the object and define the behavior of the property.

— are properties that hold the actual value of the object and define the behavior of the property. Accessor properties — are properties that are used to modify and retrieve the value from the data properties of the object.

Each property has attributes that can be used to configure its behavior. while each property have attributes that are unique to each of them there are attributes that are shared between them

— Shared Attributes

Enumerable( boolean: false ) — a boolean value that specifies if the property is accessible through iterators like for…in loops, spread operators, Object.keys(). if left undefined it will take on the default value of false .

— a boolean value that specifies if the property is accessible through iterators like for…in loops, spread operators, Object.keys(). if left undefined it will take on the default value of . Configurable( boolean: false ) — a boolean value that specifies if the property can be deleted with the delete operator. it will take on a default value of false if left unspecified. When attempting to delete the property while on sloppy mode the operation will be ignored while on strict mode it will throw an error.

slopy mode and strict mode are beyond the scope of this article. if you want a detail discussion make sure you check out each by following there corresponding link.

— Data Property Attributes

Value( [string|object|number|Array|null] : undefined ) — holds the actual value of the property. it can be any valid javascript data type. when we set the value using this property it’s the same as assigning it directly as we saw it earlier. if left undefined it will take on a default value of undefined.

holds the actual value of the property. it can be any valid javascript data type. when we set the value using this property it’s the same as assigning it directly as we saw it earlier. if left undefined it will take on a default value of undefined. Writable ( boolean: false ) — used to specify whether the property can be assigned another value after the moment of creation. if left undefined it will take on the default value of false which means the property becomes read-only .

If we attempt to reassign new value for a property with the writable value set to false in sloppy mode the assignment will be ignored while on strict mode it will through error.

— Accessor property attributes

get ( Function: undefined ) — called whenever we attempt to retrieve the property value associated with this attribute as a function that takes no arguments.

— called whenever we attempt to retrieve the property value associated with this attribute as a function that takes no arguments. set( Function: undefined ) — used to modify the value of a property. it’s a function that is called with one argument that contains the assigned value and is executed whenever a specified property is attempted to be changed.

As we can see there are a lot of properties we can utilize to configure the property of objects in our application.

Mutual Exclusivity between Configurations

While we can configure objects however we want there are few configurations that will not work when other configurations are also set.

Value & writable Vs. set & get assertion

you can set data writable & value properties and also define set and get accessor since they create conflicts.

on these occasions, it will throw an error similar to oojs.html:34 Uncaught TypeError: Invalid property descriptor. Cannot both specify accessors and a value or writable attribute, #<Object>

But how do we actually set these values did you say? well, that we’re one of the predefined functions for the global Object Object.definePropertiy & Object.defineProperties come in to play.

Introduction to Object.defineProperty()

The global Object provides lots of prefined functions that let us manipulate Objects in various ways and is the superclass to all objects created in javascript.

Object.definePropery and its sibling Object.defineProperties let us configure the object's properties as we want. in the following section, we will see how we can use these functions to configure object properties.

— Object.defineProperty take 3 arguments.

Object.defineProperty(obj: Object, key: strinng, config: Object)

Object — the first argument takes the object to which we want to configure.

— the first argument takes the object to which we want to configure. key — string value that specifies the property we want to modify the attributes of. if the specified key doesn’t exist object.defineProperties will create the key.

— string value that specifies the property we want to modify the attributes of. if the specified key doesn’t exist object.defineProperties will create the key. config — the last argument is used to define the attribute values of the property. we can pass an empty object for this value in which case the default attribute values.

Object.defineProperty(Object, 'key: String', {

configurable: Boolean,

writable: Boolean,

enumerable: Boolean,

value: String|Number|Array|Object,

get: Function,

set: Function

});

— its sibling Object.defineProperties() takes 2 arguments

Object.defineProperty(obj: Object, config: Object)

Object — the object that you want to configure

— the object that you want to configure config — the configuration object.

Object.defineProperties(Object, {

'propertyName': string {

configurable: Boolean,

writable: Boolean,

enumerable: Boolean,

value: String|Number|Array|Object,

get: Function,

set: Function

},

'propertyName': string {

configurable: Boolean,

writable: Boolean,

enumerable: Boolean,

value: String|Number|Array|Object,

get: Function,

set: Function

},{}...});

Configuring Object properties using Object.create()

event though object.defineProperty and Object.defineProperties are dedicated function for setting object properties there is one other way we can we use to set objects properties, that is using the second argument to the function Object.create() that accept property configuration object.

var myObject = Object.create({}, {

'propertyName': string {

configurable: Boolean,

writable: Boolean,

enumerable: Boolean,

value: String|Number|Array|Object,

get: Function,

set: Function

},

'propertyName': string {

configurable: Boolean,

writable: Boolean,

enumerable: Boolean,

value: String|Number|Array|Object,

get: Function,

set: Function

}...} )

Examples

In the following section, I’ll try to show different configuration options we can follow in applications.

1 Object with a default value

var myObject = {};

Object.defineProperty(myObject, 'firstProperty', {

configurable: false,

writable: true,

value: 200, //default value

enumerable: false,

set(val) {

this.first = val;

},

get() {

return this.first;

}

});

> console.log(myObject);

> 200

2 Read-only property — Soppy-mode

var myObject = {};

Object.defineProperty(myObject, 'firstProperty', {

configurable: false,

writable: false,

value: 200,

enumerable: false

}); myObject.firstProperty = 100; // will not affect the value console.log(myObject.firstProperty);

> 200 // same as defined inside object.defineProperty()

3 Read-only property — strict-mode

'use strict'; // strict mode var myObject = {};

Object.defineProperty(myObject, 'firstProperty', {

configurable: false,

writable: false,

value: 200,

enumerable: false

}); myObject.firstProperty = 100; // will throw error console.log(myObject.firstProperty); > Uncaught TypeError: Cannot assign to read only property 'firstProperty' of object '#<Object>'

4. Setting Multiple values using Object.defineProperties

var myObject = {};

Object.defineProperties(myObject, {

firstProperty: {

configurable: false,

writable: true,

value: 200,

enumerable: false

},

secondProperty: {

configurable: false,

writable: true,

value: 100,

enumerable: false

}

});

> console.log(myObject.firstProperty);

> 200

> console.log(myObject.secondProperty);

> 100

5 Hide property from Iterators

var myObject = {};

Object.defineProperties(myObject, {

firstProperty: {

configurable: false,

writable: true,

value: 200,

enumerable: true

},

secondProperty: {

configurable: false,

writable: true,

value: 100,

// hidden from itterators

enumerable: false

}

}); for (const key in myObject) {

console.log(key);

} > firstProperty

6 Restrict Delete — slopy mode

var myObject = {}; Object.defineProperty(myObject, 'firstProperty',

{

// disable delete

configurable: false,

writable: true,

value: 200,

enumerable: true

}); // does not have any effect

delete myObject.firstProperty; console.log(myObject.firstProperty);

> 200 // value still available

7 Restrict Delete — slopy mode

'use strict'; var myObject = {}; Object.defineProperty(myObject, 'firstProperty',

{

// disable delete

configurable: false,

writable: true,

value: 200,

enumerable: true

}); // will throw error since firstProperty is not configurable

delete myObject.firstProperty; console.log(myObject.firstProperty); > Uncaught TypeError: Cannot delete property 'firstProperty' of #<Object>

8 Define accessor for property

var myObject = {};

Object.defineProperty(myObject, 'firstProperty', {



configurable: false,

enumerable: true,

get() { return this.first;},

set(val) {

// change value to uppercase return (this.first = val.toUpperCase());

}); myObject.firstProperty = 'Mikael Araya';

console.log(myObject.firstProperty); > MIKAEL ARAYA

9 Define object property using Object.create

var myObject = Object.create({}, {

firstProperty: {

configurable: false,

writable: true,

value: 200,

enumerable: false

},

secondProperty: {

configurable: false,

writable: true,

value: 100,

enumerable: false

}

});

console.log(myObject.firstProperty);

> 200

console.log(myObject.secondProperty);

> 100

Conclusion

While there are many libraries and frameworks out there abstracting the underline javascript engine understanding how some aspects of the language are implemented is essential to have great control over the tool.

Defining object property attributes explicitly instead of passing to javascript default behavior will enable us to have control over how objects in application behave and increase predictability and security.

Reference