Tipos de datos en Javascript, lo que no te enseñaron

Data types in Javascript, what they didn't teach you

Introduction

Data types in Javascript are a little different compared to other programming languages like C or JAVA.

JavaScript is a weakly typed language, this means that it is not necessary to define the data type. But it is not that it does not have types, since the data type is defined at run time by Javascript.

This behavior and specification of data types applies to any place where javascript is executed, whether in the browser, in node.js, mongodb, or any tool that uses Javascript.

Now if we analyze the concept of types a little, when you make a sum between numbers in the real world you don't care what type it is, you only care that they can be added, regardless of whether it is an integer or decimal. These subtypes of numbers are still part of the set of real numbers, and are used in real life.

Javascript allows us to apply this thinking and with that we save many type comparisons. There will be times when we have no choice but to convert or compare them, but the less we do it, the simpler our code will be, and therefore easier to understand and faster to execute.

It is said that Javascript has a dynamic data type system, this is because the variables that are created can receive any other type of data at any time, and change type depending on the value they store. What we are really interested in is the value and what we can do with that value, not so much the type.

Later we will see some conversions and comparisons that can confuse and complicate the code, the recommendation is to reduce their use as much as possible. Although we will not see each type in great detail, we will see more important things necessary to use data types in Javascript.

It is useful to know how to define variables and constants, if you do not know how to create a variable or a constant, you can review this information before continuing.

Primitive data types

  • It is one that is not an object
  • It has no methods.
  • They are immutable
  • We have seven guys primitive data in Javascript.
  1. number, numbers like; 1, 0, 18500, 89.95124
  2. BigInt, added in 2020, to represent very, very large integers, 99999999999999n
  3. String, character string like 'Hello' and "Good night".
  4. Boolean, only accept true either false, that is, yes or no.
  5. null, serves to indicate that something is nothing, its only value is null.
  6. undefined, serves to indicate that something is not yet defined.
  7. symbol, added in 2015, with EcmaScript 6

Data Types Objects

All other data types in Javascript are objects. In the section Objects there is the explanation.

number

If I had written this before 2020, I would tell you that there is only one numeric data type, unfortunately (with some exceptions) a new numeric value called BigInt. In this section we will pretend that it does not exist.

number is a value 64 bit float, that is, it is a number double In other programming languages, this is basically the only numeric data type in JavaScript, there are no integers (except for BigInt), decimals, floats or doubles. Its specification is provided by IEEE-754.

The way to define and use them is very simple, you simply write the number, it does not matter if it is integer or decimal, floating point or double, as we mentioned before, all of these will be of type double for javascript. This is the recommended way to define them.

const edad = 33;
const PI = 3.1416;
const descuento = 0.30;
const pesoEnDolares = 0.05; // que tristeza xD!!
edad + descuento; // 33.30, no nos interesa el tipo, solo la suma

As we see in the last line, we can add integers and decimals without any problem, we are not interested in the type, we are interested in the ability to add them.

Float values are known to have a certain precision error when performing arithmetic operations, the most obvious operation being division.

0.2 + 0.1; // es igual a 0.30000000000000004

As we see, it does not give us an exact value of 0.3, to mitigate this you can multiply the values by 100 and then divide the result by 100.

(0.2 * 100 + 0.1 * 100)/100; // es igual a 0.3

NaN

There is a special number called NaN. This value is the error of an operation with numbers.

25 * undefined; // es igual a NaN
25 * {}; // es igual a NaN

Any operation you have NaN as one of its operands, will result in NaN.

25 * NaN; // es igua a NaN
25 + NaN; // es igual a NaN

NaN it is not even equal to NaN

NaN === NaN; // es igual a false
NaN == NaN; // es igual a false

To mitigate this strange behavior, it is recommended to use the method Number.isNaN(), there is also a global function called isNaN(), but due to the implicit functionality of Javascript in wanting to convert between types automatically, it can give us very strange results. So as a recommendation always use Number.isNaN(). This last function checks if the type is number and equal to NaN, any other value will return false.

// Usando funcion global
isNaN('James'); // true --> Esto esta mal, deberia seguir regresando false
// lo que realmente hace es una conversion automatica
const result = number('James'); // NaN
isNaN(result); // true
number.isNaN('343434'); // false
number.isNaN('James'); //false
number.isNaN(1 + undefined); // true

We can see in the first example that the global function returns true when it should be false, this is due to the automatic type conversion that javascript does.

Function Number(value)

You can convert a value to a number using the function Number(value), just be careful because this function can return 0 for many values, as well as NaN.

number('5'); // 5
number(''); // 0
number(undefined); // NaN
number(null); // 0
number('8778jaime'); // NaN
number(false); // 0
number(true); // 1;
number({}); // NaN
number([]); // 0

Number.parseInt and Number.parseFloat

Finally we have the functions Number.parseInt(value) and Number.parseFloat(value), if the value is not a string, then convert it to string using the method .toString() before converting to number.

number.parseInt(''); // NaN
number.parseInt('78.5jaime'); // 78
number.parseInt(78.58977); // 78
number.parseFloat(''); // NaN
number.parseFloat('78.5jaime'); // 78.5

BigInt

This type of value is new, added to the language in 2020, it is used to represent very large integer values, especially for mathematical calculations with very large quantities.

To use this type of data, the letter is added to the number n in the end. This is the recommended way.

const enteroMuyGrante = 999999999999999999999999999999999999999999999999999n;
const otroEnteroMuyGrande = 55555555555555555555555555555555555555555555555n;
const result = enteroMuyGrande * otroEnteroMuyGrande; //

Operations can be performed between the Number type and the BigInt, but because conversion between types can cause loss of precision, it is recommended to only use values BigInt when values greater than 2 are being used53 and only perform operations with values of the same type BigInt.

Another bad news about BigInt is that you cannot use the object's methods on a BigInt value. MathematicsFor example, you cannot use Math.sqrt().

Mathematics.sqrt(99); // 9.9498743710662
Mathematics.sqrt(99999999999999999n); // Uncaught TypeError: Cannot convert a BigInt value to a number

As a final recommendation, do not complicate your life, do not use BigInt unless the problem you want to solve necessarily requires very large integers.

BigInt(value) function

You can convert and create a BigInt with the function BigInt(value)

BigInt('9999999999'); // 9999999999n

Boolean

Boolean is a logical data type, which is represented by only two values. true and false. Very useful for making decisions in our programs. Named after the mathematician George Boole.

Boolean type values can be defined as follows. This is the recommended way

const tieneHijos = true;
const esEstudiante = false;

They are widely used in logical operations, for example:

if (tieneHijos) {
  // Si "si" tiene hijos, preguntar cuantos hijos tiene
} else {
  // si "no"
}
if (esEstudiante) {
  // Si "si" es estuduante, aplicar descuento
} else {
  // si "no"
}

Boolean function(value)

Booleans also have a function Boolean(value), is suitable for creating booleans and explicitly converting a value to Boolean. More details below in the section Values that can generate Booleans.

null

This data type in Javascript is very easy, it is a data that means it is nothing compared to the other data types. In other languages null It refers to a pointer or a memory reference that is empty, but in javascript it is different, it is simply a value that means “nothing".

const nada = null;

undefined

This data type represents something that is not yet defined. It is the automatic value of variables, parameters and properties of objects that have not had a value defined.

let name; // undefined
let edad; // undefined
name === undefined; // true
edad === undefined; // true

symbol

This type of data is primarily used to ensure that its value is unique and immutable. It can be used as object properties to reduce access to those properties and thus avoid unwanted modifications. When we look at the objects in more detail we will see their use in practice.

To create this type of primitive data the function is used Symbol(). It is the only way to create a symbols and it is the recommended one.

const name = symbol('Jaime');
const nombreIgual = symbol('Jaime');
name === nombreIgual; // false

String or string of characters

Strings allow us to save information in text form. They are a sequence of one or more 16-bit, UTF-16 characters. There is no `char` type like in other languages, if you want a character, you simply create a string with a single character. Simple right?

We have three ways to create a string.

Actually you can also create strings with the function String(value) or in constructor form new String(value), but let's not complicate our existence and only use the three below for simplicity:

  1. With single quotes, ''. Recommended if you do not need to evaluate expressions inside.
  2. Double quotation marks, ""
  3. backticks, `` . Recommended if you need to evaluate expressions within.
const name = 'Jaime';
const last name = "Cervantes";
const mother's last name = `Velasco`;

The third way to define Strings, allows us to use expressions within the character string, so it is very useful. For example:

const name = 'Jaime';
const last name = "Cervantes";
const mother's last name = `Velasco`;
const nombreCompleto = `${name} ${last name} ${mother's last name}`; // Jaime Cervantes Velasco

Strings are immutable, when you modify or extend a string a new one is actually generated.

Two character strings can be the same

You can check that two character strings are the same with ===.

"James" === "James"; // true
'James' === "James"; // true
`James` === 'James'; // true

Function String(value)

To convert a value to a string you can use the function String(value).

String(1); // '1'
String(null); // 'null'
String(undefined); // 'undefined'

String.length

The property length of a string is used to know the length of a string of characters, you will see over time that this is useful when working with strings of characters.

const name = 'Jaime Cervantes Velasco';
name.length // 23

Objects

All other data types are objects, a function is an object. A object is a collection of pairs name: value, similar to PHP's “associative arrays”. These pairs of name/value They are called properties, a property is like a variable and can contain any type of value.

Some objects in Javascript:

  • object
  • function
  • array
  • date
  • RegExp
  • Mistake

Primitive Wrapping Objects

Even primitive data types String, Boolean, Number, BigInt and Symbol has its corresponding representation in Object, called enveloping objects. In fact, Javascript implicitly converts this primitive data to objects in order to occupy useful methods and properties. For example the property length of a string of characters.

How were you planning to get the length of a character string? Understanding that a character string is primitive data and has no methods

'Jaime Cervantes Velasco'.length; // 23, el pri
// A groso modo, lo que sucede implictamente al querer obtener lenght:
const nuevoString = new String('Jaime Cervantes Velasco');
nuevoString.length; // 23
(5).toFixed(2); // 5.00
// Igual a groso modo pasa algo asi:
const numero = new number(5);
numero.toFixed(2); // 5.00
false.toString(); // 'false'
// Igual a groso modo pasa algo asi:
const booleano = new Boolean(false);
numero.toString(2); // false
// Estos dos tipos de datos primitivos no permiten el uso de new
(9n).toLocaleString(); // '9'
symbol('Hi').toString(); // 'Symbol(Hi)'

Although the BigInt and Symbol data types do not allow the use of new It does not mean that objects are not created behind, it is clear that javascript wraps them in an object because it allows us to use the methods of the example, toLocaleString and toString.

How to create an object?

To create an object you don't need to create a class, you simply create the object and start using it. The easiest way to create an object is to use the definition called literal object, where you simply open and close keys {}. This is the recommended way.

const vacio = {};
const person = {
  name: 'Jaime',
  apellidos: 'Cervantes Velasco',
  edad: 33,
  getName: functions () {
    return `${this.name} ${this.apellidos}`;
  },
  talk: functions () {
    return `Hola, soy ${this.getName()}, tengo ${this.edad} años.`;
  }
};
const frase = person.talk();
console.log(frase); // 'Hola soy Jaime Cervantes Velasco, tengo 33 años.'

In the example we have an object person, has several properties of different types, its name is a String, his age is a numbergetName and talk are of type function, functions that are members of an object are called methods.

Below are examples of objects.

Accessing properties with square brackets, ['key']

In the previous example we saw how to access the method talk(), this method is still a property and is of type functions. But there is another notation to access properties, using square brackets. Very similar to how the elements of an array are accessed.

person.edad; // regresa 33
persona['edad']; // regresa 33
// obtenemos la funciónn con corcheteds y la invocamos con parentesis
const frase = persona['talk']();
console.log(frase); // 'Hola soy Jaime Cervantes Velasco, tengo 29 años.'

How to create an object functions?

functions printPerson(person) {
  console.log(person.name);
  console.log(person.edad);
}

As the function printPerson It is an object, we can add properties to it without any problem.

printPerson.miPropiedad = 'Mi propiedad de una funcion';
console.log(imprimierPersona.miPropiedad); // 'Mi propiedad de una funcion

How to create an object array?

The recommended way is to simply create them using square brackets [].

const vacio = [];
const numeros = [1, 2, 3, 4, 5, 6];
const animales = ['perro', 'gato', 'caballo'];
const conObjetos = [
  		{
          name: 'Jaime',
          edad: 33
        },
        functions imprimierPersona(person) {
          console.log(person);
        }
	];

Since an array is an object, just like a function, you can also add properties to it.

const numeros = [1, 2, 3, 4, 5, 6];
numeros.miPropiedad = 'Mi propiedad de un arreglo';
console.log(numeros.miPropiedad); // 'Mi propiedad de un arreglo

How to create an object date?

const fecha = new date();
console.log(fecha); // Fri May 28 2021 10:46:27 GMT-0500 (hora de verano central)

As you can imagine, we can also add properties to the date object because it is an object

For now, I hope this gives you an idea of the importance of objects in Javascript and why it deserves a more extensive explanation in a future publication.

Values that can generate a boolean false

There are true values and false values, which when applied to a condition behave like Booleans. This is because Javascript does an implicit type conversion, which can surprise us if we are not careful, so here I leave you the list of values that can return a Boolean false.

  • false
  • null
  • undefined
  • 0
  • 0n
  • NaN
  • "", "", " (empty character string)

All other values, including objects, in a condition or passed to the function Boolean(value) the Boolean returns true. A string with a space " ", came back true, and a string with value "false" also returns true.

Boolean function(value)

There is a global function to create Boolean values, Boolean(value). Where yes worth It's a real one, come back true, otherwise it returns false.

Boolean(false); // false
Boolean(null); // false
Boolean(undefined); // false
Boolean(0); // false
Boolean(0n); // false
Boolean(NaN); // false
Boolean(''); // false
// Todos los demas valores van a regresar true
Boolean(' '); // true
Boolean('false'); // true
Boolean('jaime cervantes'); // true
Boolean({}); // true
Boolean([]); // true;

Under logical conditions

Logical conditions in javascript check without a return expression true either false, they execute an implicit conversion.

if (false) {
} else {
  console.log(false);
}
if (null) {
} else {
  console.log(false);
}
if (undefined) {
} else {
  console.log(false);
}
if (0) {
} else {
  console.log(false);
}
if (0n) {
} else {
  console.log(false);
}
if (NaN) {
} else {
  console.log(false);
}
if ('') {
} else {
  console.log(false);
}
if (' ') {
  console.log(true);
}
if ('false') {
  console.log(true);
}
if ({}) {
  console.log(true);
}
if ([]) {
  console.log(true);
}

Verify types with the operator typeof

This operator allows us to identify the type of data we are working with, useful in case we do not know where the information comes from, or we want to process the data based on its type. The operator returns the lowercase name of the data type.

typeof 5; // 'number
typeof NaN; // 'number'
typeof 99999999999999999999999999999999999999999999999n; // 'bigint'
typeof true; // 'boolean'
typeof null; // 'object', esto es un error que existe desde la primera versión de JS
typeof undefined; // 'undefined'
typeof symbol('simbolo'); // 'symbol'
typeof 'cadena de caracteres'; // 'string'
typeof {}; // 'object'
typeof []; // 'object
typeof new date(); // 'object'
typeof new String('Jaime'); // Object
typeof functions() {} // 'function'
typeof class A {} // 'function'

There is a known bug in javascript, when the typeof operator is executed on null, this one comes back'object'. This bug has existed since the first version of Javascript, Bad things happen when you write code on the run.

If all other non-primitive values are objects, when we use the operator typeof about them, what type of data will you tell us what they are? Exactly, 'object'. Just like in the example above when we pass an object literal, an empty array, a date type object and when we use the surrounding objects of primitives like new String('Jaime').

Existe una excepción en typeof, cuando el valor es una función o una clase, regresara functions. Recuerda, una función en javascript, también es un objeto.

Check types with the method Object.prototype.toString

As we saw, it is somewhat confusing to use the operator typeof, I prefer to use a safer method, it is somewhat strange, but since everything in Javascript is an object and the base object from which all data types in javascript start is object, with the exception of the primitive data (although these in turn have their object version), then we can do something like the following.

object.prototype.toString.call(5); // '[object Number]'
object.prototype.toString.call(NaN); // '[object Number]'
object.prototype.toString.call(99999999999999999999999999999999999999999999999n); // '[object BigInt]'
object.prototype.toString.call(true); // '[object Boolean]'
object.prototype.toString.call(null); // '[object Null]',
object.prototype.toString.call(undefined); // '[object Undefined]'
object.prototype.toString.call(symbol('simbolo')); // '[object Symbol]'
object.prototype.toString.call('cadena de caracteres'); // '[object String]'
object.prototype.toString.call({}); // '[object Object]'
object.prototype.toString.call([]); // '[object Array]'
object.prototype.toString.call(new date()); // '[object Date]'
object.prototype.toString.call(new String('Jaime')); // '[object String]'

From this method, you can create a function that verifies the data type.

functions getTypeOf(worth) {
  const texto = object.prototype.toString.call(worth); // '[object Number]', '[object Boolean]', etc
  const sinPalabraObject = texto.slice(8, -1); // Number, Boolean, Null, Undefined, Symbol, String, etc.
  const tipo = sinPalabraObject.toLowerCase(); // number, boolean, null, undefined, symbol, string, etc.
  return tipo;
}
getTypeOf(1); // 'number'
getTypeOf(new date()); // date
getTypeOf([]); // array

The special property prototype is very important in Javascript, if you have read more than one of my publications, you will have noticed that I have mentioned that Javascript is a multiparadigm and object-oriented programming language based on prototypes, in another publication we will explain in detail the functionality of prototypes in Javascript .

Conclusion

Everything in Javascript is an object, with the exception of primitive types, but as we already saw, when wanting to use them as objects by invoking some method, that is where javascript wraps them (in practice everything is an object).

Any programming language has good things that we can take advantage of, but it can also have strange and confusing things (compared to most modern programming languages), such as the operator typeof and the method Object.prototype.toString, the value NaN, the values that can generate a boolean false, and many other things we didn't see for simplicity's sake. It is up to the programmer to take the best parts and eliminate or mitigate those that do not help us communicate better with our work team, always with a focus on simplifying things.

In the case of creating some type of data in Javascript, the simplest and easiest way to use is simply creating the values that we are going to use. As recommended in previous sections, this way of creating them is called literal.

const numero = 9999.54;
const enteroGrande = 99999999999999n;
const boleano = true;
const nulo = null;
let noDefinido;
const simbolo = symbol('identifier');
const cadenaDeCaracteres = 'Jaime Cervantes Velasco';
const cadenaDeCaractresConExpresion = `El numero ${numero} es "Number"`;
const object = {};
const arreglo = [];

There are even more details to cover about data types in javascript, but as we go we will see more necessary topics, for now it seems to me that this information is enough.

Paradigma de programación en JavaScript

JavaScript programming paradigm

What is a programming paradigm?

The model or map of how we see the real world, that is a paradigm, it is a way of seeing and doing things. Following this logic, a programming paradigm is nothing more than a way of viewing and creating programming code.

Paradigms are powerful because they create the glasses or lenses through which we see the world.

Stephen R. Covey

There are three main programming paradigms used today and in JavaScript they have always existed since its first version.

  • Structured programming paradigm
  • Object-oriented
  • Functional

Now, if we stick to the phrase of Stephen R. Covey, that paradigms create the lenses through which we see the world. Let's imagine that the three previous paradigms, each, are a pair of glasses that we put on when programming and that we can change those glasses according to our visual needs (for programming or problem solving).

Structured programming paradigm

Origin

In 1954 the FORTRAN programming language appeared, then in 1958 ALGOL and in 1959 COBOL. Time after Edsger Wybe Dijkstra in 1968 discover the structured programming paradigm, we say “discover” because they didn't actually invent it. Although this programming paradigm was formalized some time after the appearance of these programming languages, it was possible to do structured programming in them.

Dijkstra He recognized that programming was difficult, and programmers don't do it very well, which I totally agree with. A program of any complexity has many details for the human brain. In fact, the Neuroscience tells us that the focused mind It can only work with four pieces of data at a time, at most. For this reason, if one small detail is neglected, we create programs that seem to work well, but fail in ways you never imagine.

Evidence

Dijkstra's solution was to use tests, only these tests used a lot of mathematics, which was quite difficult to implement. During his research he found that certain uses of GOTO made it difficult to decompose a large program into smaller pieces, it could not be applied “divide and conquer”, necessary to create reasonable evidence.

Sequence, selection and iteration

Patrones de la programación estructurada
Patterns of structured programming

Böhm and Jacopini They proved two years earlier that all programs can be built by just three structures: sequence, selection and iteration. Dijkstra already knew these three structures and discovered that these are the ones necessary to make any part of the program tested. This is where the structured programming paradigm is formalized.

Edsger tells us that it is bad practice to use GOTO and suggests better using the following control structures:

  • If, then, else (selection)
  • do, while, until (iteration or repetition)

Decomposition of small units easy to test

Nowadays most programming languages use structured programming, JavaScript uses this type of programming. The simplest example is if conditions.

const EDAD_MINIMA = 18;
if (edad >= EDAD_MINIMA) {
	// hacer algo porque es mayor que 18
} else {
	// Hacer otra cosa en caso contraio
}

And if we isolate it in a function, we have a decomposition of functionalities or units that can be tested more easily. In the next section we will see the importance of having a completely probable unit

const EDAD_MINIMA = 18;
functions esMayorEdad(edad) {
  if (edad >= EDAD_MINIMA) {
     return true;
  } else {
     return false;
  }
}

With this condition we have direct control of what can happen if the age is greater than or equal to 18, and also in the event that the age is younger.

Let's not be so strict either, surely the GOTO ruling has its merits and perhaps it was very efficient in some cases, but I think that to avoid misuses that probably caused disasters, Dijkstra recommended to stop using GOTO.

Test, divide and conquer

Structured programming allows us to apply the “divide and conquer” philosophy, because we allows you to create small unit tests, until the entire program is covered. The mathematical solution of Wybe Dijkstra It was never built, precisely because of its difficulty in implementation. And unfortunately today there are still programmers who do not believe that formal tests are useful for create high quality software.

And I say create, because verify correct operation after create, is nothing more than a simple measurement and the opportunity to reduce time and money is lost.

Scientific method, experiments and impiricism

Método científico, experimentos y pruebas
Scientific method, experiments and tests, by ThisIsEngineering Raeng on unsplash

The good news is that the mathematical method is not the only way to verify our code, we also have the scientific method. Which cannot prove that things are absolutely correct from a mathematical point of view. What we can do is create experiments and obtain enough results to verify that our theories work. Since our theories work on these experiments, then we conclude that they are “correct” enough for our validation purposes.

If the theory is easily validated as false, then it is time to modify or change it. This is the scientific method and this is how tests are currently done:

First we establish our theory (write the test), then we build the experiments (write production code) and finally we verify (run the test) and repeat this cycle until we have enough evidence.

Doesn't this sound like a current agile practice called TDD?

Tests show the presence, not the absence, of defects

Edsger Wybe Dijkstra said “Testing shows the presence, not the absence, of defects.” That is, a program can be proven wrong by testing, but it cannot be proven correct. All we can do with our tests is validate that our program works well enough for our goals. But we can never be one hundred percent sure of the absence of defects.

If we can never be one hundred percent sure that our code is correct, even with its tests, what makes us think that without tests we deliver a program with sufficient validity to affirm that no negligence is consciously committed?

direct control

lto structured programming teaches us about direct control, that is, controlling the sequential flow of operations through the control structures, without neglecting the recommendation of Wybe Dijkstra about GOTO. This recommendation also applies to statements that drastically change the normal flow of operations, for example a break within a cycle for nested, that break It breaks direct control because it abruptly complicates the understanding of the algorithm. Let's not be purists either, there will surely be cases where you need these sentences, but in the first instance, try to avoid them.

In conclusion, the structured programming paradigm teaches us:

The direct, clear and explicit control of what a piece of code does

Object-oriented programming paradigm

Arised from functions?

The object-oriented programming paradigm was discovered in 1966 by Ole Johan Dahl and Kristen Nygaard when they were developing simula 67. Two years before structured programming and its adoption by the programming community was some time later. In 1967 it was launched Simulates 67, Simulates It was the first object-oriented programming language, it basically added classes and objects to ALGOL, initially Simula was going to be a kind of extension of ALGOL.

During the development of Simula, it was observed that the execution of an ALGOL function requires certain data, which could be moved to a tree structure. This tree structure is a Heap.

The heap allowed you to declare local variables of the function that can exist even after the function returns a value. Doesn't this last sound like what closure is in JavaScript?

The parent function becomes a constructor, the local variables become the properties, and the child (nested) functions become its methods. In fact, this pattern is still widely used by Javascript to create modules and use functional inheritance. This also describes how classes work in Javascript, behind are functions.

Spread of polymorphism

All this helped a lot to implement polymorphism in object-oriented programming languages. Ole Johan Dahl and Kristen Nygaard invented the notation:

object.function(parametro)

The execution of function that belongs to object, but more importantly, we pass a message through parameters from the first part of the code to the second part located in a different object.

Molecular biology and message passing

Paso de mensajes entre células
Passing messages between cells, Image modified from “Signaling molecules and cellular receptors: Figure 1,” by OpenStax College, Biology (CC BY 3.0).

Some time later it was created Smalltalk, a much more sophisticated and modern object-oriented programming language, in charge of this project was Alan Kay. This person is credited with the formal definition of object-oriented programming.

The main influence on Alan Kay's object-oriented programming was biology, he has a degree in biology. Although it is obvious that it was influenced by Simula, the influence of LISP (functional programming language) is not so obvious.

From the beginning he thought of objects as interconnected cells in a network, from which they could communicate through messages.

Alan Kay commented:

I'm sorry I coined the term a long time ago. Objects for programming because it made people focus on the least important part. The big idea is “Sending messages“.

Alan Kay

My English is bad so you can check the original text here.

Better object composition over class inheritance

Smalltalk It also allowed the creation of Self, created at Xerox Parc and later migrated to Sun Microsystems Labs. It is said that Self It is an evolution of smalltalk.

In this programming language the idea of prototypes, eliminating the use of classes to create objects, this language uses the objects themselves to allow one object to reuse the functionalities of another.

Self It is a fast language and is generally known for its great performance, self It did a good job on garbage collection systems and also used a virtual machine to manage its execution and memory.

The virtual machine Java HotSpot It could be created thanks to Self. Lars Bak one of Self's latest contributors, he was in charge of creating the V8 Javascript engine. Due to the influence of Self we have today the engine of JavaScript V8, which uses it node.js, mongoDB and Google Chrome internally.

Self followed one of the book's recommendations Design Patterns: Elements of Reusable Object-Oriented Software, long before it came out, published this recommendation:

Better composition of objects to class inheritance.

Design Patterns: Elements of Reusable Object-Oriented Software

Example

Currently Javascript uses prototypes for code reuse, you could say that it uses composition, instead of inheritance. Let's look at an example:

const person = {
    greet () {
      return 'Hola'
    }
};
// se crea un programador con el prototipo igual al objeto persona
const programmer = object.create(persona);
programmer.programar  = () => 'if true';
const saludo = programmer.greet();
const codigo = programmer.programar();
console.log(saludo); // 'Hola'
console.log(codigo); // 'if true'

The object programmer It is based on the prototype of `person`. It doesn't inherit, it just directly reuses the functionality of `person`.

JavaScript emerged shortly after JAVA, in the same year. JavaScript took influences from Self, and in turn Self was influenced by smalltalk.

The syntax of current classes in Javascript is nothing more than a facade, well a little more accurately they are an evolution of the constructor functions, but internally, their basis are functions and prototypes.

Communication with message passing

As we already saw, the origin of object-oriented programming has its origins in functions, and the main idea has always been communication between objects through message passing. We can say that Object-oriented programming tells us of message passing as a key piece for the communication of objects, for example, when a method of one object invokes the method of another.

object.function(parametro);

In conclusion, the object-oriented programming paradigm teaches us:

Message passing for communication between objects

Functional programming paradigm

lambda calculation

Image taken from https://www.slideshare.net/FASTPresentations/introduction-to-lambda-calculus-using-smalltalk-by-facundo-javier-gelatti

Functional programming is the oldest programming paradigm, in fact its discovery was long before computer programming, it was discovered in 1936 by Alonzo Church, when I invented the lambda calculus, based on the same problem to be solved by your student Alan Turing.

As a curious fact, the symbol of the lambda calculus is:

λ

The first language based on functional programming was LISP, created by John McCarthy. As we saw previously, Alan Kay also took influence from LISP to create Smalltalk, with this we can see that the programming paradigms can be united and their relationship between them arises from the idea of how to solve problems more efficiently, they are not fighting, nor Separated, they seek the same goal and somehow evolve together.

The basis of the lambda calculus is immutability, We will review this concept later.

Similarities with OO and structured paradigms

As we saw in the structured programming paradigm, we can decompose our programs into smaller units called procedures or functions. Since functional programming is the oldest paradigm, we can say that the structured programming paradigm also relies on functional programming.

Now, if we analyze the notation a little object.function(x) that we saw in the object-oriented programming paradigm section, is not very different from function(object, parameters), these two lines below are the same, the fundamental idea is the passing of messages, as Alan Kay tells us.

object.function(parametro);
function(objeto, parametro);

Smalltalk uses the “The Actor Model”, which says that actors communicate with each other through messages.

On the other hand we have LISP, which has a “Function dispatcher model” What we currently call functional language, these models are identical, because what functions and methods do is send messages between actors.

An example of this is when a function calls another function or when an object's method is invoked, what happens is that actors exist and they communicate with each other through messages.

Message passing again

So we can emphasize that the main idea of OOP is the sending of messages and that it is not very different from functional programming, in fact according to what we already established in the previous sections, OOP was born from a functional base. And here it is important to highlight what he said Alan Kay Co-creator of SmallTalk:

I'm sorry I coined the term a long time ago. Objects for programming because it made people focus on the least important part. The big idea is “Sending messages“.

Alan Kay

From the communication models between Smalltalk and LISP messages, it was created scheme.

scheme has the goodness to use tail recursion and closure to obtain a functional language, closure allows access to the variables of an external function even when it has already returned a value. This is the same principle that gave rise to object-oriented programming by Ole Johan Dahl and Kristen Nygaard. Do you remember the closure question in Javascript?

Javascript uses closure a lot in its functional programming paradigm. JavaScript took influences from scheme, at the same time scheme was influenced by LISP.

No side effects

The basis of the lambda calculus is immutability, therefore, lImmutability is also the basis of the functional programming paradigm.

We as functional programmers must follow this principle and limit object mutations as much as possible to avoid side effects.

I repeat, the main idea of functional programming is immutability, which allows you to create your programs with fewer errors by not producing side effects that are difficult to control.

As an example, suppose we have an object person and we want to “change” the name, the most obvious thing would be to modify the name property directly, but what happens if that object is used elsewhere and the name is expected to be “Jaime”, that is why instead of changing the name property , we only create a new person object with a different name, without modifying the original.

functions cambiarNombre(name, person) {
  return {
    name: name,
    edad: person.edad
  }
}
const James = { name: 'Jaime', edad: 30 };
const juan = cambiarNombre('Juan', jaime);
console.log(jaime); // { nombre: 'Jaime', edad: 30 }
console.log(juan); // { nombre: 'Juan', edad: 30 }

Here you will find more details about the fundamental principles of functional programming:

Introduction to functional programming

Finally, the functional programming paradigm teaches us:

No side effects, for clear expression and less prone to errors

Conclusion

It is important to note that if the three programming paradigms were implemented between 1958 with LISP (functional programming) and Simula (object-oriented programming) in 1966, and the discovery of the structured programming paradigm in 1968, in only a period of 10 For years there has been innovation in programming paradigms, and new paradigms have not really emerged, unless they are based on these three main ones.

Right now more than 60 years have passed, which tells us the importance and firmness they have despite the time that has passed.

  • Functional programming paradigm (1958, already implemented in a programming language for computers, remember that it was discovered in 1936)
  • Object Oriented (1966)
  • Structured (1968)

The implementation of these three paradigms from the beginning within JavaScript has made this programming language the global success it is today. And it proves to us the value of combining paradigms when writing our programs.

JavaScript is a multi-paradigm programming language, so you can combine the paradigms to create much more efficient and expressive code using:

  • The direct, clear and explicit control of what a piece of code does
  • Message passing for communication between objects
  • No side effects, for clear expression and less prone to errors

References

https://en.wikipedia.org/wiki/Structured_programming

https://en.wikipedia.org/wiki/Structured_program_theorem

http://wiki.c2.com/?AlanKayOnMessaging

https://www.slideshare.net/FASTPresentations/introduction-to-lambda-calculus-using-smalltalk-by-facundo-javier-gelatti

Clean architecture book

Variables en Javascript y constantes

Javascript variables and constants

Variables

One of the most used elements are variables in Javascript. We can describe variables in Javascript as boxes to hold information, which we label so that we can find that information easily. This label is the name of the variable and the box is the space used in RAM.

Variables y constantes, cajas que guardan información
Variables and constants, boxes that store information

This is what variables are like in Javascript, and in fact in any programming language. You can also store any datatype, whether they are numbers, text strings, functions or any type of object.

There are two ways to declare a variable. One is using let and the other using var.

//Variables de tipo String
var name = 'Jaime';
let last name = "Cervantes"

The shape var It is the one that has always existed since the origin of language, then in 2015 it appeared let in order to mitigate certain deficiencies of var. For this reason, the recommendation is to use letIn any case, it is important to know well var because you will come across a lot of code that still uses var.

How are variables used in Javascript?

The name or identifier of a variable, it cannot start with a number, it must start with some letter (including _ and $), and Javascript is also case-sensitive. Is not the same name and Name, these are two different variables.

Variables are defined in two ways:

With a single let:

let name = 'Jaime',
    last name = 'Cervantes',
    mother's last name = 'Velasco';

a single var:

var name = 'Jaime',
    last name = 'Cervantes',
    mother's last name = 'Velasco';

Now with a let for each variable:

let name = 'Jaime';
let last name = 'Cervantes';
let mother's last name = 'Velasco';

With a var for each variable.

var name = 'Jaime';
var last name = 'Cervantes';
var mother's last name = 'Velasco';

In the previous example we define variables of type string (text strings), but remember that you can store any type of data.

It is advisable to put each variable on its own line because it is faster to understand for the “you” of the future and your colleagues who have not touched your code. For example, DO NOT define the variables like this:

let name = 'Jaime', last name = 'Cervantes', mother's last name = 'Velasco'; edad = 32, sexo = 'H'

Let's try numbers.

let edad = 32.9;
let hijos = 1;
var edad = 32.9
var hijos = 1;

Boolean data only stores false or true.

let esHombre = true;
let esAlto = false;
var esHombre = true;
var esAlto = false;

As its name says, its value can be variable, therefore you can reassign a new value to your variable:

var name = 'Jaime';
name = 'Pepito';
name = 'Menganito';
console.log(nombre); // 'Menganito'

Variable scopes in Javascript, let vs var

The main difference between variables defined with let and var is the scope they reach when they are declared:

  • With let you have block scope {}.
  • With var you have scope of function function() but not block.

Example of block scope.

if (true) {
  let name = 'James';
}
console.log(nombre); // Uncaught ReferenceError: nombre is not defined

Because let has block scope, when wanting to access the variable name Javascript shows:

Uncaught ReferenceError: name is not defined

Try to use block scope with var.

if (true) {
  var name = 'Jaime';
}
console.log(nombre); // 'Jaime';

In this example the variable name If it can be accessed from outside the blocks, this is because it is not inside any function.

Now we are going to declare the variable with var inside a function.

functions setearNombre() {
  var name = 'Jaime';
}
setearNombre();
console.log(nombre); // Uncaught ReferenceError: nombre is not defined

Let's see what happens with let when we try to use function scope.

functions setearNombre() {
  let name = 'Jaime';
}
setearNombre();
console.log(nombre); // Uncaught ReferenceError: nombre is not defined

If we define a variable with let inside a function, we can't access it from outside either, because the function definition itself uses blocks {}.

Constants in Javascript

Constants are in the same way as variables, labeled boxes to store information, with the only difference that they cannot be reassigned to any other value.

const name = "Jaime";
name = "Pepito"; // Uncaught TypeError: Assignment to constant variable 

Let's not forget to declare each constant on its own line to improve the readability of our code.

const name = "Jaime";
const last name = "Cervantes";
const mother's last name = 'Velasco';
const name = 'Jaime',
    last name = 'Cervantes',
    mother's last name = 'Velasco';

Same rules as variables with let

Constants follow the same block scope rules as variables in Javascript with let.

As well as let, const has block scope, so if you define a variable with var and has the same name as a constant, the following error will be thrown:

{
  const name = "Jaime";
  var name = "Pepito"; // Uncaught SyntaxError: Identifier 'nombre' has already been declared
}

Constants in javascript read-only and mutable

Constants are read-only, which is why they cannot be reassigned a value. Even so, these saved values continue to preserve the behavior of their data type.

For example, if you create a constant for an object, you can change the properties of that object.

An object literal in JavaScript is nothing more than a set of values identified with a name or key, like the following:

const James = {
  name: "Jaime",
  last name: "Cervantes",
  mother's last name: "Velasco"
};
James.name = "Pepito"; // todo bien, se puede cambiar una propiedad
James = {}; // Uncaught Type Error: Assigment to constant variable

The reference to the object is read-only, but it does not mean that the value is immutable. As seen in the example, you can change the property, but not reassign a new value to the constant James as we can see in the last line of the example.

How to name variables and constants in Javascript?

Any fool can write code that a computer can understand. Good programmers write code that humans can understand.

Martin Fowler

The main objective of naming variables and constants is to immediately understand what we are storing in them. It is important to correctly describe the content of the variables, because this makes life easier for the next person who needs to read and modify our code.

This next person is very often “you” from the future, and unless you are a robot, you won't be able to remember every detail of your code.

Most of the time spent by a programmer is reading and understanding code, we don't want to spend a lot of time deciphering the content of them, as programmers we are happier creating new things.

For this reason we should not be surprised by the importance in naming our variables and constants, it is one of the best ways to not waste our time and the time of our colleagues.

Recommendations:

  • Take enough time to name a variable. It's like organizing your room, the tidier it is, the faster it will be to find the other sock (it happens to me a lot when I don't organize mine) xd.
  • The name must be very semantic and explain its context. Avoid names like data either info because they don't say much about the context, it is obvious that they are data and information, but for what? or what?.
  • Agree with your colleagues on how to name variables, especially those that are closely related to the business. For example, for a user's registration data, it can be “UserRegistration”, “CustomerRegistration”, “VisitorRegistration”, all three forms can be valid (it depends a lot on the context), but it is better to follow a convention through an agreement.
  • Avoid very short names like “u1”, “a2”, “_”, “_c”
  • Avoid abbreviations, prefixes, suffixes and infixes. These are difficult to understand. For example pmContentWhat is “pm”?
  • If the variable or constant has a very small scope, that is, it is used in nearby lines, then the name can be short.
  • If the variable or constant is used in a large scope, that is, it is referenced over a distance of many lines, then the name must be very descriptive, and therefore it is normal that it can be long.

Related posts

https://www.pensemosweb.com/introduccion-javascript/
https://www.pensemosweb.com/javascript-scheme-self-java/
Javascript Event Loop, concurrencia y asíncrono

Javascript Event Loop, concurrencia y asíncrono

Javascript es secuencial

“Event loop”, tal vez lo has escuchado. Esto es porque javascript tiene modelo de ejecución de código donde utiliza un ciclo de eventos (event loop), que una vez entendiendo su funcionamiento, se puede crear código mucho más eficiente, y resolver problemas rápidamente, que a simple vista no son tan obvios. Es la base de la concurrencia y el asincronismo.

Para comenzar:

  • Javascript se ejecuta en un solo hilo de ejecución, como se ejecuta un solo hilo, su ejecución es secuencial, no es como JAVA donde se pueden lanzar otros hilos.
  • Existen ambientes huéspedes donde se ejecuta javascript que tienen su propia API, ejemplo:
    • Navegador web
    • Node.js
  • Este funcionamiento secuencial es el mismo, no cambia por estar relacionado con un ambiente huésped.
  • La concurrencia se logra a través de invocaciones asíncronas a la API del ambiente huésped, esto evita que el funcionamiento se bloquee y provoque lentitud de las aplicaciones.

Elementos para la concurrencia

Veamos con más detalle los elementos que hacen funcionar Javascript en los ambientes huéspedes.

  1. Call Stack – Pila de ejecuciones
  2. Callback Queue – Cola de retrollamadas, tambien llamado Task Queue
  3. Event Loop – Ciclo de eventos
  4. Host Environment – Funcionalidad del ambiente huésped
Event loop, ciclo de eventos javascript
Event loop, ciclo de eventos javascript

Calls Stack, heap y motor de javascript

Del lado izquierdo tenemos al motor de javascript, este motor se encarga de ejecutar nuestro código. A veces es llamado máquina virtual, porque se encarga de interpretar nuestro código a lenguaje máquina y ejecutarlo. Solo puede ejecutar una línea de código a la vez. Tiene un Heap para guardar objetos y demás datos en memoria que el código pueda generar.

Pero también tenemos una Pila de llamadas (Call Stack). Los elementos de la pila son objetos y datos de memoria, pero tienen una estructura especifica. Tienen un orden y el último elemento en entrar es el primero en salir, se le llama LIFO (Last-in, First-out).

Cada elemento de la pila es un trozo de código Javascript y guarda las referencias del contexto y variables utilizadas. La pila ejecuta el trozo de código en turno hasta quedar vacía.

Callbacks Queue

Abajo tenemos Callbacks Queue, es una estructura de datos y guarda pedazos de código que el motor de javascript puede ejecutar. Es una cola, y como la cola de las tortillas el primero en formarse, es el primero en salir (FIFO, First-in, First-out).

Un callback, es una función que se pasa por parámetro a otra, de tal manera que esta última ejecuta el callback en un punto determinado, cuando las condiciones y/o los datos cumplen una cierta regla de invocación.

Event loop

Event Loop, este elemento nos permite mover la siguiente callback del Callbacks Queue al Call Stack. Como es un ciclo, en cada iteración toma un solo callback.

Ambiente huésped

Del lado derecho tenemos El ambiente huésped, el ambiente huésped es el lugar donde corremos Javascript, los más comunes son el Navegador web and Node.js. Las tareas que ejecuta el ambiente huésped son independientes de los demás componentes. En el navegador web tiene sus propias API como fetch, setTimeout, alert. Node.js también cuenta con su propia API como net, path, crypto.

¿Cómo es posible?, ¿Y la concurrencia? ¿Puedo hacer muchas cosas a la vez en un sitio web?

Todo el trabajo de poner un temporizador, renderizar contenido como texto, imágenes, animaciones, o ver videos, están a cargo del ambiente huesped. Lo que pasa es que las APIs del navegador web generan callbacks cuando su tarea ya está completada y los agrega al Callbacks Queue para que el event loop las tome y las mueva al Call stack.

Javascript se comunica con el ambiente huésped a través de su API, mas adelante vamos a utilizar un ejemplo basado en el diagrama de arriba, donde se utiliza window.setTimeout, la cual es una función del navegador web.

Concurrencia

Home es la función principal, con la que se inicia el proceso de ejecución en el call stack. Dentro de inicio tenemos cuatro setTimeout de dos segundos. La función setTimeout es propia del ambiente huésped, y a los cuatro setTimeouts le pasamos un callback, estos son, cb1, cb2, cb3 y cb4.  

Los temporizadores setTimeout se ejecutan en la parte de la funcionalidad del ambiente huésped dejando tiempo de ejecución para el call stack. He aquí la concurrencia, mientras el ambiente huésped ejecuta un temporizador, el call stack puede continuar ejecutando código.

Después de los primeros dos segundos, el ambiente huésped, a través del primer setTimeout pasa cb1 al callback queue, pero durante estos dos segundos se pueden realizar otras operaciones en el ambiente huésped, en el caso del navegador, un ejemplo seria que el usuario puede seguir escribiendo dentro de un textarea. De nuevo, he aquí la concurrencia.

Tras el primer setTimeout, el segundo setTimeout pasa cb2 al callback queue y así sucesivamente hasta el cb4. Mientras los callbacks se pasan al callback queue. He event loop nunca deja de funcionar, por lo que en alguna iteración el event Loop pasa cb1 al call stack y se empieza a ejecutar el código de cb1 y esto mismo sucede con cb2, cb3 and cb4.

Event loop en acción

Aquí abajo esta el ejemplo del que hablamos, el temporizador genera los callbacks en el orden que aparecen los setTimeouts más dos segundos. El Event Loop toma un callback en cada iteración, por lo que cada cb de setTimeout se invocan uno después del otro, y no exactamente después de dos segundos, pues entre que se posicionan los callbacks en la cola y se mueven al call stack de ejecución transcurre más tiempo. Esto sin contar el tiempo que trascurre entre cada invocación de setTimeout.

Si en los cuatro callbacks se indica el mismo tiempo en milisegundos. Presiona el botón RERUN, Te darás cuenta de que los tiempos no son iguales y que pueden pasar más de dos segundos.

Conclusion

  1. Las APIs huéspedes reciben callbacks que deben insertar en la callback queue cuando el trabajo que se les encomienda esta hecho, por ejemplo un callback de una petición ajax se pasa a la callback queue solo cuando la petición ya obtuvo la respuesta. En el ejemplo que describimos arriba con setTimeout, cuando pasan dos segundos, se inserta el callback al callback queue.
  2. Mientras el ambiente huésped realiza sus tareas, en este caso, los demás temporizadores, el call stack de ejecución de javascript puede ejecutar el código que el event loop le puede pasar desde el callback queue.
  3. He Event loop es un ciclo infinito que mientras existan callbacks en el callback queue, pasara cada callback, uno por uno, al call stack.
  4. He call stack no puede ejecutar más de un código a la vez, va ejecutando desde el último elemento hasta el primero, en nuestro caso hasta la terminación de la función inicio que dio origen a todo el proceso. Es una estructura de datos tipo Pila.

Gracias a que los callbacks se ejecutan hasta que un trabajo específico esté terminado, proporciona una manera asíncrona de ejecutar tareas. Las tareas pueden realizarse en el ambiente huésped sin afectar la ejecución del call stack. En la pila solo se ejecuta código que recibe el resultado de las tareas realizadas por el ambiente huésped.

¿Cómo empezar con Redux en 7 minutos?

¿Cómo empezar con Redux en 7 minutos?

¿Qué es Redux?

Redux es un contenedor predecible del estado de aplicaciones JavaScript.

Te ayuda a escribir aplicaciones que se comportan de manera consistente, corren en distintos ambientes (cliente, servidor y nativo), y son fáciles de probar. Además de eso, provee una gran experiencia de desarrollo, gracias a edición en vivo combinado con un depurador sobre una línea de tiempo.

redux.org

Te permite controlar el flujo de datos de una aplicación Javascript, este flujo de los datos funciona en una sola dirección. Por esta única dirección es mucho más fácil controlar las mutaciones and operaciones asíncronas.

Redux es parecido a flux, de hecho está basado en flux

En el estado de una aplicación, principalmente en aplicaciones SPA, esto es muy importante, porque las aplicaciones web modernas tienen gran complejidad de operaciones asíncronas. Además de controlar el estado entre los componentes.

¿Qué problemas puedo mitigar con Redux?

En el ejemplo de aplicaciones web, estas necesitan controlar peticiones a servidores, obtener datos y controlar el estado en el cliente. Aun cuando estos datos no han sido guardados en el servidor.

Estas aplicaciones modernas requieren de un control complejo y por eso nuevos patrones de arquitectura como Redux y flux  nacen para hacer el desarrollo más productivo.

Las mutaciones de objetos son difíciles de manejar y más a escalas medianas y grandes. Se comienza a perder el control de los datos, este flujo de datos generan comportamiento no deseados. Mala información desplegada al usuario y código que es muy difícil de mantener.

Sin contar cosas más elevadas como tu salud y causa de estrés por el esfuerzo en arreglar estas inconsistencias, te hace perder tiempo para mantener la aplicación funcionando correctamente. Por si fuera poco afectas a tus usuarios porque ellos obtienen información incorrecta y pierden su tiempo al utilizar esa información.

¿Qué decir de las operaciones asíncronas? Bueno, prácticamente pasa lo mismo o aún peor. Porque en una operación asíncrona no sabes cuando obtendrás el resultado y además normalmente vienen acompañadas con el deseo de hacer modificaciones al estado de la aplicación.

Un ejemplo común es el control de los datos de tu aplicación con cualquier frawework front-end de componentes visuales.

¿De qué está hecho Redux? Tres elementos

Store. El store es un objeto donde guardas toda la información del estado, es como el modelo de una aplicación, con la excepción que no lo puedes modificar directamente, es necesario disparar una acción para modificar el estado.

Actions. Son el medio por el cual indicas que quieres realizar una modificación en el estado, es un mensaje o notificación liviana. Solo enviando la información necesaria para realizar el cambio.

Reducers. Son las funciones que realizan el cambio en el estado o store, lo que hacen internamente es crear un nuevo estado con la información actualizada, de tal manera que los cambios se reflejan inmediatamente en la aplicación. Los reducers son funciones puras, es decir, sin efectos colaterales, no mutan el estado, sino que crean uno con información nueva.

¿Qué principios debo seguir? Tres principios

Un único Store para representar el estado de toda la aplicación. Tener una sola fuente de datos para toda tu aplicación permite tener centralizada la información, evita problemas de comunicación entre componentes para desplegar los datos, fácil de depurar y menos tiempo agregando funcionalidad o detectando errores.

Estado de solo lectura. Esto permite tener el control de cambios y evitar un relajo entre los diferentes componentes de tu aplicación, ni los componentes, ni peticiones ajax pueden modificar directamente el Estado (state) de tu aplicación, esto quiere decir que si quieres actualizar tu estado, debes  hacerlo a través de actions, de esta manera redux se encarga de realizar las actualizaciones de manera estricta y en el orden que le corresponden.

Los cambios solo se hacen con funciones puras. Al realizar los cambios con funciones puras, lo que realmente se hace es crear un nuevo objeto con la información actualizada, estas funciones puras son los reducers y no mutan el estado, al no mutar el estado, se evitan problemas de control, datos incorrectos, mal comportamiento y errores, también permite que la depuración sea más fácil. Puedes dividir los reducer en varios archivos diferentes y las pruebas unitarias son fáciles de implementar. Los reducers son funciones puras que toman el estado anterior y una acción, y devuelven un nuevo estado.

Otras arquitecturas como MVC (Modelo, Vista, Controlador), los cambios pueden existir en ambas direcciones, es decir, la vista puede cambiar el estado, el modelo lo podría modificar y también el controlador. Todos estos cambios necesitan estar sincronizados en varias partes de una aplicación para evitar inconsistencias, lamentablemente este problema de inconsistencia se vuelve muy difícil y tedioso de resolver.

Lo anterior no sucede con Redux.

¿Cómo funciona? Mi primer estado predecible con Redux

Primero veamos el flujo de una sola dirección de redux:

Redux: flujo de control una sola dirección
Redux: flujo de control una sola dirección

Ahora un ejemplo concreto para saber de que estamos hablando, el control de un contador:

See the Pen Redux: Contador State, es5 by Jaime Cervantes Velasco (@jaime_cervantes_ve) on CodePen.

Si quieres probar este ejemplo en tu máquina recuerda insertar o importar la librería Redux. En este ejemplo podemos ver el funcionamiento de Redux, cada vez que se da clic sobre los botones de incrementar y decrementar, el contador se incrementa y decrementa.

Si ahora nos vamos al código JS, podremos ver que solo tenemos una función llamada counter, esta función es un reducer y es una función pura, sin efectos colaterales.

Luego vemos que como parámetros recibe un state y un action, cuando creamos nuestro Store con Redux, estas funciones reducer son utilizadas para modificar el State.

Normalmente, el state, reducer and action son definidos en puntos diferentes, y pueden ser organizados en varios archivos y carpetas dependiendo de la necesidad de la aplicación, toda esta organización tiene la finalidad de tener un código limpio y separar funcionalidades. En este caso sencillo no es necesario, en un solo archivo tenemos todo.

State

Nuestro state es solo un valor numérico, el cual se va a incrementar o decrementar con los botones que están en la página, normalmente el state es un objeto literal o un array literal, pero en nuestro caso solo necesitamos un número. Su definición podría estar en otro archivo, sin embargo, para este ejemplo no es necesario, lo agregamos como valor por defecto del parámetro state.

functions counter(state = 0, action) { ...

Actions

Si seguimos revisando nuestro código, veremos unos cuantas condiciones que revisa el valor del parámetro action y dependiendo de la acción, se ejecuta alguna operación, en nuestro caso son las operaciones INCREMENTAR either DECREMENTAR.

The actions no son más que objetos literales como los siguientes:

const incrementar = { type: 'INCREMENTAR' }
const decrementar = { type: 'DECREMENTAR' }

Reducers

The reducer revisan esos actions, en nuestro ejemplo:

if (action.type === 'INCREMENTAR') {
  return state +  1;
}

if (action.type === 'DECREMENTAR') {
  return state - 1;
}

Con todo esto ya tenemos nuestro State y su estado inicial en caso de no estar definido, también nuestra primer reducer, counter, y nuestros primeros actions INCREMENTAR and DECREMENTAR.

Store

Es el momento de crear nuestro Store, utilizando la librería redux esto es muy fácil:

const store = Redux.createStore(counter);

Con la anterior línea, Redux crea un Store para controlar el estado de nuestra aplicación. Internamente, un Store es un Patrón observador que utiliza un Singleton para el State y expone los siguientes métodos principales:

  • store.getState()
  • store.subscribe(listener)
  • store.dispatch(action)

store.getState() te permite obtener el estado actual de tu aplicación.

store.subscribe(listener) ejecuta la función listener (u observador), cada vez que el store es actualizado.

store.dispatch(action) pide actualizar el estado, esta modificación no es directa, siempre se realiza a través de un action y se ejecuta con un reducer.

Reaccionar a cambios del state

Luego creamos una función render, para que se ejecute cada vez que el State de tu aplicación cambie.

Aquí nuestro contenido html:

<button id="incrementar">Incrementar</button>
<button id="decrementar">Decrementar</button>
<div id="state"></div>

Nuestra función render

functions render () {
  document.querySelector('#state').innerText = store.getState();
}

Invocamos render para pintar el valor 0

render()

Aquí te preguntarás, ¿Cómo es posible que esa línea imprima 0 en la pantalla?, pues internamente el store invoca un dispatch con un action vacío store.dispatch({}), esto invoca nuestra función reducer y al no encontrar ninguna acción, entonces regresa el estado inicial 0.

Luego nos subscribimos a store para escuchar u observar el State cada vez que se actualice y poder ejecutar la función render().

store.subscribe(render);

Esta línea permite que cuando demos clic en los botones de incrementar y decrementar, se imprima el nuevo valor en la página volviendo a renderizar su contenido.

Ejecutar dispatch a través de eventos del DOM

Y por último agregamos dos listeners correspondientes a los botones de incrementar y decrementar, cada botón realiza una invocación dispatch para modificar el estado.

<button id="incrementar">Incrementar</button>
<button id="decrementar">Decrementar</button>
<div id="state"></div>
document.querySelector('#incrementar').addEventListener('click', () => {
  store.dispatch(incrementar);
});

document.querySelector('#decrementar').addEventListener('click', () => {
  store.dispatch(decrementar);
});

Al fin tenemos el flujo de datos de nuestro sencillo ejemplo usando Redux, en general los componentes que forman a una aplicación que utiliza Redux son los siguientes:

Redux: flujo de control completo
Redux: flujo de control completo

Conclusions

Podemos notar el flujo en una sola dirección desde la vista con los actions dispatch(action), luego  los reducers counter(prevState, action) para modificar el store y este último manda la información a través de subscribe(render) and getState().

Redux como ya se mencionó en párrafos anteriores, nos proporciona:

  • El conocimiento en todo momento del estado de nuestra aplicación y en cualquier parte de la aplicación con mucha facilidad.
  • Fácil organización, con actions, reducer y store, haciendo cambios en una sola dirección, además puedes separar tus actions, reducer y el store en varios archivos.
  • Fácil de mantener, debido a su organización y su único store, mantener su funcionamiento y agregar nuevas funcionalidades es muy sencillo.
  • Tiene muy buena documentación, su comunidad es grande y tiene su propia herramienta para debuguear
  • Todos  los puntos anteriores hacen que sea fácil de hacer pruebas unitarias.
  • Y lo más importante, te ahorra tiempo, dinero y esfuerzo xD.
Introducción a programación funcional

Introduction to functional programming

Origin

El origen de la programación funcional data del año 1936, cuando un matemático llamado Alonzo Church necesitaba resolver un problema complejo, del cual no hablaremos aquí, pero Alonzo creó una solución, el lambda calculus. De esta forma nació la programación funcional, incluso mucho antes de la primera computadora digital programable y de los primeros programas escritos en ensamblador.

La programación funcional es mucho más antigua que la programación estructurada y la programación orientada a objetos. Te recomiendo también revisar esta información sobre el paradigma de programación funcional.

Sin efectos colaterales

Todo lo que necesitas saber sobre functional programming es que “No tiene efectos colaterales“, es decir, que sus elementos (funciones) son inmutables.

Lo anterior significa que una función no se mete en lo absoluto con datos que existen fuera de ella, si puede utilizar los datos enviados como parámetros, pero no debe modificarlos, todos los datos deben ser inmutables, ¿Por qué?, pues porque así hacemos las cosas más simples y con menos errores, más adelante tenemos un ejemplo. A este comportamiento se le llama puro.

No side effects nos permite entender todas las demás características de la programación funcional, por mencionar algunas principales:

  • Funciones puras
  • Inmutabilidad
  • Funciones de alto nivel
  • Funciones currificadas
  • Recursividad
  • Menos errores de programación porque no realiza efectos colaterales.

Toda función teniendo ciertos parámetros, cuando se ejecuta, obtendremos un resultado basado en esos parámetros, y si volvemos a utilizar los mismos parametros, entonces la función regresara el mismo valor. Esto es debido a que una función no depende de más datos externos que puedan ser modificados, así tendremos más seguridad y nuestro código se vuelve más entendible.

Javascript es un lenguaje de programación muy potente y multiparadigma, soporta el paradigma funcional y lo utilizaremos para nuestros ejemplos.

Funciones puras e inmutabilidad

Bueno, realmente ya explicamos de manera indirecta que es una función pura en los párrafos anteriores, pero veamos una definición formal. Una función pura es la que cumple con estas dos características:

  1. Siempre obtendremos el mismo resultado dado los mismos parámetros de entrada.
  2. No tiene ningún efecto colateral observable, no modifica el estado de los datos externos, por lo que todos los datos deben ser inmutables.

Un ejemplo de como cambiar el nombre de una objeto persona usando primero una función con efector colaterales:

functions cambiarNombre(name) {
  person.name = name;
}
const James = { name: 'Jaime', edad: 30 };
cambiarNombre('Juan')
console.log(jaime); // { nombre: 'Juan', edad: 30 }

En la anterior función notamos que se cambia objeto James, el cual supongamos que es parte del estado de nuestra aplicación, pero puede haber otras funciones que utilicen este objeto, por lo que se puede generar problemas si alguien más espera que la propiedad name del objeto siga siendo 'jaime'.

Ahora veamos la versión funcional de la función:

functions cambiarNombre(name, person) {
  return {
    name: name,
    edad: person.edad
  }
}
const James = { name: 'Jaime', edad: 30 };
const juan = cambiarNombre('Juan', jaime);
console.log(jaime); // { nombre: 'Jaime', edad: 30 }
console.log(juan); // { nombre: 'Juan', edad: 30 }

En la versión funcional, cambiarNombre no modifica el objeto James, más bien crea un nuevo objeto con la misma edad que James y con la propiedad name equal to 'Juan', con esto evitamos efectos colaterales por si el objeto James es utilizado por otra función u otro programador.

Con esta función sin efecto colateral, nos damos cuenta de que los datos se manejan sin ser modificados, es decir, inmutables, los parámetros person and name nunca fueron cambiados.

Funciones de alto nivel y currificadas

Una función de alto nivel es una función que implementa al menos una de las opciones siguientes:

  • Recibir como parámetro una o más funciones
  • Regresar como resultado una función

Un ejemplo muy común usado en nuestro navegador web es agregar escuchadores de eventos:

<button id="boton">Soy un botón</button>
const boton = document.querySelector('#boton');
boton.addEventListener('click', functions () {
  alert('Click sobre el boton');
});

En el código pasamos como segundo parámetro del método addEventListener una función anónima (sin nombre) que mostrará un alerta al dar click sobre un botón con id igual a ‘botón’. Dado que pasamos por parámetro una función, entonces se dice que es una función de alto nivel.

Otro ejemplo de función de alto nivel lo podemos observar en los métodos de arreglos en Javascript, el código de abajo toma un arreglo de números y crea otro arreglo con los valores aumentados al doble.

See the Pen Funciones de alto nivel by Jaime Cervantes Velasco (@jaime_cervantes_ve) on CodePen.

The function map retorna un nuevo arreglo, no cambia el arreglo original, por lo que decimos que no existe un efecto colateral.

Las funciones currificadas son funciones de alto nivel que como resultado regresan otra función, de tal manera que el acto de currificar es convertir una función de más de un parámetro en dos o más funciones que reciben parcialmente esos parámetros en dos o más invocaciones currificadas.

See the Pen Funciones de alto nivel y funciones currificadas by Jaime Cervantes Velasco (@jaime_cervantes_ve) on CodePen.

Las funciones flecha o arrow functions nos permiten acceder al contexto de los parámetros, es por eso que seguimos teniendo acceso al parámetro to de la primera invocación de summaryCurry. De esta manera cuando se les define un valor, una arrow function puede ver ese valor. Para lograr lo mismo sin funciones flecha se debe utilizar la variable arguments que existe como variable local dentro de todas las funciones en JavaScript. Para mantener las cosas simples, de momento no veremos como hacerlo con arguments.

Función recursiva

Para crear una función recursiva, primero se define un caso base, luego a través de la división del problema en pedazos más pequeños se encuentra un patrón, este patrón llamado caso recursivo se repite muchas veces, es aquí donde la función se llama así misma y acumula los resultados, la ejecución se detiene hasta llegar a su caso base.

  1. El caso base, el cual permite detener la ejecución de subsecuentes invocaciones de la función recursiva.
  2. El caso recursivo, el cual permite que una función se llame a sí misma hasta llegar al caso base.

El factorial de un número positivo es la multiplicación de ese número por el número inmediato menor y así sucesivamente hasta llegar al número 1, su notación es n!, donde n es un número positivo. Por ejemplo el factorial de 5 is 120, 5! = 5 x 4 x 3 x 2 x 1 = 120.

// caso base:
1! = 1 = 1
// caso recursivo, ejemplos:
2! = 2 x 1 = 2 x 1!
3! = 3 x 2 x 1 = 3 x 2!
4! = 4 x 3 x 2 x 1 = 4 x 3!
5! = 5 x 4 x 3 x 2 x 1 = 5 x 4!

Con estos datos, podemos crear nuestra formula factorial(n) = n * factorial(n-1), lo cual seria nuestro caso recursivo, pero debemos de añadir nuestro caso base para que se detenga, cuando n=1 debemos obtener como resultado 1.

Veamos como quedaría nuestra función recursiva en javascript:

See the Pen Funciones recursivas by Jaime Cervantes Velasco (@jaime_cervantes_ve) on CodePen.

Con esto cubrimos las cualidades principales de la programación funcional, pero recuerda, lo más importante es que NO existen efectos colaterales.

Patrón de diseño observador en Javascript

Patrón de diseño observador en Javascript

¿Qué es el patrón de diseño observador?

El patrón de diseño observador, define una dependencia de uno a muchos objetos de tal manera que cuando un objeto cambio de estado, todos sus dependientes son notificados y actualizados automáticamente

Del libro “Design patterns: elements of reusable object-oriented software”

Si aún no sabes que es un patrón de diseño, revisa primero esta publicación sobre patrones de diseño.

Si has utilizado eventos del navegador, como escuchar el evento click sobre un botón, ahí estás utilizando el patrón observador, tu función callback es tu objeto observador y el botón es el sujeto, tu función callback esta interesada en la actividad de dar click sobre el botón.

Se compone de un Sujeto y uno o más Observadores. Veamos el diagrama tomado del libro Design Patterns: Elements of reusable Object-Oriented software:

Patrón de diseño observador
Patrón de diseño observador

He Sujeto está compuesto por las siguientes métodos importantes que usaremos en nuestro código javascript:

  • Una colección de observers
  • Método attach()
  • Método detach()
  • Método notify()

Normalmente un Observador contiene un método update() que el Sujeto utiliza.

Para tener más claro esto, vamos a ver dos ejemplos del patrón observador, el primero será el Observador puro y el segundo en su modo Publicador/Suscriptor.

Simplificando el observador

Simplificando el diagrama anterior, el patrón observador funciona así:

Patrón de diseño observador simplificado
Patrón de diseño observador simplificado

Juega con el ejemplo de abajo, y agrega nuevos checkbox, si has agregado más de un nuevo checkbox, podemos notar que cuando damos click en el checkbox ‘Seleccionar‘ todos los demás checkbox nuevos se enteran de esa actividad y se actualizan automáticamente.

Todo esto sin necesidad de estar al pendiente de que el checkbox ‘seleccionar‘ ha cambiado su estado, el encargado de notificar del cambio es el Sujeto y solo si existe algún cambio. Esto es muy eficiente si tienes cientos o miles de checkbox observando ese cambio.

Si das click sobre uno de los checkbox, se ejecuta el método subject.detach(), entonces ese checkbox ya no es un observador, por lo que si ahora activas y desactivas el checkbox seleccionar nunca es notificado sobre el cambio.

Publicador/suscriptor simple

El patrón de diseño publicador/suscriptor es una variación del observador, en este modo el suscriptor u observador se suscribe a una actividad o evento del publicador o sujeto.

He publicador notifica a todos los objetos suscritos cuando el evento al que están interesados se dispara o publica.

He publicador está compuesto por las siguientes métodos importantes que usaremos en nuestro código javascript:

  • Una colección de observers either subscribers
  • Método subscribe() either attach()
  • Método unsubscribe() either detach()
  • Método publish() either notify()

Aquí dejo el diagrama simple de como funciona esta versión:

Patrón de diseño publicador/suscriptor simplificado
Patrón de diseño publicador/suscriptor simplificado

He publicador/suscriptor se parece más a los eventos del DOM y a eventos personalizados, pero no deja de ser el patrón de diseño Observador. Ademas, como observadores, podemos suscribirnos a más de una actividad o evento.

En el ejemplo, el método suscribe agrega la función observadora, esta última se ejecuta cuando la actividad click es publicada.

publisherSeleccionar.subscribe('check', subscriberCheckbox.update, subscriberCheckbox);

En conclusión, el patrón de diseño observador es muy útil, se puede modificar o adecuarlo a ciertas necesidades, un ejemplo es la variacion publicador/suscriptor. Se usa en:

  • ReactveX.
  • Librerias y frameworks de componentes web tales como angular, react, lit, vue, svelte utilizan este patrón para su bindeo de datos.
  • Navegadores web cuando usamos eventos
  • Node.js cuando utilizamos EventEmitter al recibir una petición a nuestro servidor o al leer un archivo del disco duro.
  • Flux y redux para manejar cambios en el estado de nuestra aplicación.
¿Cómo crear un servidor web en 5 minutos con Node.js?

¿Cómo crear un servidor web en 5 minutos con Node.js?

Para crear un servidor web en node.js, primero, ¿Qué es node.js?, tomando la definición del sitio oficial, Node.js® es un entorno de ejecución para JavaScript construido con el motor de JavaScript V8 de Chrome. Node.js usa un modelo de operaciones E/S sin bloqueo y orientado a eventos, que lo hace liviano y eficiente. El ecosistema de paquetes de Node.js, npm, es el ecosistema más grande de librerías de código abierto en el mundo.

Vamos a describir la parte que nos interesa, Node.js es un programa, V8 es un motor de javascript de código abierto creado por Google, por lo que también lo hace un programa, V8 está escrito en C++, y la tarea de V8 es tomar código Javascript y convertirlo a código máquina (compilar código), pero lo que lo hace especial para nuestros fines es que puede ser embebido dentro de otros programas, lo que permite que V8 esté embebido en Node.js, V8 por así decirlo es el punto de partida para toda la funcionalidad de Node.js.

Node.js también está escrito en C++ y utiliza la API de V8 para agregarle características y funcionalidades nuevas a Javascript. Estas nuevas funcionalidades permiten tener acceso al sistema de archivos y carpetas, nos permite crear un servidor TCP y http, además de acceso a POSIX, o sea, a toda la funcionalidad del sistema operativo donde se encuentre instalado.

Node.js proporciona la sintaxis Javascript para crear programas que tengan acceso a las características del sistema operativo donde sé está ejecutando.

Con esto podemos razonar que con Node.js podemos crear un servidor web, para crearlo, vamos a utilizar NPM (Node Package Manager) y express.js un frawework web.

Vamos a crear una nueva carpeta llamada mi-servidor-web, luego accede a esta carpeta con:

$ cd mi-servidor-web

Ahora vamos a iniciar el proyecto utilizando el siguiente comando:

$ npm init

La línea de comandos nos pedirá algunos datos, puedes dar “enter” a todos si quieres, te muestro un ejemplo:

Press ^C at any time to quit.
package name: (mi-servidor-web)
version: (1.0.0)
description: Mi primer servidor web
entry point: (index.js)
test command:
git repository:
keywords:
author: Jaime Cervantes<James.cervantes.ve@gmail.com>
license: (ISC)
About to write to /home/James/develop/node.js/mi-servidor-web/package.json:
{
  "name": "mi-servidor-web",
  "version": "1.0.0",
  "description": "Mi primer servidor web",
  "main": "server.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "Jaime Cervantes <jaime.cervantes.ve@gmail.com>",
  "license": "ISC"
}
Is this ok? (yes)

npm init nos genera un archivo package.json:

{
  "name": "mi-servidor-web",
  "version": "1.0.0",
  "description": "Mi primer servidor web",
  "main": "server.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "Jaime Cervantes <jaime.cervantes.ve@gmail.com>",
  "license": "ISC"
}

Este archivo contiene la información anteriormente proporcionada y además se encarga de controlar los paquetes que instalamos para nuestro proyecto. Por ejemplo, para poder crear nuestro servidor rápidamente, vamos a instalar un paquete llamado express.js de la siguiente manera:

$ npm install express --save

Este comando instala express.js y además actualiza nuestro archivo package.json gracias al parámetro --save en la propiedad dependencies:

{
  "name": "mi-servidor-web",
  "version": "1.0.0",
  "description": "Mi primer servidor web",
  "main": "server.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "Jaime Cervantes <jaime.cervantes.ve@gmail.com>",
  "license": "ISC",
  "dependencies": {
    "express": "^4.16.2"
  }
}

Ya teniendo express instalado, vamos a crear nuestro servidor web creando el archivo  ./mi-servidor-web/index.js:

const express = require('express');
const app = express();
app.use(express.static(__dirname + '/public/'));
app.listen('3000', functions() {
  console.log('Servidor web escuchando en el puerto 3000');
});

Hay una parte importante que nos permitirá ver el funcionamiento de nuestro servidor web:

app.use(express.static(__dirname + '/public/'));

Esta línea le indica a nuestro servidor que cuando un usuario haga una petición de archivos estáticos, por ejemplo, http://localhost:300/index.html enviará como respuesta el contenido de ./public/index.html.

Vamos a crear la carpeta public y el archivo index.html con el editor de nuestro preferencia o en línea de comandos si lo deseas. Agregamos el siguiente contenido a nuestro archivo index.html:

<!DOCTYPE html>
<html lang="is">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Mi primer servidor web</title>
</head>
<body>
  <h1>HOLA, mi primer servidor web</h1>
</body>
</html>

Para ejecutar nuestro servidor nos posicionamos dentro de nuestra carpeta mi-servidor-web y ejecutamos el siguiente comando:

$ node index.js;

Veremos este mensaje en nuestra consola:

Servidor web escuchando en el puerto 3000

Por último abrimos nuestro navegador web y obtendremos nuestro index.html como la imagen de abajo, utilizando http://localhost:3000 either http://localhost:3000/index.html:

¿Cómo se usan los patrones glob de la shell de linux en Javascript?

¿Cómo se usan los patrones glob de la shell de linux en Javascript?

¿Qué son los patrones glob?

En Javascript se utiliza mucho los Patrones Glob, estos permiten seleccionar un número de archivos con una sintaxis parecida a las expresiones regulares pero con menos caracteres comodín y menor complejidad. Un carácter comodín es él * o el signo de ?.

Una gran diferencia entre expresiones regulares es que los patrones glob se ocupan para buscar y filtrar archivos, y las expresiones regulares funcionan con cadenas de texto.

  1. Expresiones regulares trabaja con Texto
  2. Glob trabaja con archivos/directorios

¿Origen?

Tienen su origen en las primeras versiones de Unix, durante la versión 6 para ser exacto, 1969-1975, era el programa /etc/glob, se usaba para seleccionar un conjunto de archivos en la shell, se llamaba glob por ser la abreviación de global.

¿Cómo se usan?

También la funcionalidad es un poco diferente, por ejemplo el * en una expresión regular coincide con la ausencia o cualquier número de repeticiones del carácter que le precede.

Por ejemplo a*, indica cero o más repeticiones de la letra to.

Otro ejemplo con carácter especial es .* el cual indica cero o más repeticiones de cualquier carácter, excepto carácter de nueva de línea.

Por otro lado el carácter * en un patrón glob representa la ausencia o cualquier número de repeticiones de cualquier carácter.

El ejemplo más utilizado es cuando queremos listar archivos con una determinada extensión, por ejemplo:

/$ ls *.js

Muy similar con lo que hacemos en el MS-DOS de windows:

C:\> dir *.js

No es necesario un carácter antes del *, como sucede con las expresiones regulares.

Aquí abajo un ejemplo donde tenemos un archivo de configuración de jasmine, Jasmine es un framework para realizar pruebas a tu código Javascript, este archivo de configuración permite seleccionar que archivos se usarán para ejecutar las pruebas:

{
  "spec_dir": "spec",
  "spec_files": [
    "**/*[sS]pec.js"
  ],
  "helpers": [
    "helpers/**/*.js"
  ],
  "stopSpecOnExpectationFailure": false,
  "random": false
}

Algo que destacar es el uso de doble asterisco **, esto indica cero o más coincidencias de cualquier subdirectorio y archivo, es decir, cero o más niveles de subdirectorios.

También podemos notar el uso de [sS], esta notación de glob indica que acepta sola una vez ya sea la sminúscula o la Smayúscula.

En el arreglo spec_files, su primer elemento es un patrón glob, el cual busca en cualquier subdirectorio relativo al directorio definido en spec_diry que tenga cualquier conjunto de letras al principio pero que terminen con spec.jseither Spec.js. Esta definición podría obtener las siguientes rutas de archivos:

  • /spec/nombre-archivo.spec.js
  • /spec/nombre-archivo.Spec.js
  • /spec/helpers/nombre-archivo.spec.js
  • /spec/helpers/nombre-archivo.Spec.js
  • /spec/esto/es/otra/ruta/nombre-archivo.spec.js
  • /spec/esto/es/otra/ruta/nombre-archivo.Spec.js

¿Dónde se utilizan?

En Javascript se utiliza:

  1. Para automatizar tareas que necesitan de la lectura y escritura de archivos
  2. Se utiliza mucho en node.js con herramientas como gulp y webpack
  3. Automatizado de pruebas
  4. Minificado y concatenado para el código en producción.
¿Cómo implementar el patrón de diseño Iterator(Iterador) en Javascript?

¿Cómo implementar el patrón de diseño Iterator(Iterador) en Javascript?

El patrón de diseño iterador either iterator proporciona una manera de acceder a elementos de un objeto (que contiene algún tipo de datos agregados como un arreglo o una lista) secuencialmente sin exponer su estructura interna.

Cita original de Design Patterns: Elements of Reusable Object-Oriented Software por GoF:

Provide a way to access the elements of an aggregate object sequentially without exposing its underlying representation.

Este patrón de diseño también es conocido como cursor, si has usado cursores para recorrer los elementos obtenidos de una base de datos, ¿Que crees?, ahí estas utilizando el patrón de diseño iterador.

El objetivo de este patrón es poder recorrer y obtener elementos de un objeto sin necesidad de saber como estos datos están estructurados. Además de que la responsabilidad de recorrer los elementos no está en el objeto sino en el iterador.

Un iterador se compone normalmente de los siguientes métodos:

  • iterador.hasNext() either iterador.hayMas()
  • iterador.next() either iterador.siguiente()
  • iterador.current() either iterador.elementoActual()
  • iterador.rewind() either iterador.rebobinar(), que nos permite posicionar el “cursor” en el primer elemento.

Aquí te dejo como implementarlo en un navegador web:

Podemos notar que el siguiente elemento está determinado por la función iterador.next() el cual suma 2 a la variable index y es por eso que obtenemos los valores 1,3,5,7,9 del arreglo data.

Al final rebobinamos al inicio de data e imprimimos el elemento actual, es decir 1, con el método iterador.current().

MongoDB es una base de datos basada en documentos en formato BJSON que es la forma binaria de JSON, en MongoShell se puede ver el uso de este patrón de diseño:

const cursor = db.users.find( { type: 2 } );
while (cursor.hasNext()) {
  imprimirDocumento(cursor.next());
}

En este ejemplo se obtienen los documentos de la colección users que tengan una propiedad type equal to 2, luego se recorren uno por uno a través de los métodos cursor.hasNext()and cursor.next().

en_USEN