Details about javascript objects
- Transfer
- Tutorial
The author of the material, the translation of which we are publishing today, says that there are many things in JavaScript objects that one could not even suspect about the existence of using them in their daily work. Objects in JavaScript are very easy to create, it is convenient to work with them, they seem to be understandable and flexible entities, and many programmers simply do not think that objects are actually arranged is not so simple.

Here we will talk about what is hidden in the depths of objects and discuss the subtleties of working with them.
Having mastered this material, you will know the answers to the following questions:
You have probably created countless objects resembling this one:
Properties
Such properties are also known as getters and setters, they are found in other programming languages like C # or Python. A property with access methods (Accessor Property) is a combination of two functions -
When declaring such properties instead of using the traditional construction of the form
Take a look at the object
When an attempt is made to access a property
Functions
Here’s what an object declaration with a getter and setter looks like:
The setter function gets what it is trying to assign to the property of the object, as a parameter. Now you can save something in the object property. In this case, we create a "private" property of the object
At the same time, in the getter function, before returning the value of the property
Here is what it might look like:
This program, by the way, contains the answer to one of the questions given at the beginning of the article, which concerns the analysis of a code that is incomprehensible at first glance.
Why would anyone need properties with access methods if you can safely work with ordinary properties? For example, they may be needed in order to log information about property read operations, or to keep a history of changes in property values. Properties with access methods give us all the possibilities of data processing with the help of functions and the simplicity characteristic of working with ordinary properties. More information about the use of such properties can be found here .
How does JavaScript distinguish regular properties that store data from properties with accessors? Let's figure it out.
At first glance it may seem that there is a direct correspondence between the keys and the values stored in the objects. However, this is not quite true.
Associated with each object key is a set of attributes that define the characteristics of the value associated with a given key. These attributes can also be viewed as metadata describing the pair
Attributes are used to set and describe the state of object properties. The set of property attributes is called a descriptor. There are six property attributes:
Why are property attribute names in this list enclosed
Consider the following image taken from here , where you can see the object and the attributes of its properties.

Object and attributes of its properties
. Our object has 2 keys -
How can JavaScript get object information like those shown in the previous figure? To do this, you can use the function
It should be noted that the composition of the attributes of a particular property depends on its type. All six attributes of the same property are not found.
This attribute stores what is issued when trying to get the value of an object property. That is, if in the previous example we use the view construct
This attribute stores a link to the function, which is a getter property. This function is called without arguments when trying to read the value of a property.
Here is a reference to the function declared when creating the setter property. It is called with an argument representing the value that the property was attempted to assign, that is, it is called with each assignment operation to the property of a new value.
In this example, the right side of the expression is passed as the argument
This attribute stores a boolean value. It indicates whether the value of the property can be rewritten or not. If a value is stored here
The logical value is also stored here. This attribute governs the output of a property in cycles
This attribute is also represented by a logical value. This is what happens if a value is stored in it
The effect of setting this attribute to a value
Now that we are familiar with the attributes, let us ask ourselves how we can influence them. In JavaScript, there are special functions designed to work with property descriptors. Let's talk about them.
We have already met with this method. It, taking the object and the name of its property, returns either
This is a static method
It can be run in the Node.js environment. The code is quite large, but, in fact, it is quite simple. We will analyze it, focusing on the comments of the form
In the snippet,
In a place marked as
Creating an object (fragment
Teams
The command
The fragment
Periodically, the developer needs to protect objects from outside interference. For example, given the flexibility of JavaScript, it is very easy to mistakenly change the properties of an object, which should not change. There are three main ways to protect objects.
The method
To find out if an object is non-expandable, you can use the method
The method
As a result, it turns out that this method prevents the addition of new properties to the object and the deletion of existing properties in it.
Consider an example:
To check whether the object is “sealed” or not, you can use the method
The method
Here is an example:
You can check whether the object is “frozen” by using the method
It is important to note that the methods described above, used to protect objects, affect only their properties, which are not objects.
Here is a summary table on the considered methods of protection of objects, which is taken from here .
Considering how often objects are used in JavaScript code, it is important for each developer to know how they work. We hope that what you have learned by reading this material will be useful to you. In addition, now you know the answers to the questions listed at the beginning of the article.
Dear readers! How do you protect JavaScript objects?


NB: Information from the publication in practice should be applied very carefully and under the supervision of more experienced colleagues.
Here we will talk about what is hidden in the depths of objects and discuss the subtleties of working with them.
Having mastered this material, you will know the answers to the following questions:
- How to make a property of the object to be deleted?
- What are the properties with access methods and what are their features?
- How to make a property immutable or hidden?
- Why are some properties not visible in cycles
for-in
or in the results of the methodObject.keys()
, and some - visible? - How to “protect” an object from modification?
- How to understand a code snippet like this:
obj.id = 5;
console.log(obj.id)
// => '101' (5 в двоичной системе счисления)
Types of properties of objects
▍Properties storing data
You have probably created countless objects resembling this one:
const obj = {
name: 'Arfat',
id: 5
}
obj.name
// => 'Arfat'
Properties
name
and id
objects obj
are called properties that store data, or “data properties” (Data Properties). These are familiar properties that are constantly found in JavaScript code. What other kinds of properties can objects have?▍Properties with access methods
Such properties are also known as getters and setters, they are found in other programming languages like C # or Python. A property with access methods (Accessor Property) is a combination of two functions -
get
and set
. When declaring such properties instead of using the traditional construction of the form
ключ: значение
, the following syntax is used:const accessorObj = {
get name() {
return'Arfat';
}
};
accessorObj.name;
// => 'Arfat'const dataObj = {
name: 'Arfat',
};
dataObj.name;
// => 'Arfat'
Take a look at the object
accesorObj
and compare it with the object dataObj
. As you can see, they are now showing the same behavior. In describing the first object, we used the keyword get
, followed by the function declaration. In order to access such a property, although it is represented by a function, it is not necessary to put parentheses after the name of the property to call this function. That is the design like is accessorObj.name();
incorrect. When an attempt is made to access a property
accessorObj.name
, that is, when an attempt is made to read it, the corresponding function is executed and the value returned to it becomes the value of the property name
. Functions
get
are called getters, they are responsible for getting values. If we continue our example and try to change the value of the propertyname
an object accessorObj
, say, by executing a command accessorObj.name = 'New Person’;
, it turns out that nothing will happen. The point here is that the name
setter function is not associated with the key . Such functions allow you to customize the order in which new values are assigned to properties of objects, access to which is organized using getters. Here’s what an object declaration with a getter and setter looks like:
const accessorObj = {
_name: 'Arfat',
get name() {
returnthis._name;
},
set name(value) {
this._name = value;
}
};
The setter function gets what it is trying to assign to the property of the object, as a parameter. Now you can save something in the object property. In this case, we create a "private" property of the object
_name
. The first symbol of the name of such a property is an underscore, which is nothing more than a hint for the programmer, indicating that this property is intended for the internal needs of the object. Further, we work with it when referring to the property of an object name
, access to which is regulated by a getter and a setter. At the same time, in the getter function, before returning the value of the property
_name
, we can modify it. Here is what it might look like:
const obj = {
get name() {
returnthis._name.toUpperCase();
},
set name(value) {
this._name = value;
},
get id() {
returnthis._id.toString(2); // Преобразуем десятичное число в его двоичное представление
},
set id(value) {
this._id = value;
}
}
obj.name = 'Arfat';
obj.name;
// => 'ARFAT'
obj.id = 5;
obj.id;
// => '101
This program, by the way, contains the answer to one of the questions given at the beginning of the article, which concerns the analysis of a code that is incomprehensible at first glance.
Why would anyone need properties with access methods if you can safely work with ordinary properties? For example, they may be needed in order to log information about property read operations, or to keep a history of changes in property values. Properties with access methods give us all the possibilities of data processing with the help of functions and the simplicity characteristic of working with ordinary properties. More information about the use of such properties can be found here .
How does JavaScript distinguish regular properties that store data from properties with accessors? Let's figure it out.
Object Property Descriptors
At first glance it may seem that there is a direct correspondence between the keys and the values stored in the objects. However, this is not quite true.
Свойств Property Attributes
Associated with each object key is a set of attributes that define the characteristics of the value associated with a given key. These attributes can also be viewed as metadata describing the pair
ключ: значение
. Attributes are used to set and describe the state of object properties. The set of property attributes is called a descriptor. There are six property attributes:
[[Value]]
[[Get]]
[[Set]]
[[Writable]]
[[Enumerable]]
[[Configurable]]
Why are property attribute names in this list enclosed
[[]]
? Double parentheses indicate that these are entities used by the internal mechanisms of the language. The JS programmer cannot access these properties directly. In order to influence them, appropriate methods are used. Consider the following image taken from here , where you can see the object and the attributes of its properties.

Object and attributes of its properties
. Our object has 2 keys -
x
andy
. In addition, each of them is associated with a set of attributes. How can JavaScript get object information like those shown in the previous figure? To do this, you can use the function
Object.getOwnPropertyDescriptor()
. It takes an object and the name of its property, and then returns an object containing the attributes of this property. Here is an example:const object = {
x: 5,
y: 6
};
Object.getOwnPropertyDescriptor(object, 'x');
/*
{
value: 5,
writable: true,
enumerable: true,
configurable: true
}
*/
It should be noted that the composition of the attributes of a particular property depends on its type. All six attributes of the same property are not found.
- If we are talking about the properties of the data, then they will only attributes
[[Value]]
,[[Writable]]
,[[Enumerable]]
and[[Configurable]]
. - Properties with access methods, instead of attributes
[[Value]]
and[[Writable]]
, have attributes[[Get]]
and[[Set]]
.
▍ [[Value]]
This attribute stores what is issued when trying to get the value of an object property. That is, if in the previous example we use the view construct
object.x
, we get what is stored in the attribute [[Value]]
. The same thing will happen when trying to read the properties of an object using square brackets.▍ [[Get]]
This attribute stores a link to the function, which is a getter property. This function is called without arguments when trying to read the value of a property.
▍ [[Set]]
Here is a reference to the function declared when creating the setter property. It is called with an argument representing the value that the property was attempted to assign, that is, it is called with each assignment operation to the property of a new value.
const obj = {
set x(val) {
console.log(val)
// => 23
}
}
obj.x = 23;
In this example, the right side of the expression is passed as the argument
val
to the setter function. Here is the code that demonstrates the use of setters and getters.▍ [[Writable]]
This attribute stores a boolean value. It indicates whether the value of the property can be rewritten or not. If a value is stored here
false
, then attempts to change the value of a property will not succeed.▍ [[Enumerable]]
The logical value is also stored here. This attribute governs the output of a property in cycles
for-in
. If it is set to a value true
, then it will be possible to work with the property using such cycles.▍ [[Configurable]]
This attribute is also represented by a logical value. This is what happens if a value is stored in it
false
:- The property cannot be deleted.
- It will not be possible to convert properties that store data into properties with access methods, and vice versa. Attempts to perform such transformations will not lead to anything.
- It will be forbidden to change property attribute values. That is immutable will be the current values of attributes
[[Enumerable]]
,[[Configurable]]
,[[Get]]
and[[Set]]
.
The effect of setting this attribute to a value
false
also depends on the type of property. This attribute, in addition to the above effects on the properties, acts on them and so:- If we have a property that stores data, then the attribute
[[Writable]]
can only be changed fromtrue
tofalse
. - As long as the attribute is
[[Writable]]
not setfalse
, you can change the attribute[[Value]]
. But after thefalse
attributes are set in[[Writable]]
and[[Configurable]]
, the property will be unrecordable, undeletable and immutable.
Work with Handles
Now that we are familiar with the attributes, let us ask ourselves how we can influence them. In JavaScript, there are special functions designed to work with property descriptors. Let's talk about them.
Object Method Object.getOwnPropertyDescriptor ()
We have already met with this method. It, taking the object and the name of its property, returns either
undefined
, or an object with a property descriptor.Object Method Object.defineProperty ()
This is a static method
Object
that allows you to add properties to objects or change existing properties. It takes three arguments — an object, a property name, and an object with a handle. This method returns a modified object. Consider an example:const obj = {};
// #1Object.defineProperty(obj, 'id', {
value: 42
});
// #2console.log(obj);
// => { }// #3console.log(obj.id);
// => 42// #4Object.defineProperty(obj, 'name', {
value: 'Arfat',
writable: false,
enumerable: true,
configurable: true
});
// #5console.log(obj.name);
// => 'Arfat'// #6
obj.name = 'Arfat Salman'// #7console.log(obj.name);
// => 'Arfat' // (а не 'Arfat Salman')Object.defineProperty(obj, 'lastName', {
value: 'Salman',
enumerable: false,
});
console.log(Object.keys(obj));
// => [ 'name' ]// #8delete obj.id;
// #9console.log(obj.id);
// => 42//#10Object.defineProperties(obj, {
property1: {
value: 42,
writable: true
},
property2: {}
});
console.log(obj.property1)
// => 42
It can be run in the Node.js environment. The code is quite large, but, in fact, it is quite simple. We will analyze it, focusing on the comments of the form
// #n
. In the snippet,
#1
we use a function defineProperty
, passing it an object obj
, the name of a property, id
and a descriptor object containing only a property value
indicating that the [[Value]]
value will be written to the attribute 42
. Remember that if you do not pass in this object values for attributes like [[Enumerable]]
or [[Configurable]]
, then they will, by default, be set to a value false
. In this case, attributes [[Writable]]
, [[Enumerable]]
and [[Configurable]]
the properties id
are set in false
. In a place marked as
#2
, we are trying to display a string representation of the object in the console. Since its property id
is non-enumerable, it will not be inferred. At the same time, the property exists, which proves its successful output by the command #3
. Creating an object (fragment
#4
), we set the complete list of attributes. In particular, set [[Writable]]
to value false
. Teams
#5
and #7
we display the value of the property name
. But between them (fragment #6
) we tried to change this value. This operation did not change the value of the property because its attribute is [[Writable]]
set to false
. As a result, both commands output the same to the console. The command
#8
is an attempt to delete a property.id
. Recall that its attribute is [[Configurable]]
set to a value false
, which means that it cannot be removed. This is proved by the team #9
. The fragment
#10
shows the use of the Object.defineProperties () function . It works in the same way as a function defineProperty()
, but allows, in one call, to affect several properties of an object, while it defineProperty()
works with only one property of an object.Protection of objects
Periodically, the developer needs to protect objects from outside interference. For example, given the flexibility of JavaScript, it is very easy to mistakenly change the properties of an object, which should not change. There are three main ways to protect objects.
Object Method Object.preventExtensions ()
The method
Object.preventExtensions()
prevents the object from expanding, that is, adding new properties to it. It takes an object and makes it non-expandable. Note that you can delete properties from such an object. Consider an example:const obj = {
id: 42
};
Object.preventExtensions(obj);
obj.name = 'Arfat';
console.log(obj);
// => { id: 42 }
To find out if an object is non-expandable, you can use the method
Object.isExtensible()
. If it returns true
, then new properties can be added to the object.Object Method Object.seal ()
The method
seal()
“seals” the objects. This is what it is about:- Its use prevents the addition of new properties to an object (in this it is similar
Object.preventExtensions()
). - It makes all existing properties of the object non-configurable.
- Values of existing properties, if their attribute is
[[Writable]]
not set tofalse
, can be changed.
As a result, it turns out that this method prevents the addition of new properties to the object and the deletion of existing properties in it.
Consider an example:
const obj = {
id: 42
};
Object.seal(obj);
delete obj.id
// (не работает)
obj.name = 'Arfat';
// (не работает)console.log(obj);
// => { id: 42 }Object.isExtensible(obj);
// => falseObject.isSealed(obj);
//=> true
To check whether the object is “sealed” or not, you can use the method
Object.isSealed()
.Object Method Object.freeze ()
The method
freeze()
allows you to "freeze" objects, equipping them with the highest possible level of protection in JavaScript. Here is how it works:- “Seals” an object with
Object.seal()
. - Completely prohibits the modification of any existing object properties.
- Forbids modification of property descriptors.
Here is an example:
const obj = {
id: 42
};
Object.freeze(obj);
delete obj.id
// (не работает)
obj.name = 'Arfat';
// (не работает)console.log(obj);
// => { id: 42 }Object.isExtensible(obj);
// => falseObject.isSealed(obj);
//=> trueObject.isFrozen(obj);
// => true
You can check whether the object is “frozen” by using the method
Object.isFrozen()
.▍ Overview of methods used to protect objects
It is important to note that the methods described above, used to protect objects, affect only their properties, which are not objects.
Here is a summary table on the considered methods of protection of objects, which is taken from here .
Property creation | Reading property | Property rewrite | Property removal | |
Object.freeze() | - | + | - | - |
Object.seal() | - | + | + | - |
Object.preventExtensions() | - | + | + | + |
Results
Considering how often objects are used in JavaScript code, it is important for each developer to know how they work. We hope that what you have learned by reading this material will be useful to you. In addition, now you know the answers to the questions listed at the beginning of the article.
Dear readers! How do you protect JavaScript objects?
