Dynamic creation of javascript objects. Removing object properties


Greetings to everyone who reads this publication. Today I want to walk you through a key tool of the language - JavaScript objects. Let me remind you that js is cross-browser and works on all operating systems (windows, mac os, etc.). Unlike object-oriented programming languages, the implementation of objects in js differs significantly from the usual functionality and variations in the use of instances, for example, in C#.

Therefore, after reading the current article, you will learn the main distinguishing features of script objects, learn in what ways they can be created, updated and deleted. I will also touch on the topic of properties, methods and constructors, and talk about useful commands and of course a little about inheritance. I think it's time to start learning!

What is an object in JavaScript and what capabilities does it have?

In js, objects are simple associative arrays (they are also called hashes).

What is an associative array?

This is a data structure that stores a certain amount of information relating to and describing a specific element. All data is structured and interconnected as “key => value”.

For example, you need to describe cars. Then you create an auto object and describe its characteristics in an array. I decided to describe the make of the car (name), its color (color) and cost (price). Below I have attached the code for implementing the described task.

1 2 3 4 5 var avto = ( name: "BMW 116i", color: "black", price: 588000 );

var avto = ( name: "BMW 116i", color: "black", price: 588000 );

Here you see one way to create an object called “avto”. Name, color and price are keys that can be used during the writing of the application.

I got ahead of myself with this example, so now let’s look at everything in order.

You can create an object in several ways:

var auto = (); or var auto = new Object();

In both cases an empty object is created with famous name, but the first option is used much more often, since it is shorter and more convenient to write.

All about properties

Now you need to fill the empty object with parameters. To do this, you need to add properties, which I also called keys above. Again, there are two ways to declare properties.

I would like to note that JavaScript does not have a strict framework for creating and initializing such parameters. New properties can appear throughout the code, just as they can be deleted and updated.

Thus, you can create all the keys at once or declare them as they become available. And even if during the writing of the program you turn to non- existing keys, there will be no error. In this case, “undefined” will be returned.

First way.

Creating and accessing properties using a dot. To implement this option, you need to write the name of the object, and then add the name of the key to it through a dot and then assign some value through the equal sign:

avto.name = “BMW 116i”

But in this method you will add one more element to the existing keys:

This method is used when the name of the property is already known and you need to do certain actions with the values.

Second way.

No different from the first, if you compare their purposes. However, this method has slight advantage. For this option use square brackets:

avto[“name”] = “BMW 116i”

A nice addition is the ability to create property names in the form of any string. Eg,

avto[“name of the car”] = “BMW 116i”

Working with keys through square brackets is used when some parameters are entered by the user and stored in variables or when the names of properties are unknown in advance. For example, a user requests the price of a selected car. The element that was called is written to the variable, and the price is sent in response:

var auto = (); avto.name = "BMW_116i"; avto.price = 588000; var key = "price"; // the price of the car was requested alert(avto);

Now let's move on to deleting properties. Everything is very simple here. To remove, use the command delete. So, if you add the following 2 lines to the last example below:

delete auto.price;

alert(auto);

Then, when calling alert a second time, the dialog box will display “undefined”.

A few words about compactness

At the current stage, I told you how to create an object and describe its properties. I have attached test cases to this, but the most attentive of you, dear readers, have noticed that the first program code somewhat different from all the others.

And all because it uses a compact data representation. This is a very popular method of declaring keys because it is shorter to write and easier to understand visually.

Let's go through our properties

In JavaScript, you can quickly iterate through created properties. For this purpose, a special mechanism was provided, better known as cycle.

If you are familiar with other programming languages, you know that most often loops are created using the word for, then the condition for enumerating elements is written in parentheses.

In js it resembles a loop in its appearance foreach from the C# language. Check out the general design:

for (var obj in object) ( // performing the search)

where obj is responsible for the name of the enumerated keys,

object – for their values.

And now here is a concrete example for you.

1 2 3 4 5 6 7 8 var avto = ( name: "BMW 116i", color: "black", price: 588000 ); for (var obj in object) ( alert(obj + ":" + object) )

var avto = ( name: "BMW 116i", color: "black", price: 588000 ); for (var obj in object) ( alert(obj + ":" + object) )

It's time to get acquainted with the methods

The scripting language provides for the creation of methods. This is an absolutely simple mechanism with which at any time you can add a method or methods to any object that expand the capabilities of the created associative arrays. They are also called function properties.

Js itself is very dynamic and amazing to some extent. This is how you can create elements of different types. When learning this language, you do not need to memorize complex structures, since many declarations are very similar to each other.

So, to create a method, you need to declare an object, and then start writing a command that is exactly like creating properties. However, after “=” it is no longer the value that is written, but the keyword function (variable). And then in curly braces actions are listed.

Here is the implementation of this mechanism:

var avto =() avto.name = “BMV” avto.year = 1999 avto.drive = function(k) ( alert(“The car has passed”+n+“ km.”)) avto.drive(300) avto.drive( 450)

As you can see, this example contains properties and methods whose calls are initially identical.

Does JS also have constructors?

Yes sir! In this language, everything that uses the keyword " new", automatically becomes a constructor. So, above you saw the declaration of an empty object in the form: avto = new Object ();. This is the constructor.

For clarity, consider the lines below.

var bob = new Object();

bob.name = "Bob Smith";

However, this is not the entire arsenal of possibilities. In js, you can create your own constructors and then use them to declare new objects.

So, I want to “make” a custom constructor for already existing cars. Please note that the name must be written with capital letters. This is the hallmark of functions. To do this, I write the following software implementation:

function Auto (name, price) (

this.name = name;

this.price = price;

Now, when you create an unlimited number of objects and apply this constructor to them, they will all belong to the same class. For example:

var car1 = new Avto("BMW", 650000);

var car2 = new Avto("Audi", 520000);

In addition to this, you can create methods inside the constructor.

Features of inheritance in JavaScript

Typically, in many languages, inheritance is based on classes that can inherit from each other. Then you can hear expressions such as “ancestor class”, “child class”, etc.

However, in js everything is different. This is where objects are inherited.

All inheritance is based on an internal reference between objects, which is known as a "prototype". If you add “.prototype” to a method using a dot, and then enter the name of the prototype, then all objects of the selected method will be inherited from this prototype.

Let's move on to an example.

function Transport (name) ( this.name = name this.canDrive = true ) var transport = new Transport ("avto") // created a transport object function Bike (name) ( this.name = name ) Bike.prototype = transport / / specify that all new objects of this class will use transport bike1 = new Bike ("for_sport") bike2= new Bike ("for_child") console.log(bike1.name) console.log(bike2.name) console .log(bike1.canDrive)

I guess I'll end here. I told you about the fundamental aspects scripting language. However, this is only superficial knowledge. Next we will go deeper. In the meantime, don’t forget to join the ranks of my subscribers and share the link to the article with your friends. Good luck!

Bye bye!

Best regards, Roman Chueshov

Read: 97 times

JavaScript is an object-oriented language. With the exception of basic language constructs such as loops and relational operators, almost every feature of JavaScript is implemented using objects in one way or another.

Sometimes objects are used explicitly to perform specific tasks, such as, for example, processing (X)HTML and XML-based documents object model document. In other cases, the role of objects is less obvious, such as the role of the String object when working with primitive string data.

Previous chapters have provided examples that clearly demonstrate the usefulness of built-in objects, but in this chapter we'll dive into JavaScript objects directly.

Objects in JavaScript

Objects in JavaScript can be divided into four groups.

  1. User objects created by the programmer and having a structure and entity that suit a specific programming task. We will discuss the possibilities of creating and using such objects in this chapter.
  2. Built-in objects are provided by the JavaScript language itself. These include objects that are associated with data types (String, Number, and Boolean), objects that allow you to create custom objects and composite types (Object and Array), and objects that make common tasks easier (such as Date, Math, and RegExp). The capabilities of built-in objects are regulated by the ECMA-262 language standard and, to a lesser extent, by browser manufacturer specifications.
  3. Browser objects that are not part of JavaScript language, but supported by most browsers. Examples of browser objects are Window, an object through which browser windows are managed and interact with the user, and Navigator, an object that provides client configuration information. Because most aspects of browser objects are not governed by any standards, their properties and behavior can vary greatly depending on both the browser and its version. Objects of this type will be discussed further.
  4. Document objects are part of the Document Object Model (DOM), defined by the W3C consortium. Such objects provide the programmer with a structured interface to (X)HTML and XML documents. It is these objects that provide JavaScript with the ability to manipulate nested style sheets (CSS - Cascade Style Sheet) and simplify the implementation of dynamic HTML (DHTML). Access to document objects is provided by the browser through the document property of the Window object (window. document). We'll talk more about the DOM later.

Principles of working with objects

An object is an unordered collection of data, including primitive data types, functions, and even other objects. The benefit of objects is that they concentrate in one place all the data and logic necessary to perform a specific task. The String object stores text data and offers many of the functions needed to act on it. Although the presence of objects in a programming language is not at all necessary (there are no objects in the C language, for example), they certainly simplify the use of the language.

Creating Objects

An object is created using a constructor - a special type of function that prepares a new object for use by initializing the memory occupied by the Object. In Chapter 4, we saw that objects can be created by applying the new operator to their constructors. Using this operation causes the constructor to create a new object, the nature of which is determined by the constructor being called. For example, the String() constructor creates String objects, and the Array() constructor creates Array objects. This is how object types are named in JavaScript: by the name of the constructor that creates the object.
Here's a simple example of creating an object:

var city = new String();

This statement creates a new String object and places a reference to it in the city variable. Here, the constructor is not offered any arguments, so the city variable will get its default value - in in this case this is an empty string. You can make this example more interesting by passing an argument to the constructor that specifies the initial value:

var city = new String("San Diego");

In this article, I want to talk as fully and consistently as possible about what an object is in JavaScript, what its capabilities are, what relationships can be built between objects and what methods of “native” inheritance follow from this, how all this affects performance and what in general to do with all this :)

The article will NOT have a word about: emulation of the traditional class-object paradigm, syntactic sugar, wrappers and frameworks.

The complexity of the material will increase from the beginning to the end of the article, so for pros the first parts may seem boring and banal, but then it will be much more interesting :)

Objects in JavaScript

Many articles contain the phrase “In JavaScript, everything is an object.” Technically this is not entirely true, but it makes the right impression on beginners :)

Indeed, much in language is an object, and even what is not an object can have some of its capabilities.

It is important to understand that the word “object” is used here not in the sense of “an object of some class.” An object in JavaScript is first and foremost just a collection of properties (if you prefer, you can call it an associative array or list) consisting of key-value pairs. Moreover, the key can only be a string (even for array elements), but the value can be any type of data listed below.

So in JavaScript there are 6 basic types data are Undefined (indicating the absence of a value), Null, Boolean (Boolean), String (string), Number (number) and Object (object).
Moreover, the first 5 are primitive data types, but Object is not. In addition, we can conventionally consider that the Object type has “subtypes”: array (Array), function (Function), regular expression(RegExp) and others.
This is a somewhat simplified description, but in practice it is usually sufficient.

Additionally, the primitive types String, Number, and Boolean are related in certain ways to the non-primitive "subtypes" of Object: String, Number, and Boolean, respectively.
This means that the string "Hello, world", for example, can be created either as a primitive value or as a String object.
In short, this is done so that the programmer can use methods and properties when working with primitive values ​​as if they were objects. You can read more about this in the corresponding section of this article.

Work from the link

A link is a means of accessing an object under different names. Work with any objects is carried out exclusively by reference.
Let's demonstrate this with an example:
test= function () (alert("Hello!" )) //Create a function (alert("Hello!")) (and a function, as we remember, is a full-fledged object) and make the test variable a reference to it
test_link=test; //test_link now also refers to our function
test(); //Hello!
test_link(); //Hello!


As we can see, both the first link and the second give the same result.
We need to realize that we don't have any function named test, and that the test variable is not some kind of "main" or "primary" link, and "test_link" is a minor one.

Our function, like any other object, is simply an area in memory, and all references to this area are absolutely equivalent. Moreover, the object may not have any references at all - in this case it is called anonymous, and can only be used immediately immediately after creation (for example, passed to a function), otherwise it will be impossible to access it and will soon be destroyed by the garbage collector (garbage collection), which is responsible for deleting objects without references.

Let's see why it is so important to understand this:

test=(prop: "sometext" ) //Create an object with the prop property
test_link=test; //Create another link to this object

Alert(test.prop); //sometext

//Change the property of the object
test_link.prop="newtext" ;

Alert(test.prop); //newtext
alert(test_link.prop); //newtext
/*One could say that the property has changed both here and there - but this is not so.
There is only one object. So the property changed on it once, and the links just continue to point where they point. */

//Add a new property and remove the old one
test.new_prop="hello" ;
delete test.prop;

Alert(test_link.prop); //undefined - this property no longer exists
alert(test_link.new_prop);

//Delete the link
delete test;
alert(test.new_prop);
/*At this point the script will throw an error, because test no longer exists, and test.new_prop does not exist even more so */
alert(test_link.new_prop); //hello
/* but here everything is in order, because we did not delete the object itself, but only a link to it. Now our object is pointed to by a single link, test_link */

//Create a new object
test=test_link; //First, create the test link again
test_link=(prop: "sometext" ) //And here is the new object

Alert(test_link.prop); //sometext
alert(test.prop); //undefined
/* Creating a new object breaks the reference link, and now test and test_link point to different objects.
In fact, this is equivalent to deleting the test_link and creating it again, but pointing to a different object */
alert(test.new_prop); //hello - now test contains a link to our very first object


* This source code was highlighted with Source Code Highlighter.

This behavior of objects often raises a lot of questions for novice developers, so I hope this text will bring some clarity. If we want to create a truly new, independent copy of an object, and not a link, then the only way to do this is to create a new object and copy the required properties there.

It is also worth noting that working with objects by reference, in addition to the fun effects listed above, also provides significant memory savings, which is important when one object is widely used in different places in the program.

Primitive values

As I mentioned above, the String and Number data types can be either objects or primitive values.
obj= new String("hello" ); //Create a string as an object
simple="hello" ; //Create a primitive value

Alert(obj); //hello
alert(simple); //hello - so far everything is predictable

Alert(obj.length); //6 - an object of type String has a length property that stores the length of the string
alert(simple.length); //6
/* Although simple is not an object, we can access the same set of properties as an object of type String. It's quite convenient */

Obj.prop="text" ;
simple.prop="text" ;

Alert(obj.prop); //text - since obj is a regular object, we can easily give it another property
alert(simple.prop); //undefined - but simple is not an object, and this number will not work for us

* This source code was highlighted with Source Code Highlighter.


The same is true for both the Number and Boolean types (well, except that they don’t have a length property, but they have a number of other great properties).
Using strings and numbers as objects does not have any practical benefit, because primitive values ​​are more convenient to use, but at the same time retain all the necessary functionality. However, to complete the picture it is necessary to understand this mechanism.

Don't confuse the use of primitive values ​​with the use of literals - for example, whether we create an array as "test=new Array()" or as "test=", the result will still be the same object. We will not receive any primitive values.

Creating and Using Objects

So, unlike languages ​​that implement the class-object paradigm, we do not need to create a class first and then create an object of the class. We can immediately create an object, which is what we will do in the following example:
test=(
simple_property: "Hello" ,
object_property: (
user_1: "Petya" ,
user_2: "Vasya"
},
function_property: function (user) (
alert(this .simple_property + ", " + this .object_property);
}
}

Test.function_property("user_1" ); //Hello, Petya.

* This source code was highlighted with Source Code Highlighter.


We have a test object that has 3 properties, the names of which, I hope, speak for themselves. What interests us most about it is the function_property, which contains the function. Such a function can be called an object method.

Our function uses the this keyword twice, which is a pointer (i.e., a reference) to the object from which the function is called. Thus, this.simple_property=test.simple_property="Hello", and this.object_property=test.object_property="Peter".

It is important to be clear that this always points to the object from which the function is called, and not to the object to which it belongs. Although in in this example this is the same object, this is not always the case.

test.function_property("user_1" ); //Hello, Petya.

Test2=new Object(); //Another form of creating a new object, similar to test2=()

Test.function_property.call(test2, "user_1" ); //error
/* The call method allows you to call a function on behalf of another object. In this case, we call the function_property method of the test object, and its this no longer points to the test object, but to the test2 object. And because it does not have the object_property property, then when you try to get this.object_property the script will throw an error */

//let's try to fix the situation
test2.simple_property="Good day" ;
test2.object_property=test.object_property; //In this case, we will use specifying the object by reference so as not to duplicate the code

Test.function_property.call(test2, "user_1" ); //Good day, Petya.


* This source code was highlighted with Source Code Highlighter.

It should also be clear from the example that there are no clear steps for creating and using an object. An object can be modified in any way at any time - before, after and even during use. It is too important difference from "traditional" OOP.

Constructor

In the example above, we created 2 objects that had some similarity. Both had simple_property and object_property properties. Obviously, when writing real code, the task of creating identical or simply similar objects often arises. And of course, we do not have to create each such object manually.

A designer will come to our aid. A constructor in JavaScript is not part of a class (because there are no classes), but simply a function in its own right. The most common function.

make_me= function (_name) (
alert("I was launched" );
this .name=_name;

}


/* Let's figure out what's going on here. The interpreter sees the new operator and checks what is to the right of it. Because make_me is a function, and it can be used as a constructor, then a new object is created in memory and the make_me function is launched for execution, and its this points precisely to this new object. Next, this object is added with a name property, which is assigned the value from the _name argument, and a show_name method. Also (I don’t know at what point, but it doesn’t matter) the child variable starts pointing to our brand new, just born object */

Alert(child.name); //Vasya
child.show_name(); //Vasya


child2.show_name(); //Peter

Child2.show_name=function () (alert( "I won't say my name");} //Don't forget that we can change our objects at any time
child2.show_name(); //I won't say my name

Child.show_name(); //Vasya - children do not influence each other in any way


* This source code was highlighted with Source Code Highlighter.

You can also compare a designer with a father - he gives birth to a child, endowing him with certain qualities, but immediately after creation the child becomes completely independent of the parent and can become very different from his brothers.
If we remember the description of data types at the beginning of the article, it becomes clear that Object and its subtypes (Function, Array and others) are actually constructors that give the created object the capabilities of a function, array, etc.

So this is already much better. We now have the ability to create objects according to some pattern. However, all is not well yet. First, each object we create and all its properties and methods occupy a separate place in memory, although in many ways they are repeated. Secondly, what if we want to maintain the connection between parent and child, and be able to change all child objects at once. A prototype will come to our aid.

Prototype

Just as every child has a father and mother (at least in a biological sense), so does every object in JavaScript. And if the father, as we have determined, works as a designer, then the mother is precisely the prototype. Let's see how this happens:
make_me= function (_name) (
alert("I was launched" );
this .name=_name;
this .show_name=function () (alert(this .name);)
}
/*
Seeing the function keyword, the interpreter checks the code to the right of it, and so on. everything is ok - it creates a new object in memory, which is also our function. Then, automatically (without programmer intervention) a prototype property is created for this function, which refers to an empty object. If we did this manually, it would look like make_me.prototype=new Object();

Then, this object (pointed to by the prototype property) is also automatically given a constructor property, pointing back to the function. It turns out this is a cyclic link.

Now this object, which can be described as (constructor: ...here is a reference to a function...) is the prototype of the function.
*/

//Object - indeed, an object
alert(typeof make_me.prototype.constructor); //Function is our function
alert(make_me.prototype.constructor === make_me); //true

//Add a new method to the make_me function prototype

Child=new make_me("Vasya"); //I was launched
/* Now, in addition to everything described in the previous example, an additional hidden property [] is created in the child object, which points to the same object as make_me.prototype. Because The property is hidden, we can neither view its value nor change it - however, it plays an important role in further work */

Alert(child.name); //Vasya
child.show_name(); //Vasya

Child.set_name("Kolya" );
/* First, the interpreter looks for the set_name method in the child object. Since it's not there, it continues searching in the child.[ property, finds it there, and runs it. */
child.show_name(); //Kolya - now Vasya’s name is Kolya :)

Make_me.prototype.show_name2=function () (alert("Hello, " + this .name;) //Because a prototype is an ordinary object, we can just as well change it on the fly

Child2=new make_me("Petya" );
child2.show_name2(); //Hello, Petya
child.show_name2(); //Hi, Kolya - changes in the prototype affect not only newly created objects, but also all old ones

Child2.show_name2=function () (alert( "I won't say my name");} //We can still change the object itself, and the new show_name2 method in this object (and only in it) will, as it were, “overwrite” the old method from the prototype
child2.show_name2(); //I won’t say my name - because... we now have our own method show_name2, then it is called, and the search in the prototype does not occur

Child.show_name2(); //Hello, Kolya - everything is still the same here

Make_me.prototype=(prop: "hello" ) //Let's try to recreate the prototype again

Alert(child.prop); //undefined
child.show_name2(); //Hi Kolya
/* If you remember what working by reference is, then everything is clear. Recreating the prototype breaks the connection, and now the [] property of the child and child2 objects point to one object (which was previously the prototype of the make_me function), and the make_me.prototype property points to another object, which is the new prototype of the make_me function */

Child3=new make_me("Oleg" );
alert(child3.prop); //hello - as expected


* This source code was highlighted with Source Code Highlighter.

As can be seen from the example, as long as the father remains faithful to the mother (that is, as long as the type of function remains the same), all children depend on the mother and are sensitive to all changes in her. However, as soon as the parents divorce (the designer changes the prototype to another), the children immediately run away in all directions and there is no more contact with them.

A little about terminology
As long as the primary connection between the designer and the prototype is not broken, we can observe the following picture:

make_me= function (_name) (
alert("I was launched" );
this .name=_name;
this .show_name=function () (alert(this .name);)
}

Make_me.prototype.set_name=function (_name) (this .name=_name;)
child=new make_me("Vasya" );

Alert(typeof make_me.prototype); //object - the function has a prototype property
alert(typeof child.prototype); //undefined - at soz of this object NO prototype property
alert(child.constructor.prototype === make_me.prototype); //true - but the object has a constructor property, which points to the constructor function make_me, which, in turn, has a prototype property


* This source code was highlighted with Source Code Highlighter.

As I've noticed after reading numerous forums on this topic, the main problem people have is when they confuse the prototype property of a function with the hidden [] property of the object created by that function.
Both of these properties are a reference to the same object (as long as the primary connection between the prototype and the constructor is not broken), but they are nevertheless different properties, with different names, one of which is accessible to the programmer, and the other is not.

It is always necessary to clearly understand that if we're talking about about the prototype of the constructor, then this is always the prototype property, and if about the prototype of the created object, then this is the hidden property [].

Inheritance

Now we know that every object has a hidden prototype reference, and every prototype is a regular object.
The most sensitive readers have already caught the smell of recursion :)
Indeed, because a prototype is an ordinary object, then it, in turn, has a link to its prototype, and so on. This is how the prototype hierarchy is implemented.
bird= function()() //This is the bird's constructor
bird.prototype.cry=function ()(alert("Cry!");) //The bird can scream
bird.prototype.fly=function ()(alert("I'm flying!");) //and fly

Duck=function () ()
duck.prototype=new bird();
duck.prototype.cry=function ()(alert("Quack-quack!" ;) //Duck screams differently
duck.prototype.constructor=duck; //Forcibly set the prototype.constructor property to duck, because otherwise it will refer to bird

Billy = new duck(); //Billy is our duck
billy.fly(); //I'm flying! - Billy can fly because he's a bird.
billy.cry(); //Quack quack! - Billy screams quack-quack because he's a duck.


* This source code was highlighted with Source Code Highlighter.

This way you can implement a hierarchy of any nesting level.

Star task

Now, since we know so much about all this, let's try to figure out how much is happening in these three lines
make_me= function()()
child=new make_me();
alert(child.toString()); //outputs

* This source code was highlighted with Source Code Highlighter.

On the first line we create new feature and a make_me variable that points to this function. This creates a function prototype, make_me.prototype, which contains a constructor property pointing to make_me.
But that's not all:)
Because the make_me function is also an object, then it, in turn, has a father and a mother, i.e. designer and prototype. Its constructor is a native function of the Function() language, and its prototype is an object containing the methods call, apply, etc. - It is thanks to this prototype that we can use these methods in any function. Thus, the make_me function has a [] property pointing to Function.prototype.

In turn, the prototype of a Function constructor is also an object, the constructor of which is (surprise!) Object (i.e. Function.prototype.[].constructor===Object), and the prototype is an object containing the standard properties and methods of the object, such as toString, hasOwnProperty and others (in other words - Function.prototype.[]["hasOwnProperty"] - this is exactly the method that we can use in all derived objects - and this is the own method of this object, and not an inherited one ). In this interesting way we discover that all kinds of objects are derived from Object.

Can we continue further? It turns out not. Object.prototype contains the basic properties of the object precisely because it does not have its own prototype. Object.prototype.[]=null; At this point, the journey through the prototype chain in search of a property or method stops.

Another interesting fact- the constructor of Object is Function. Those. Object.[].constructor===Function.
There is another circular reference - the constructor of Object is Function, and the constructor of Function.prototype is Object.

Let's return to our example. We have already understood how the function is created, now let’s move on to the second line. There we create a child object whose constructor is the make_me function and whose prototype is make_me.prototype.

Well, in the third line we see how the interpreter goes up the chain, from child to child.[] (aka make_me.prototype), then to child.[].[] (aka Object.prototype), and already finds there the toString method, which launches execution.

Impurities

It may seem that inheritance through prototypes is the only way possible in JavaScript. This is wrong.
We are dealing with a very flexible language that provides possibilities rather than rules.

For example, if we wish, we can not use prototypes at all, but program using the concept of mixins. For this we will need our good old friends - designers.

//This is a human constructor
man=function() (
this .live=function ()(alert("I'm live" ;) //Man knows how to live
this .walk=function ()(alert("I'm walking" ;) //The man can walk
}

//This is the poet's constructor
poet=function ()(
this .kill=function ()(alert( "The poet killed a man");} //A poet can kill a person
this .live=function ()(alert("I'm dead" ;) //A person will die from this
}

Vladimir=new man(); //Vladimir is a man
vladimir.live(); //I live - he is alive
vladimir.walk(); //I'm walking - he's walking

Poet.call(vladimir); //Execute the poet constructor for the vladimir object
vladimir.kill(); //The poet killed a man
vladimir.live(); //I'm dead

//Now focus
man.call(vladimir);
vladimir.live(); //I live


* This source code was highlighted with Source Code Highlighter.

What do we see in this example? Firstly, it is possible to inherit from several objects that are not in the same hierarchy. In the example there are 2 of them, but there can be as many as you like.
Secondly, there is no hierarchy at all. Overriding of properties and methods is determined solely by the order in which constructors are called.
Thirdly, this is the ability to change the object even more dynamically, and precisely separate object, and not all children, as when changing the prototype.

Upd: Closures and private properties

In order not to bloat this already rather large article, I provide a link to the post Closures in JavaScript, where this is written in some detail.

What to do now with all this

As I said above, arbitrary modification of individual objects, the use of constructors, mixins, and the flexibility of prototypes are just tools, opportunities that allow the programmer to create both terrible and wonderful code in all respects. It is only important to understand what problems we solve, by what means, what goals we achieve and what price we pay for it.

Moreover, the question of price is quite non-trivial, especially if we are talking about development for the browser Internet Explorer 6 and 7 versions.
1. Memory - everything is simple here. In all browsers, inheritance on prototypes takes up much less memory than when creating methods through constructors. Moreover, the more methods and properties we have, the greater the difference. However, it is worth remembering that if we do not have a thousand identical objects, but only one, then the memory consumption in any case will be small, because There are other factors to consider here.
2. Processor time - here the main subtleties are related specifically to browsers from Microsoft.
On the one hand, objects where methods and properties are created through a constructor can be created many times (in some cases tens and hundreds of times) slower than through a prototype. The more methods, the slower it is. So if your IE freezes for a few seconds during script initialization, there is a reason to dig in this direction.

On the other hand, an object's own methods (those created through the constructor) can execute slightly faster than prototype methods. If you desperately need to speed up the execution of a particular method in this browser, then you need to take this into account. Keep in mind that it is the method call (i.e., searching for it in the object) that is speeded up, not its execution. So if the method itself runs for a second, then you won’t notice much of an increase in performance.

Similar problems are observed in other browsers, where the time for creating objects and calling their methods is approximately the same for both approaches.

P.S. Usually in articles of this kind the author offers some kind of wrapper, either trying to implement class-object inheritance based on prototypic inheritance, or simply syntactic sugar for prototypic inheritance. I don't do this intentionally, because... I believe that a person who understands the meaning of this article is able to write any wrapper for himself, and many more interesting things :)

Tags: Add tags




Objects are one of the core concepts in JavaScript. When I first started studying them, they seemed quite simple to me: just pairs of keys and values, as described in theory.

Only after some time did I begin to understand that the topic was much more complex than I thought. And then I began to study information from different sources. Some of them gave a good idea of ​​the subject, but I was not able to see the whole picture right away.

In this post, I tried to cover all aspects of working with objects in JS, without going too deep into specific details, but also without leaving out important details that will help you understand the subject and feel more confident as you study it further.

So let's start with the basics.

An object

An object in JavaScript is simply a collection of properties, each of which is a key-value pair. You can access the keys using a dot ( obj.a) or bracket notation ( obj["a"]).

Remember that parentheses should be used if the key is:

  • is not a valid JavaScript identifier (it has a space, a dash, starts with a number...)
  • is a variable.
One of the properties that objects in JS receive when created is called Prototype, and this is a very important concept.

Prototype

Every object in JavaScript has an internal property called Prototype. In most browsers you can refer to it by the notation __proto__.

Prototype is a way to enforce property inheritance in JavaScript. This way you can share functionality without duplicating code in memory. The method works by creating a connection between two objects.

Simply put, Prototype creates a pointer from one object to another.

Prototype chain

Every time JS looks for a property in an object and does not find it directly on the object itself, it checks for the presence of the property in the prototype object. If there is no property in it, then JS will continue to look in the prototype of the associated object. This will continue until JS finds a suitable property or reaches the end of the chain.

Let's look at an example:

Var cons = function () ( this.a = 1; this.b = 2; ) var obj = new cons(); cons.prototype.b = 3; cons.prototype.c = 4;
cons is a constructor (simply a function that can be called using the operator new).

On the fifth line we create a new object - a new copy cons. Immediately after creation obj also gets the prototype property.

And now we add properties ( "b", "c") object prototype cons.
Let's consider obj:

obj.a // 1- everything is the same here, obj.a is still 1.
obj.c?- y obj no property c! However, as previously mentioned, JS will now look for it in the prototype obj and will return the value 4.

Now let's think about what the meaning is obj.b and what it will be like when we remove obj.b?

Obj.b is equal to 2. We assigned the property b, but we did it for a prototype cons, so when we check obj.b, then we still get 2. However, immediately after removing obj.b JS will no longer be able to find b y o bj, and therefore will continue searching in the prototype and return the value 3.

Creating an Object

Object literal: let obj = (a: 1);
We created an object with the following prototype chain: obj ---> Object.prototype ---> null
As you can guess, object.prototype is the prototype of the object, and also the end of the prototype chain.

Object.create():var newObj = Object.create(obj);
U newObj there will be the following chain of prototypes: newObj ---> obj ---> Object.prototype ---> null

Constructor. As in the example above, the constructor is simply a JS function that allows us to take advantage of the operator new to create new instances of it.

ES6 classes:

Class rectangle ( constructor(height, width) ( this.height = height; this.width = width; ) getArea() ( return this.height * this.width; ) ) let square = new rectangle(2, 2);
Square- constructor instance rectangle, and so we can call square.getArea() //4, square.width, as well as all functions inherited from object.prototype.

Which way is better? If you plan to create multiple instances, you can use ES6 or the designer. If you plan to create the object once, then it is better to specify a literal, since this is the simplest way.

And now that we have learned about prototype and having become familiar with all the ways to create new objects, we can move on to discuss one of the most confusing aspects associated with objects.

Compare and change objects

In JavaScript, objects are of reference type

When we create an object let obj = (a: 1);, variable obj gets the object's memory address, but not its value! It is extremely important to understand this difference, otherwise errors may occur. When we create another object let newObj = obj, we are actually creating pointer to a certain memory area obj, and not a completely new object.

This means that by doing newObj.a = 2, we actually change obj so that obj.a becomes equal to 2!

This approach easily leads to bugs, which is why many companies work with immutable objects. Instead of changing an already created object, you will have to again create a new object (a copy of the original) and make changes to it. This is how important libraries like Redux work, and it is one of the core concepts of functional programming in general. You can read more.

Equality

It also follows from the above that two objects can never be equal, even if they have the same properties. This is due to the fact that JS actually compares the memory location of objects, and two objects are never in the same memory location.

// Two distinct objects with the same properties are not equal var fruit = (name: "apple"); var fruitbear = (name: "apple"); fruit === fruitbear; // return false // here fruit and fruitbear are pointing to the same object var fruit = (name: "apple"); var fruitbear = fruit; fruit === fruitbear; // return true
So, you most likely have already wondered how you can compare objects or how to perform various manipulations with objects, given the requirement for their immutability.

Let's consider several possibilities.

Changing an object

Let's say it's clear that we shouldn't actually change objects, so we want to create a copy of the corresponding object and change its properties. Comes to the rescue Object.assign().

Var obj = (a: 1, b: 2); var newObj = Object.assign((), obj,(a:2)) // (a: 2, b: 2 )
If we want to change the property value a object obj, you can use object.assign to create a copy obj and its changes.

In the example you can see that we first create an empty object, then copy the values obj and make our changes, ultimately obtaining a new and ready-to-use object.

Please note that this method will not work for deep copying. When we talk about deep copying, we mean that we need to copy an object with one or more properties.

Const obj = (a: 1, b: ( a: 1 ) ); // b property is an object
Object.assign() copies the properties of an object, so if the value of the property is a pointer to an object, then only the pointer is copied.

A deep copy requires a recursive operation. Here you can write a function or just use a method _.cloneDeep from the Lodash library.

Comparison of objects

There is one cool technique for working with objects - string conversion. In the following example, we convert both objects to strings and compare them:

JSON.stringify(obj1) === JSON.stringify(obj2)
This approach makes sense because we end up comparing strings that are a pointer to a value type. The bad news is that it doesn't always work, mainly because the order of the object's properties is not guaranteed.

Other good decision- use the method _.isEqual from Lodash, which performs deep object comparison.

And before we wrap up, let's go over some frequently asked questions about objects. This will help you dive deeper into the topic and apply the acquired knowledge in practice.

Try to think about the solution yourself before reading the answer.

How to find out the length of an object?

To get the answer, you need to go through all the properties of the object one by one and count them. There are several ways to perform such an iteration:
  • for in. This method covers all countable properties of an object and its prototype chains. We've seen the prototype (and hopefully learned the material), so it should be clear that the application for in won't always be true for getting properties of an object.
  • Object.keys. This method returns an array with the keys of all own(belonging to the specified object) counting properties. This approach is better because we only work on the properties of the object, without accessing the properties prototype. There are, however, situations where you have assigned an attribute enumerable some property is false, and object.keys ends up skipping it, and you get an incorrect result. This rarely happens, but in such cases it will come in handy getOwnPropertyNames.
  • getOwnPropertyNames returns an array containing everything own object keys (both countable and uncountable).
Also worth mentioning:
  • Object.values iterates over its own counting properties and returns an array with the corresponding values.
  • Object.entries iterates over its own counting properties and returns an array with keys and their values.
I think you noticed that most of the methods listed above return an array. This is an opportunity to take advantage of all the benefits JavaScript methods for working with arrays.

One such method is array.length. As a result, we can simply write

Let objLength = Object.getOwnPropertyNames(obj).length;

How to check if an object is empty?

  1. JSON.stringify(myObj) === “()”?. Here we again use the string conversion tool to easily check whether an object is empty (by comparing strings, not objects).
  2. !Object.keys(myobj).length // true?.? As I mentioned, converting object keys to an array can be very useful. Here we use the convenient property length, inherited from Array.prototype, using it to check the length of the keys in the array. In JS 0 turns to false, so adding ! we turn it to true. Any other numbers will be converted to false.

Finally

I hope you now feel more confident in creating and working with objects. Let's summarize:
  • Remember that objects are of a reference type, which means that it is recommended to work with them without changing the original objects.
  • Make friends with the property prototype and a chain of prototypes.
  • Get to know the tools that help you work with objects. Remember that you can turn objects into strings, get an array of their keys, or simply iterate over their properties using the set of methods we've been introduced to.
Good luck learning JavaScript objects.

Last update: 04/08/2018

Object-oriented programming is one of the dominant paradigms in application development today, and in JavaScript we can also take full advantage of OOP. At the same time, in relation to JavaScript, object-oriented programming has some features.

Objects

In previous topics, we worked with primitive data - numbers, strings, but data does not always represent primitive types. For example, if in our program we need to describe the essence of a person who has a name, age, gender, and so on, then naturally we will not be able to represent the essence of a person as a number or string. We will need a few lines or numbers to properly describe the person. In this regard, a person will act as a complex complex structure, which will have individual properties - age, height, first name, last name, etc.

To work with such structures, JavaScript uses . Each object can store properties that describe its state and methods that describe its behavior

Creating a new object

There are several ways to create a new object.

The first way is to use the Object constructor:

Var user = new Object();

In this case, the object is called user. It is defined in the same way as any regular variable using the var keyword.

The new Object() expression represents a call to a constructor, a function that creates a new object. The new operator is used to call the constructor. Calling a constructor is essentially like calling a regular function.

The second way to create an object is by using curly braces:

Var user = ();

Today, the second method is more common.

Object properties

After creating an object, we can define properties on it. To define a property, you need to specify the name of the property after the name of the object, separated by a dot, and assign a value to it:

Var user = (); user.name = "Tom"; user.age = 26;

In this case, two properties name and age are declared and assigned corresponding values. After that, we can use these properties, for example, display their values ​​in the console:

Console.log(user.name); console.log(user.age);

You can also define properties when defining an object:

Var user = ( name: "Tom", age: 26 );

In this case, a colon character is used to assign a value to the property, and a comma (rather than a semicolon) is placed after the property definition.

In addition, there is a shortcut way to define properties:

Var name = "Tom"; var age = 34; var user = (name, age); console.log(user.name); // Tom console.log(user.age); // 34

In this case, the names of the variables are also the names of the properties of the object. And this way you can create more complex designs:

Var name = "Tom"; var age = 34; var user = (name, age); var teacher = (user, course: "JavaScript"); console.log(teacher.user); // (name: "Tom", age: 34) console.log(teacher.course); // JavaScript

Object Methods

An object's methods define its behavior, or the actions it performs. Methods are functions. For example, let's define a method that would display a person's name and age:

Var user = (); user.name = "Tom"; user.age = 26; user.display = function())( console.log(user.name); console.log(user.age); ); // method call user.display();

As with functions, methods are first defined and then called.

Methods can also be defined directly when defining an object:

Var user = ( name: "Tom", age: 26, display: function())( console.log(this.name); console.log(this.age); ) );

As with properties, a method is assigned a function reference using a colon.

To access properties or methods of an object within that object, use the this keyword. It means a reference to the current object.

You can also use a shorthand way to define methods by omitting the colon and function:

Var user = ( name: "Tom", age: 26, display())( console.log(this.name, this.age); ), move(place)( console.log(this.name, "goes to" , place); ) ); user.display(); // Tom 26 user.move("the shop"); //Tom goes to the shop

Array syntax

There is also alternative way defining properties and methods using array syntax:

Var user = (); user["name"] = "Tom"; user["age"] = 26; user["display"] = function())( console.log(user.name); console.log(user.age); ); // calling the method user["display"]();

The name of each property or method is enclosed in quotation marks and square brackets, then it is also assigned a value. For example, user["age"] = 26 .

When accessing these properties and methods, you can either use dot notation (user.name) or use: user["name"]

Strings as Properties and Methods

It should also be noted that the names of object properties and methods are always strings. That is, we could rewrite the previous definition of the object like this:

Var user = ( "name": "Tom", "age": 26, "display": function())( console.log(user.name); console.log(user.age); ) ); // method call user.display();

On the one hand, there is no difference between the two definitions. On the other hand, there are cases where enclosing the title in a line can help. For example, if the property name consists of two words separated by a space:

Var user = ( name: "Tom", age: 26, "full name": "Tom Johns", "display info": function())( console.log(user.name); console.log(user.age) ; ) ); console.log(user["full name"]); user["display info"]();

Only in this case, to access such properties and methods, we must use array syntax.

Removing properties

Above we looked at how we can dynamically add new properties to an object. However, we can also delete properties and methods using the delete operator. And just like with adding, we can remove properties in two ways. The first way is to use dot notation:

Delete object.property

Or use array syntax:

Delete object["property"]

For example, let's remove the property:

Var user = (); user.name = "Tom"; user.age = 26; user.display = function())( console.log(user.name); console.log(user.age); ); console.log(user.name); // Tom delete user.name; // remove the property // Alternative option// delete user["name"]; console.log(user.name); // undefined

After deletion, the property will be undefined, so when you try to access it, the program will return the value undefined.







2024 gtavrl.ru.