Built-in objects: Object properties

This lesson documents all the Object built-in object properties and methods.

An object value can be generated using the object literal syntax:

const person = {}
typeof person //object

using the Object global function:

const person = Object()
typeof person //object

or using the Object constructor:

const person = new Object()
typeof person //object

You can initialize the object with properties using this syntax:

const person = {
  age: 36,
  name: 'Flavio',
  speak: () => {
    //speak
  }
}

const person = Object({
  age: 36,
  name: 'Flavio',
  speak: () => {
    //speak
  }
})

const person = new Object({
  age: 36,
  name: 'Flavio',
  speak: () => {
    //speak
  }
})

All those ways are basically equivalent as they all give you access to the methods I’ll list below.

We divide methods in static methods, and instance methods. Static methods are called directly on Object. Instance methods are called on an object instance (an object).

Properties

The Object object has 2 properties

  • length always equal to 1
  • prototype this points to the Object prototype object: the object that all other objects inherit from. Check the prototypal inheritance lesson.

Static methods

Static methods are a great way to offer a namespace for functions that work in the same space. In this way we don’t have global functions around, but all are namespaced under the Object global object.

  • Object.assign() *ES2015
  • Object.create()
  • Object.defineProperties()
  • Object.defineProperty()
  • Object.entries() *ES2017
  • Object.freeze()
  • Object.getOwnPropertyDescriptor()
  • Object.getOwnPropertyDescriptors()
  • Object.getOwnPropertyNames()
  • Object.getOwnPropertySymbols()
  • Object.getPrototypeOf()
  • Object.is() *ES2015
  • Object.isExtensible()
  • Object.isFrozen()
  • Object.isSealed()
  • Object.keys()
  • Object.preventExtensions()
  • Object.seal()
  • Object.setPrototypeOf() *ES2015
  • Object.values()

Instance methods

  • hasOwnProperty()
  • isPrototypeOf()
  • propertyIsEnumerable()
  • toLocaleString()
  • toString()
  • valueOf()

The rest of this lesson describes each method in detail.

Before doing so, I want to spend one minute to introduce the property descriptor object.

Property descriptor object

Any object in JavaScript has a set of properties, and each of these properties has a descriptor.

Some of the methods listed above will make use of the property descriptor object. This is an object that defines a property behavior and own properties.

Those methods include:

  • Object.create()
  • Object.defineProperties()
  • Object.defineProperty()
  • Object.getOwnPropertyDescriptor()
  • Object.getOwnPropertyDescriptors()

Here is an example of a property descriptor object:

{
  value: 'Something'
}

This is the simplest one. value is the property value, in a key-value definition. This key is defined as the object key, when you define this property in an object:

{
  breed: {
    value: 'Siberian Husky'
  }
}

Example:

const animal = {}
const dog = Object.create(animal, {
  breed: {
    value: 'Siberian Husky'
  }
});
console.log(dog.breed) //'Siberian Husky'

You can pass additional properties to define each different object property:

  • value: the value of the property
  • writable: true the property can be changed
  • configurable: if false, the property cannot be removed nor any attribute can be changed, except its value
  • enumerable: true if the property is enumerable
  • get: a getter function for the property, called when the property is read
  • set: a setter function for the property, called when the property is set to a value

writable, configurable and enumerable set the behavior of that property. They have a boolean value, and by default those are all false.

Example:

const animal = {}
const dog = Object.create(animal, {
  breed: {
    value: 'Siberian Husky',
    writable: false
  }
});
console.log(dog.breed) //'Siberian Husky'
dog.breed = 'Pug' //TypeError: Cannot assign to read only property 'breed' of object '#<Object>'

Object.assign()

Introduced in ES2015, this method copies all the enumerable own properties of one or more objects into another.

Its primary use case is to create a shallow copy of an object.

const copied = Object.assign({}, original)

Being a shallow copy, values are cloned, and objects references are copied (not the objects themselves), so if you edit an object property in the original object, that’s modified also in the copied object, since the referenced inner object is the same:

const original = {
  name: 'Fiesta',
  car: {
    color: 'blue'
  }
}
const copied = Object.assign({}, original)

original.name = 'Focus'
original.car.color = 'yellow'

copied.name //Fiesta
copied.car.color //yellow

I mentioned “one or more”:

const wisePerson = {
  isWise: true
}
const foolishPerson = {
  isFoolish: true
}
const wiseAndFoolishPerson = Object.assign({}, wisePerson, foolishPerson)

console.log(wiseAndFoolishPerson) //{ isWise: true, isFoolish: true }

Object.create()

Introduced in ES5.

Creates a new object, with the specified prototype.

Usage:

const newObject = Object.create(prototype)

Example:

const animal = {}
const dog = Object.create(animal)

The newly create object will inherit all the prototyope object properties.

You can specify a second parameter to add new properties to the object, that the prototype lacked:

const newObject = Object.create(prototype, newProperties)

where newProperties is an object of objects that define each property.

Example:

const animal = {}
const dog = Object.create(animal, {
  breed: {
    value: 'Siberian Husky'
  }
});
console.log(dog.breed) //'Siberian Husky'

I didn’t just say breed: 'Siberian Husky' but I had to pass a property descriptor object, defined at the beginning of this page.

Object.create() is often used in combination with Object.assign():

const dog = Object.assign(Object.create(animal), {
  bark() {
    console.log('bark')
  }
})

Object.defineProperties()

Creates or configures multiple object properties at once. Returns the object.

Takes 2 arguments. The first is an object upon which we’re going to create or configure the properties. The second is an object of properties.

Example:

const dog = {}
Object.defineProperties(dog, {
  breed: {
    value: 'Siberian Husky'
  }
})
console.log(dog.breed) //'Siberian Husky'

I didn’t just say breed: 'Siberian Husky' but I had to pass a property descriptor object, defined at the beginning of this page.

It can be used in conjunction with Object.getOwnPropertyDescriptors to copy properties over from another object:

const wolf = { /*... */ }
const dog = {}
Object.defineProperties(dog, Object.getOwnPropertyDescriptors(wolf))

Object.defineProperty()

Creates or configures one object property. Returns the object.

Takes 3 arguments. The first is an object upon which we’re going to create or configure the properties. The second is the property name defined as a string. The third is an object with the property definition.

Example:

const dog = {}
Object.defineProperty(dog, 'breed', {
  value: 'Siberian Husky'
})
console.log(dog.breed) //'Siberian Husky'

I didn’t just say breed: 'Siberian Husky' but I had to pass a property descriptor object, defined at the beginning of this page.

Object.entries()

Introduced in ES2017.

This method returns an array containing all the object own properties, as an array of [key, value] pairs.

Usage:

const person = { name: 'Fred', age: 87 }
Object.entries(person) // [['name', 'Fred'], ['age', 87]]

Object.entries() also works with arrays:

const people = ['Fred', 'Tony']
Object.entries(people) // [['0', 'Fred'], ['1', 'Tony']]

You can use it to count the number of properties an object contains, combined with the length property of the array.

Object.freeze()

Takes an object as argument, and returns the same object. The object passed as argument is mutated and it’s now an immutable object. No properties can be added, no properties can be removed, properties can’t be changed.

Example:

const dog = {}
dog.breed = 'Siberian Husky'
const myDog = Object.freeze(dog)

Object.isFrozen(dog) //true
Object.isFrozen(myDog) //true
dog === myDog //true

dog.name = 'Roger' //TypeError: Cannot add property name, object is not extensible

In the example, both dog and myDog are frozen. The argument passed as argument to Object.freeze() is mutated, and can’t be un-freezed. It’s also returned as argument, hence dog === myDog (it’s the same exact object).

Calling Object.freeze() is the equivalent of calling Object.preventExtensions() to prevent an object to have more properties defined, plus setting all properties as non-configurable and non-writeable.

Object.getOwnPropertyDescriptor()

I talked about property descriptors up above at the beginning of this lesson. This method can be used to retrieve the descriptor of a specific property.

Usage:

const propertyDescriptor = Object.getOwnPropertyDescriptor(object, propertyName)

Example:

const dog = {}
Object.defineProperties(dog, {
  breed: {
    value: 'Siberian Husky'
  }
})
Object.getOwnPropertyDescriptor(dog, 'breed')
/*
{
  value: 'Siberian Husky',
  writable: false,
  enumerable: false,
  configurable: false
}
*/

Object.getOwnPropertyDescriptors()

This method returns all own (non-inherited) properties descriptors of an object.

Object.getOwnPropertyDescriptors(obj) accepts an object, and returns a new object that provides a list of the descriptors.

Example:

const dog = {}
Object.defineProperties(dog, {
  breed: {
    value: 'Siberian Husky'
  }
})
Object.getOwnPropertyDescriptors(dog)
/*
{
  breed: {
    value: 'Siberian Husky',
    writable: false,
    enumerable: false,
    configurable: false
  }
}
*/

There is one use case that makes this property very useful. ES2015 gave us Object.assign(), which copies all enumerable own properties from one or more objects, and return a new object. However there is a problem with that, because it does not correctly copies properties with non-default attributes.

If an object has just a setter, it’s not correctly copied to a new object, using Object.assign(). For example, with this object:

const person1 = {
  set name(newName) {
    console.log(newName)
  }
}

This copy attempt won’t work:

const person2 = {}
Object.assign(person2, person1)

But this will work and copy over the setter correctly:

const person3 = {}
Object.defineProperties(person3,
  Object.getOwnPropertyDescriptors(person1))

As you can see with a console test:

person1.name = 'x'
"x"

person2.name = 'x'

person3.name = 'x'
"x"

person2 misses the setter, it was not copied over.

The same limitation goes for shallow cloning objects with Object.create().

Object.getOwnPropertyNames()

Object.getOwnPropertyNames() returns an array containing all the names of the own properties of the object passed as argument, including non-enumerable properties. It does not consider inherited properties.

Non enumerable properties are not iterated upon. Not listed in for..of loops, for example.

To get only a list of the enumerable properties you can use Object.keys() instead.

Example:

const dog = {}
dog.breed = 'Siberian Husky'
dog.name = 'Roger'

Object.getOwnPropertyNames(dog) //[ 'breed', 'name' ]

Object.getOwnPropertySymbols()

Get an array of symbols defined on an object.

Symbols is an ES2015 feature, and this method was introduced in ES2015 as well.

Example:

const dog = {}
const r = Symbol('Roger')
const s = Symbol('Syd')
dog[r] = {
  name: 'Roger',
  age: 6
}
dog[s] = {
  name: 'Syd',
  age: 5
}

Object.getOwnPropertySymbols(dog) //[ Symbol(Roger), Symbol(Syd) ]

Object.getPrototypeOf()

Returns the prototype of an object.

Usage:

Object.getPrototypeOf(obj)

Example:

const animal = {}
const dog = Object.create(animal)
const prot = Object.getPrototypeOf(dog)

animal === prot //true

If the object has no prototype, we’ll get null. This is the case of the Object object:

Object.prototype //{}
Object.getPrototypeOf(Object.prototype) //null

Object.is()

This method was introduced in ES2015. It aims to help comparing values.

Usage:

Object.is(a, b)

The result is always false unless:

  • a and b are the same exact object
  • a and b are equal strings (strings are equal when composed by the same characters)
  • a and b are equal numbers (numbers are equal when their value is equal)
  • a and b are both undefined, both null, both NaN, both true or both false

0 and -0 are different values in JavaScript, so pay attention in this special case (convert all to +0 using the + unary operator before comparing, for example).

Object.isExtensible()

This method checks if we can add new properties to an object.

Any object is extensible, unless it’s been used as an argument to

  • Object.freeze()
  • Object.seal()
  • Object.preventExtensions()

Usage:

const dog = {}
Object.isExtensible(dog) //true
const cat = {}
Object.freeze(cat)
Object.isExtensible(cat) //false

Object.isFrozen()

Accepts an object as argument, and returns true if the object is frozen, false otherwise. Objects are frozen when they are return values of the Object.freeze() function.

Example:

const dog = {}
dog.breed = 'Siberian Husky'
const myDog = Object.freeze(dog)
Object.isFrozen(dog) //true
Object.isFrozen(myDog) //true
dog === myDog //true

In the example, both dog and myDog are frozen. The argument passed as argument to Object.freeze() is mutated, and can’t be un-freezed. It’s also returned as argument, hence dog === myDog (it’s the same exact object).

Object.isSealed()

Accepts an object as argument, and returns true if the object is sealed, false otherwise. Objects are sealed when they are return values of the Object.seal() function.

Example:

const dog = {}
dog.breed = 'Siberian Husky'
const myDog = Object.seal(dog)
Object.isSealed(dog) //true
Object.isSealed(myDog) //true
dog === myDog //true

In the example, both dog and myDog are sealed. The argument passed as argument to Object.seal() is mutated, and can’t be un-sealed. It’s also returned as argument, hence dog === myDog (it’s the same exact object).

Object.keys()

Object.keys() accepts an object as argument and returns an array of all its (own) enumerable properties.

const car = {
  color: 'Blue',
  brand: 'Ford',
  model: 'Fiesta'
}

Object.keys(car) //[ 'color', 'brand', 'model' ]

I said enumerable properties. This means their internal enumerable flag is set to true, which is the default. Check MDN for more info on this subject.

One use of the Object.keys function is to create a copy of an object that has all the properties of it, except one:

const car = {
  color: 'blue',
  brand: 'Ford'
}
const prop = 'color'

const newCar = Object.keys(car).reduce((object, key) => {
  if (key !== prop) {
    object[key] = car[key]
  }
  return object
}, {})

Object.preventExtensions()

Takes an object as argument, and returns the same object. The object passed as argument is mutated and it’s now an object that will not accept new properties. New properties can’t be added, but existing properties can be removed, and existing properties can be changed.

Example:

const dog = {}
dog.breed = 'Siberian Husky'
Object.preventExtensions(dog)

dog.name = 'Roger' //TypeError: Cannot add property name, object is not extensible

The argument passed as argument is also returned as argument, hence dog === myDog (it’s the same exact object).

We can’t add new properties, but we can remove existing properties:

const dog = {}
dog.breed = 'Siberian Husky'
dog.name = 'Roger'
Object.preventExtensions(dog)
delete dog.name
dog //{ breed: 'Siberian Husky' }

Object.seal()

Takes an object as argument, and returns the same object. The object passed as argument is mutated and it’s now an object that will not accept new properties. New properties can’t be added, and existing properties can’t be removed, but existing properties can be changed.

Example:

const dog = {}
dog.breed = 'Siberian Husky'
Object.seal(dog)
dog.breed = 'Pug'
dog.name = 'Roger' //TypeError: Cannot add property name, object is not extensible

The argument passed as argument is also returned as argument, hence dog === myDog (it’s the same exact object).

Similar to Object.freeze() but does not make properties non-writable. In only prevents to add or remove properties.

Similar to Object.preventExtensions() but also disallows removing properties:

const dog = {}
dog.breed = 'Siberian Husky'
dog.name = 'Roger'
Object.seal(dog)
delete dog.name //TypeError: Cannot delete property 'name' of #<Object>

Object.setPrototypeOf() *ES2015

Set the prototype of an object. Accepts two arguments: the object and the prototype.

Usage:

Object.setPrototypeOf(object, prototype)

Example:

const Animal = {}
Animal.isAnimal = true

const Mammal = Object.create(Animal)
Mammal.isMammal = true

console.log('-------')
Mammal.isAnimal //true

const dog = Object.create(Animal)

dog.isAnimal  //true
console.log(dog.isMammal)  //undefined

Object.setPrototypeOf(dog, Mammal)

console.log(dog.isAnimal) //true
console.log(dog.isMammal) //true

Object.values()

This method returns an array containing all the object own property values.

Usage:

const person = { name: 'Fred', age: 87 }
Object.values(person) // ['Fred', 87]

Object.values() also works with arrays:

const people = ['Fred', 'Tony']
Object.values(people) // ['Fred', 'Tony']

Let’s now define the instance methods that any object has. We call these on the object itself, not on the Object global object.

hasOwnProperty()

Called on an object instance, accepts a string as argument. If the object has a property with the name contained in the string argument, it returns true. Otherwise it returns false.

Example:

const person = { name: 'Fred', age: 87 }
person.hasOwnProperty('name') //true
person.hasOwnProperty('job') //false

isPrototypeOf()

Called on an object instance, accepts an object as argument. If the object you called isPrototypeOf() on appears in the prototype chain of the object passed as argument, it returns true. Otherwise it returns false.

Example:

const Animal = {
  isAnimal: true
}

const Mammal = Object.create(Animal)
Mammal.isMammal = true

Animal.isPrototypeOf(Mammal) //true

const dog = Object.create(Animal)
Object.setPrototypeOf(dog, Mammal)

Animal.isPrototypeOf(dog) //true
Mammal.isPrototypeOf(dog) //true

propertyIsEnumerable()

Called on an object instance, accepts a string as argument. If the object has a property with the name contained in the string argument, and that property is enumerable, it returns true. Otherwise it returns false.

Example:

const person = { name: 'Fred' }

Object.defineProperty(person, 'age', {
  value: 87,
  enumerable: false
})

person.propertyIsEnumerable('name') //true
person.propertyIsEnumerable('age') //false

toLocaleString()

Called on an object instance, returns a string representation of the object. Accepts an optional locale as argument.

Returns the [object Object] string unless overridden. Objects can then return a different string representation depending on the locale.

const person = { name: 'Fred' }
person.toLocaleString() //[object Object]

toString()

Called on an object instance, returns a string representation of the object. Returns the [object Object] string unless overridden. Objects can then return a string representation of themselves.

const person = { name: 'Fred' }
person.toString() //[object Object]

valueOf()

Called on an object instance, returns the primitive value of it.

const person = { name: 'Fred' }
person.valueOf() //{ name: 'Fred' }

This is normally only used internally by JavaScript, and rarely actually invoked in user code.

Lessons in this unit:

0: Introduction
1: The global object
2: ▶︎ Object properties
3: Number
4: String
5: Math
6: JSON
7: Date
8: Intl
9: Set and Map
Are you intimidated by Git? Can’t figure out merge vs rebase? Are you afraid of screwing up something any time you have to do something in Git? Do you rely on ChatGPT or random people’s answer on StackOverflow to fix your problems? Your coworkers are tired of explaining Git to you all the time? Git is something we all need to use, but few of us really master it. I created this course to improve your Git (and GitHub) knowledge at a radical level. Launching May 21, 2024. Join the waiting list!