📜 ⬆️ ⬇️

The book "How is JavaScript"

image Most programming languages ​​have grown out of the ancient paradigm originated during the time of Fortran. JavaScript guru Douglas Crockford uproots these dried roots, allowing us to reflect on the future of programming, moving to a new level of understanding of the requirements for The Next Language.

The author begins with the basics: names, numbers, logical values, symbols and other basic information. You will learn not only about the problems and difficulties of working with types in JavaScript, but also about how to get around them. Then you begin to get acquainted with the data structures and functions to understand the underlying mechanisms, and learn how to use higher-order functions and object-oriented programming style without classes.

Excerpt
How code without classes works


And you think that you are intelligent outside of all classes and free.
John Lennon

One of the key ideas in the development of object-oriented programming was the model of data exchange between parts of the program. The name of the method and its arguments must be presented as messages. The method call sends a message to the object. Each object is characterized by its own behavior, which manifests itself when receiving specific messages. The sender believes that the recipient knows what to do with the message.
')
One of the added benefits is polymorphism. Every object that recognizes a particular message has the right to receive it. What happens next depends on the specialization of the object. And this is a very productive thought.

Unfortunately, we began to be distracted by inheritance - a very effective code reuse scheme. Its importance is associated with the ability to reduce labor costs in the development of the program. Inheritance is built on a similar design, with the exception of some nuances. It can be said that some object or object class is similar to some other object or object class, but it has some important differences. In a simple situation, everything works fine. It should be recalled that modern OOP began with Smalltalk, a programming language for children. As the situation becomes more complex, inheritance becomes problematic. It generates a strong grip classes. Changing a single class can cause a crash in those classes that depend on it. Modules from the classes are simply useless.

In addition, we observe increased attention to properties, and not to objects. Particular attention is paid to the methods of obtaining (get-methods) and assigning (set-methods) values ​​to each individual property, and in even less successful projects, the properties are open and can be changed without the knowledge of the object. It is quite possible to put into use a more successful project, where properties are hidden, and methods process transactions, without being concerned only with changing properties. But this approach is used infrequently.

In addition, there is too much dependence on the types. Types became a feature of FORTRAN and later languages, as they were convenient to the creators of the compiler. Since then, the mythology around types has grown, having acquired extravagant claims that types protect the program from errors. Despite their dedication to type, mistakes have not gone from everyday practice.

Types cause respect, they are praised for early detection of errors at the compilation stage. The sooner an oversight is detected, the less cost it will require its liquidation. But with proper testing of the program, all these failures are detected very quickly. Therefore, type identification errors are classified as low-cost.

Types are not to blame for hard-to-find and costly errors. They are not guilty in the occurrence of problems caused by such errors and requiring some tricks. Types can push us to use obscure, confusing, and dubious programming techniques.

Types are similar to a diet for weight loss. Diet is not accused of returning and weight gain. She is also not considered to be the cause of suffering or health problems caused by her. Diets give hope that the weight will come to a healthy standard and we will continue to eat junk food.

Classical inheritance allows us to think that we are creating high-quality programs, while we make more and more errors and use more and more inefficient inheritances. If you ignore the negative manifestations, the types seem to be a major victory. The advantages are obvious. But if you look at the types more closely, you will notice that costs outweigh the benefits.

Constructor


In Chapter 13, we worked with factories — functions that return functions. Something similar can now be done with constructors - functions that return objects that contain functions.

Let's start by creating a counter_constructor, similar to the counter generator. He has two methods, up and down:

function counter_constructor() { let counter = 0; function up() { counter += 1; return counter; } function down() { counter -= 1; return counter; } return Object.freeze({ up, down }); } 

The returned object is frozen. It cannot be damaged or damaged. The object has a state. The variable counter is a private property of the object. It can only be accessed through methods. And we don't need to use this.

This is a very important circumstance. The object interface is methods only. He has a very strong shell. We get the best encapsulation. There is no direct access to the data. This is a very high quality modular design.

A constructor is a function that returns an object. Parameters and constructor variables become closed object properties. It does not have public properties consisting of data. Internal functions become object methods. They turn properties into closed ones. Methods falling into a frozen object are public.

Methods must implement transactions. Suppose, for example, that we have a person object. You may need to change the address of the person whose data is stored in it. You do not need a separate set of functions to change each individual address element. We need one method that receives an object literal that can describe all parts of the address that need to be changed.

One of the brilliant ideas in JavaScript is the object literal. This is a nice and expressive syntax for clustering information. By creating methods that consume and create data objects, you can reduce the number of methods, thereby increasing the integrity of the object.

So, we have two types of objects.


It is believed that the PLO began with the addition of procedures to the records of the Kobol language, thereby providing some kind of behavior. I believe that the combination of methods and data properties was an important step forward, but should not be the last step.

If a hard object needs to be converted to a string, you need to enable the toJSON method. Otherwise, JSON.stringify will see it as an empty object, ignoring methods and hidden data (see Chapter 22).

Constructor Parameters


Once I created a constructor that takes ten arguments. They were very difficult to use, because no one could remember the order of the arguments. Later it was noticed that no one uses the second argument, I wanted to remove it from the list of parameters, but it would break all the already developed code.

If I were more prudent, I would have a constructor that takes one object as a parameter. It is usually taken from the object literal, but can also come from other sources, for example, from JSON content.

This would have many benefits.


Most often, the parameter is used to initialize a private property. This is done as follows:

 function my_little_constructor(spec) { let { name, mana_cost, colors, type, supertypes, types, subtypes, text, flavor, power, toughness, loyalty, timeshifted, hand, life } = spec; 

This code creates and initializes 15 private variables using properties with the same names from spec. If there is no corresponding property in the spec, a new variable is initialized, which is assigned the value undefined. This allows you to fill all missing with default values.

Composition


The vivid expressiveness and effectiveness of JavaScript allows you to create programs in the classical paradigm, although this language does not belong to classical ones. JavaScript also allows you to make improvements. We can work with a functional composition. So, instead of adding something as an exception, you can get a little bit of this and that. The constructor has the following general form:

 function my_little_constructor(spec) { let {} = spec; const _ = other_constructor(spec); const  = function () { //   spec, , _,  }; return Object.freeze({ , _. }); } 

Your constructor can call as many other constructors as you need to gain access to state management and the behavior they provide. You can even pass it the exact same spec object. When documenting the spec parameters, we list the properties my_little_constructor needs, and the properties needed by other constructors.

Sometimes you can simply add the resulting methods to a frozen object. In other cases, we have new methods that cause the obtained methods. Thereby, code reuse is achieved, similar to inheritance, but without strong coupling. The function call is the original code reuse scheme, and nothing better has yet been invented.

The size


With this approach, the construction of an object involves more memory than when using prototypes, since each rigid object contains all the methods of the object, and the prototype object contains a reference to the prototype containing methods. Is the difference in memory consumption significant? Comparing the difference with the latest achievements in increasing the amount of memory, one can say: no. We are accustomed to counting memory in kilobytes. And now we consider it in gigabytes. Against this background, the difference is not felt at all.

The difference can be reduced by improving modularity. Focusing on transactions, not on properties, allows us to reduce the number of methods, and at the same time to improve connectivity.

The classic model is characterized by monotony. Each object must be an instance of a class. JavaScript removes these limitations. Not all objects need to comply with such rigid rules.

For example, I believe that there is no point in the fact that points are necessarily hard objects with methods. A dot can be a simple container for two or three numbers. Points are passed to functions that are able to perform projection, or interpolation, or something else that can be done with points. This can be much more productive than creating subclasses of points that give them special behavior. Let the functions work.

»More information about the book can be found on the publisher site.
» Table of Contents
» Excerpt

For Habrozhiteley 25% coupon discount - javascript

Upon payment of the paper version of the book, an e-book is sent to the e-mail.

Source: https://habr.com/ru/post/455698/


All Articles