Revision:
a JavaScript object is a collection of unordered properties, which can usually be changed, added, and deleted, but some are read only.
objectName.property // person.age
or
objectName["property"] // person["age"]
or
objectName[expression] // x = "age"; person[x]
P.S. The expression must evaluate to a property name.
Examples
access a property with .property :
access a property with ["property"] :
<div class="spec"> <p>access a property with <em>.property</em> :</p> <p class="spec" id="property1"></p> <p>access a property with <em>["property"]</em> :</p> <p class="spec" id="property2"></p> </div> <script> const person_1a = { firstname: "John", lastname: "Doe", age: 50, eyecolor: "blue" }; document.getElementById("property1").innerHTML = person_1a.firstname + " is " + person_1a.age + " years old."; document.getElementById("property2").innerHTML = person_1a["firstname"] + " is " + person_1a["age"] + " years old."; </script>
New properties to an existing object can be added by giving it a value.
The delete keyword deletes both the value of the property and the property itself. After deletion, the property cannot be used before it is added back again. The delete operator is designed to be used on object properties. It has no effect on variables or functions. The delete operator should not be used on predefined JavaScript object properties. It can crash your application.
Examples
<div class="spec"> <p id="property4"></p> <p id="property5"></p> <p id="property6"></p> </div> <script> const person2 = { firstname: "Thomas", lastname: "Wellens", age: 50, eyecolor: "blue" }; person2.nationality = "English"; document.getElementById("property4").innerHTML = person2.firstname + " is " + person2.nationality + "."; document.getElementById("property5").innerHTML = person2.firstname + " is " + person2.age + " years old."; document.getElementById("property6").innerHTML = person2.firstname + " is " + person2.age + " years old."; </script>
<div class="spec"> <p id="property7"></p> <p id="property8"></p> <p id="property9"></p> </div> <script> const person2a = { firstname: "Thomas", lastname: "Wellens", age: 50, eyecolor: "blue" }; person2a.nationality = "English"; document.getElementById("property7").innerHTML = person2a.firstname + " is " + person2a.nationality + "."; delete person2a.age; document.getElementById("property8").innerHTML = person2a.firstname + " is " + person2a.age + " years old."; delete person2a["age"] document.getElementById("property9").innerHTML = person2a.firstname + " is " + person2a.age + " years old."; </script>
Defining object literals in JavaScript makes life much easier. ES6 provides an even easier way of assigning properties to objects. If the variable name is the same as the object key, you can take advantage of the shorthand notation; if you want to define an object who's keys have the same name as the variables passed-in as properties, you can use the shorthand and simply pass the key name.
base
const name = "Luis", city = "Paris", age = 43, food = "Spaghetti"; let firstname = 'Emma'; let lastname = 'Turner'; let name = 'Katniss'; let surname = 'Everdeen'; let home = 'District 12';
longhand
let person = { name: name, city: city, age: age, food: food }; let contestant = { name: name, surname: surname, home: home } let obj = {firstname: firstname, lastname: lastname}; const x = 1920, y = 1080; const obj = { x:x, y:y };
shorthand
person = { name, city, age, food }; let contestant = { name, surname, home } let obj = {firstname, lastname}; const obj = { x, y };
In JavaScript, you can access the properties and methods of an object with the dot notation. You can use optional chaining by adding a question mark before the dot notation. The optional chaining operator (?.) permits reading the value of a property located deep within a chain of connected objects without having to expressly validate that each reference in the chain is valid. The ?. operator functions similarly to the . chaining operator
base
const data = { a: { b: { c: 10 } } }
longhand
console.log(student && student.address && student.address.ZIPCode); const result = data && data.a && data.a.b && data.a.b.c // 10
shorthand
console.log(student?.address?.ZIPCode); const result = data?.a?.b?.c // 10
Values in an object can be another object. Nested objects can be accessed using the dot notation or the bracket notation.
Examples
<div class="spec"> <p id="property10"></p> <p id="property11"></p> <p id="property12"></p> </div> <script> const myObj = { name: "William", age: 30, cars: { car1: "Ford", car2: "BMW", car3: "Fiat" } } document.getElementById("property10").innerHTML = myObj.cars.car2; document.getElementById("property11").innerHTML = myObj.cars["car3"]; let p1 = "cars"; let p2 = "car1"; document.getElementById("property12").innerHTML = myObj[p1][p2]; </script>
Values in objects can be arrays, and values in arrays can be objects.
Examples
<div class="spec"> <p id="property13"></p> </div> <script> let x = ""; const myObject = { name: "Anthony", age: 45, cars: [ {name:"Ford", models:["Fiesta", "Focus", "Mustang"]}, {name:"BMW", models:["320", "X3", "X5"]}, {name:"Fiat", models:["500", "Panda"]} ] } for (let i in myObject.cars) { x += "<h4>" + myObject.cars[i].name + "</h4>"; for (let j in myObject.cars[i].models) { x += myObject.cars[i].models[j] + "<br>"; } } document.getElementById("property13").innerHTML = x; </script>
All properties have a name. They also have a value.
The value is one of the property's attributes.
Other attributes are: enumerable, configurable, and writable.
These attributes define how the property can be accessed (is it readable?, is it writable?)
In JavaScript, all attributes can be read, but only the value attribute can be changed (and only if the property is writable). ( ECMAScript 5 has methods for both getting and setting all property attributes).
for (let variable in object) { // code to be executed }
The block of code inside the "for...in loop" will be executed once for each property.
Examples: looping object property values.
<div class="spec"> <p id="property14"></p> </div> <script> const person1 = { fname:"John", lname:"Doe", age:25 }; let txt = ""; for (let x in person1) { txt += person1[x] + " "; } document.getElementById("property14").innerHTML = txt; </script>
This is a built-in method provided by JavaScript that iterates the object and returns an array of enumerable properties. Non-enumerable properties are properties of objects that do not appear in the loop when the respective object is passed with Object.keys() or "for ...in" in the loop.
Object.keys(object);
This function takes an object as an input and it is a mandatory parameter. This method only extracts enumerable properties from an Object.
Examples
<div class="spec"> <p id="property15"></p> </div> <script> const inputObject = { id: 82, name: 'Walter Zinzen', address: { city: "Antwerpen", country: "Belgie" } }; Object.defineProperty(inputObject, 'salary',{ value : '30,000$', enumerable: false }) console.log(Object.keys(inputObject)); document.getElementById("property15").innerHTML = Object.keys(inputObject); </script>
This is a built-in method provided by JavaScript that iterates the object and returns an array of properties, including non-enumerable properties.
Object.getOwnPropertyNames(object);
Examples
<div class="spec"> <p id="property16"></p> </div> <script> const inputObject2 = { id: 75, name: 'Roger Devlaeminck', address: { city: "Eeeklo", country: "Belgium" } }; Object.defineProperty(inputObject2, 'salary',{ value : '30,000$', enumerable: false }) console.log(Object.getOwnPropertyNames(inputObject2)); document.getElementById("property16").innerHTML = Object.getOwnPropertyNames(inputObject2); </script>
This function takes a mandatory parameter object as an input. This method only extracts the enumerable and non-enumerable properties of an Object and not the values.
The main difference between getOwnPropertyNames() and Object.keys() is that getOwnPropertyName() returns both the properties enumerable and non-enumerable, whereas the Object.keys() only returns enumerable keys. Non-enumerable properties can be created using Object.defineProperty. An enumerable flag is set to true when the property initializer initializes properties. You can use the propertyIsEnumerable() method to check whether an object contains enumerable or non-enumerable properties.
The border property sets or returns up to three separate border properties, in a shorthand form. With this property, you can set/return one or more of the following (in any order): border-width, border-style, border-color.
return the border property : object.style.border
set the border property : object.style.border = "width style color|initial|inherit"
property values:
width: sets the width of the borders;
style: sets the style of the borders;
color: sets the color of the border;s
initial: sets this property to its default value;
inherit: inherits this property from its parent element. .
Examples
<div class="spec"> <div id="property17">This is a div element.</div><br> <button type="button" onclick="setBorder()">set border</button> </div> <script> function setBorder() { document.getElementById("property17").style.border = "thick solid #0000FF"; } </script>
<div class="spec"> <div id="prop1">This is a div element.</div><br> <button type="button" onclick="setBorder1()">change border</button> </div> <style> #prop1{ border: thick solid darkgreen;} </style> <script> function setBorder1() { document.getElementById("prop1").style.border = "thin dotted red"; } </script>
<div class="spec"> <div id="prop2" style="border:0.2vw solid red;">This is a div element.</div><br> <button type="button" onclick="returnBorder()">return border</button> <p id="prop3"></p> </div> <script> function returnBorder() { document.getElementById("prop3").innerHTML = "div element's border: " + prop2.style.border; } </script>
Examples
<div class="spec"> <p id="descriptor1"></p> <p id="descriptor2"></p> <p id="descriptor3"></p> </div> <script> var myObj1 = { myPropOne: 1, myPropTwo: 2 }; console.dir( myObj1 ); document.getElementById("descriptor1").innerHTML = JSON.stringify(myObj1); // override `myPropOne` property myObj1.myPropOne = 10; console.log( 'myObj.myPropOne =>', myObj1.myPropOne ); console.log( 'myObj =>', myObj1 ); document.getElementById("descriptor2").innerHTML = "myObj.myPropOne => " +JSON.stringify(myObj1.myPropOne); document.getElementById("descriptor3").innerHTML = "myObj => " +JSON.stringify(myObj1); </script>
There are two types of properties in JavaScript:
data properties maps to a value (i.e. primitive value, object, or function).
accessor properties maps to "getter" and "setter" methods.
Each of these property types also has its own property descriptors :
data descriptors ( for data properties) and accessor descriptors (for "getter" and "setter" or accessor properties). A JavaScript property can have only one of the descriptors. It cannot have both descriptors.
these contain the following fields: value, writable, enumerable, configurable.
When a new object is created using the "object literal syntax" or any other method, JavaScript adds the descriptor for each property. By default, it creates the property "writable", "enumerable" and "configurable" set to true. The "value" property is set to the value of the property.
these contain the following fields: set, get, enumerable, configurable.
When a getter and setter property is created using the "object literal syntax" JavaScript adds this descriptor to the property. By default, it creates the descriptor with "enumerable" and "configurable" set to true. The "get" and "set" mapped to the getter and setter functions.
The property descriptor of any property can be read using the getOwnPropertyDescriptor method, which returns the property descriptor of the own property, i.e. property directly present on the object.
The object can be changed, but it will not have any effect on the original property's descriptor.
Parameters:
obj : the object, in which to look for the property;
prop : the name of the property whose description we want to add or modify.
Examples
see also the "console.log"
<div class="spec"> <p id="descriptor4"></p> <p id="descriptor5"></p> </div> <script> const person = { _name: "", get name() { return this._name; }, set name(value) { this._name = value; }, age:30 }; console.log(Object.getOwnPropertyDescriptor(person,'name')); document.getElementById("descriptor4").innerHTML = Object.entries(person, 'name'); console.log(Object.getOwnPropertyDescriptor(person,'age')); document.getElementById("descriptor5").innerHTML = Object.entries(person, 'age'); </script>
value property of the property descriptor is the current value of the property,
writable is whether the user can assign a new value to the property,
enumerable is whether this property will show up in enumerations like for in loop or for of loop or Object.keys,
configurable property tells whether the user has permission to change property descriptor such as to change the value of writable and enumerable settings.
Examples
see also the "console.log"
<div class="spec"> <p id="descriptor6"></p> <p id="descriptor7"></p> </div> <script> var myObj2 = { myPropOne: 2, myPropTwo: 4 }; // get property descriptor of `myPropOne` let descriptor = Object.getOwnPropertyDescriptor( myObj2, 'myPropOne' ); console.log( descriptor ); document.getElementById("descriptor6").innerHTML = JSON.stringify(descriptor, null, 2); </script> </script>
The object returned by the getOwnPropertyDescriptor() can be modified, but it will not change the descriptor of the original property. To change the descriptor of a property, the defineProperty or defineProperties method can be used.
Syntax: Object.defineProperty(obj, prop, descriptor)
Parameters:
obj : the object, in which to look for the property;
prop : the name of the property whose description we want to add or modify,
descriptor : descriptor for the property that wants to add or modify.
For a "new property", if we do not provide any values for writable, enumerable & configurable, then they are set to false. The value is set to undefined.
Examples
see console.log
<div class="spec"> <p id="descriptor7"></p> <p>see console.log</p> </div> <script> const person_b = {}; Object.defineProperty(person_b, "_name", { value: "", writable: true, configurable: true, enumerable: true, }); Object.defineProperty(person_b, "name", { get() { return this._name; }, set(value) { this._name = value; }, configurable: true, enumerable: true, }); Object.defineProperty(person_b, "age", { value: "30", writable: true, configurable: true, enumerable: true, }); console.log(person_b); document.getElementById("descriptor8").innerHTML = JSON.stringify(person_b); </script>
see console.log
<div class="spec"> <p>see console.log</p> <p id="descriptor9"></p> </div> <script> 'use strict'; var myObj3 = { myPropOne: 1, myPropTwo: 2 }; // modify property descriptor Object.defineProperty( myObj3, 'myPropOne', { writable: false } ); // print property descriptor let descriptor2 = Object.getOwnPropertyDescriptor( myObj3, 'myPropOne' ); console.log( descriptor2 ); document.getElementById("descriptor9").innerHTML = JSON.stringify(descriptor2, null, 2); // set new value //myObj3.myPropOne = 2; creates an error as "writeble" is false </script>
Syntax: Object.defineProperties(obj, props), where "obj" is the object, in which to look for the property, "props" is an object whose each property must be a descriptor (either a data descriptor or an accessor descriptor). The name of the key becomes the property name.
For a "new property", if we do not provide any values for writable, enumerable & configurable, then they are set to false. The value is set to undefined.
Examples
see console.log
<div class="spec"> <p id="descriptor3"></p> </div> <script> const person_a = {}; obj= { _name : { value: "", writable: true, configurable: true, enumerable: true, }, name : { get() { return this._name; }, set(value) { this._name = value; }, configurable: true, enumerable: true, }, age : { value: "30", writable: true, configurable: true, enumerable: true, } } Object.defineProperties(person_a,obj); console.log(person_a) document.getElementById("descriptor3").innerHTML = Object.entries(person_a); </script>
let user = {}; // user has no address alert( user?.address?.street ); // undefined (no error) let html = document.querySelector('.elem')?.innerHTML; // will be undefined, if there's no element let user = null; alert( user?.address ); // undefined alert( user?.address.street ); // undefined
let user = null; let x = 0; user?.sayHi(x++); // no "user", so the execution doesn't reach sayHi call and x++ alert(x); // 0, value not incremented
let userAdmin = { admin() { alert("I am admin"); } }; let userGuest = {}; userAdmin.admin?.(); // I am admin userGuest.admin?.(); // nothing happens (no such method) let key = "firstName"; let user1 = { firstName: "John" }; let user2 = null; alert( user1?.[key] ); // John alert( user2?.[key] ); // undefined delete user?.name; // delete user.name if user exists