Skip to content

Methods of primitives #105

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

Try running it:
Prueba a ejecutar:

```js run
let str = "Hello";
Expand All @@ -9,23 +9,16 @@ str.test = 5; // (*)
alert(str.test);
```

There may be two kinds of result:
1. `undefined`
2. An error.
Dependiendo del uso o no del modo estricto "use strict", el resultado puede ser:
1. `undefined` (sin strict mode)
2. Un error (strict mode)

Why? Let's replay what's happening at line `(*)`:
¿Por qué? Repasemos qué ocurre en la línea `(*)`:

1. When a property of `str` is accessed, a "wrapper object" is created.
2. The operation with the property is carried out on it. So, the object gets the `test` property.
3. The operation finishes and the "wrapper object" disappears.
1. Cuando se accede a una propiedad de `str`, un "wrapper object" es creado.
2. Con modo estricto, alterarlo produce error.
3. De otra manera, la operación es llevada a cabo y el objeto obtiene la propiedad `test`, pero después de ello el "wrapper object" desaparece, entonces en la última linea `str` queda sin rastros de la propiedad.

So, on the last line, `str` has no trace of the property. A new wrapper object for every object operation on a string.

Some browsers though may decide to further limit the programmer and disallow to assign properties to primitives at all. That's why in practice we can also see errors at line `(*)`. It's a little bit farther from the specification though.

**This example clearly shows that primitives are not objects.**

They just can not store data.

All property/method operations are performed with the help of temporary objects.
**Este ejemlplo claramente muestra que los tipos primitivos no son objetos.**

Ellos no pueden almacenar datos adicionales.
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@ importance: 5

---

# Can I add a string property?
# ¿Puedo agregar un propiedad a un string?


Consider the following code:
Considera el siguiente código:

```js
let str = "Hello";

str.test = 5;
str.test = 5;

alert(str.test);
```

How do you think, will it work? What will be shown?
Qué piensas, ¿funcionará? ¿Qué mostrará?
100 changes: 49 additions & 51 deletions 1-js/05-data-types/01-primitives-methods/article.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,20 @@
# Methods of primitives
# Métodos en datos primitivos

JavaScript allows us to work with primitives (strings, numbers, etc.) as if they were objects.
JavaScript nos permite trabajar con datos primitivos (strings, numbers, etc.) como si fueran objetos. Ellos también proveen métodos para ser llamados como tales. Los estudiaremos pronto, pero primero veamos cómo trabajan porque, por supuesto, los primitivos no son objetos (y aquí lo haremos más evidente).

They also provide methods to call as such. We will study those soon, but first we'll see how it works because, of course, primitives are not objects (and here we will make it even clearer).
Veamos las principales diferencias entre primitivos y objetos.

Let's look at the key distinctions between primitives and objects.
Un primitivo

A primitive
- Es un valor de tipo primitivo.
- Hay 6 tipos primitivos: `string`, `number`, `boolean`, `symbol`, `null` y `undefined`.

- Is a value of a primitive type.
- There are 6 primitive types: `string`, `number`, `boolean`, `symbol`, `null` and `undefined`.
Un objeto

An object
- Es capaz de almacenar múltiples valores como propiedades.
- Puede ser creado con `{}`, por ejemplo: `{name: "John", age: 30}`. Hay otros tipos de objetos en JavaScript; por ejemplo, las funciones son objetos.

- Is capable of storing multiple values as properties.
- Can be created with `{}`, for instance: `{name: "John", age: 30}`. There are other kinds of objects in JavaScript; functions, for example, are objects.

One of the best things about objects is that we can store a function as one of its properties.
Una de las mejores cosas de los objetos es que podemos almacenar una función como una de sus propiedades.

```js run
let john = {
Expand All @@ -29,102 +27,102 @@ let john = {
john.sayHi(); // Hi buddy!
```

So here we've made an object `john` with the method `sayHi`.
Aquí hemos hecho un función `john` con el método `sayHi`(saludar).

Many built-in objects already exist, such as those that work with dates, errors, HTML elements, etc. They have different properties and methods.
Ya existen muchos objetos incorporados, como aquellos que trabajan con fechas, errores, elementos HTML, etc. Ellos tienen diferentes propiedades y métodos.

But, these features come with a cost!
¡Pero estas características vienen con un costo!

Objects are "heavier" than primitives. They require additional resources to support the internal machinery. But as properties and methods are very useful in programming, JavaScript engines try to optimize them to reduce the additional burden.
Los objetos son más "pesados" que los tipos primitivos. Requieren recursos adicionales para soportar su maquinaria interna.

## A primitive as an object
## Un primitivo como objeto

Here's the paradox faced by the creator of JavaScript:
Aquí la paradoja que enfrentó el creador de JavaScript:

- There are many things one would want to do with a primitive like a string or a number. It would be great to access them as methods.
- Primitives must be as fast and lightweight as possible.
- Hay muchas cosas que uno quisiera hacer con primitivos como string o number. Sería grandioso accederlas como métodos.
- Los Primitivos deben ser tan rápidos y livianos como sea posible.

The solution looks a little bit awkward, but here it is:
La solución es algo enrevesada, pero aquí está:

1. Primitives are still primitive. A single value, as desired.
2. The language allows access to methods and properties of strings, numbers, booleans and symbols.
3. When this happens, a special "object wrapper" that provides the extra functionality is created, and then is destroyed.
1. Los primitivos siguen siendo primitivos. Con un valor único, como es deseable.
2. El lenguaje permite acceder a métodos y propiedades de strings, numbers, booleans y symbols.
3. Para que esto funcione, un "object wrapper" (objeto envoltura) especial que provee la funcionalidad extra es creado, y luego destruido.

The "object wrappers" are different for each primitive type and are called: `String`, `Number`, `Boolean` and `Symbol`. Thus, they provide different sets of methods.
Los "object wrappers" son diferentes para cada tipo primitivo y son llamados: `String`, `Number`, `Boolean` y `Symbol`. Así, proveen diferentes sets de métodos.

For instance, there exists a method [str.toUpperCase()](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/String/toUpperCase) that returns a capitalized string.
Por ejemplo, hay un método [str.toUpperCase()](https://developer.mozilla.org/es/docs/Web/JavaScript/Referencia/Objetos_globales/String/toUpperCase) que devuelve un string en mayúsculas.

Here's how it works:
Aquí cómo funciona:

```js run
let str = "Hello";

alert( str.toUpperCase() ); // HELLO
```

Simple, right? Here's what actually happens in `str.toUpperCase()`:
Simple, ¿no es así? Lo que realmente ocurre en `str.toUpperCase()`:

1. The string `str` is a primitive. So in the moment of accessing its property, a special object is created that knows the value of the string, and has useful methods, like `toUpperCase()`.
2. That method runs and returns a new string (shown by `alert`).
3. The special object is destroyed, leaving the primitive `str` alone.
1. El string `str` es un tipo primitivo. Entonces al momento de acceder a su propiedad, un objeto especial es creado, uno que conoce el valor del string y tiene métodos útiles como `toUpperCase()`.
2. El método se ejecuta y devuelve un nuevo string (el mostrado con `alert`).
3. El objeto especial es destruido, dejando solo el primitivo `str`.

So primitives can provide methods, but they still remain lightweight.
Así las primitivas pueden proporcionar métodos y aún permanecer livianas.

The JavaScript engine highly optimizes this process. It may even skip the creation of the extra object at all. But it must still adhere to the specification and behave as if it creates one.
El motor JavaScript optimiza este proceso enormemente. Puede incluso saltear la creación del objeto extra por completo. Pero aún debe adherir a la especificación y comportarse como si creara uno.

A number has methods of its own, for instance, [toFixed(n)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed) rounds the number to the given precision:
Un number tiene sus propios métodos, por ejemplo [toFixed(n)](https://developer.mozilla.org/es/docs/Web/JavaScript/Referencia/Objetos_globales/Number/toFixed) redondea el número a la precisión dada:

```js run
let n = 1.23456;

alert( n.toFixed(2) ); // 1.23
```

We'll see more specific methods in chapters <info:number> and <info:string>.
Veremos más métodos específicos en los capítulos <info:number> y <info:string>.


````warn header="Constructors `String/Number/Boolean` are for internal use only"
Some languages like Java allow us to create "wrapper objects" for primitives explicitly using a syntax like `new Number(1)` or `new Boolean(false)`.
````warn header="Los class constructor `String/Number/Boolean` son de uso interno solamente"
Algunos lenguajes como Java nos permiten crear explícitamente "wrapper objects" para primitivas usando una sintaxis como `new Number(1)` o `new Boolean(false)`.

In JavaScript, that's also possible for historical reasons, but highly **unrecommended**. Things will go crazy in several places.
En JavaScript, eso también es posible por razones históricas, pero firmemente **desaconsejado**. Las cosas enloquecerán en varios lugares.

For instance:
Por ejemplo:

```js run
alert( typeof 1 ); // "number"

alert( typeof new Number(1) ); // "object"!
```

And because what follows, `zero`, is an object, the alert will show up:
Los objetos son siempre verdaderos en un `if`, por ello el alert se mostrará:

```js run
let zero = new Number(0);

if (zero) { // zero is true, because it's an object
alert( "zero is truthy?!?" );
if (zero) { // zero es true, porque es un objeto
alert( "¡zero es verdadero!?" );
}
```

On the other hand, using the same functions `String/Number/Boolean` without `new` is a totally sane and useful thing. They convert a value to the corresponding type: to a string, a number, or a boolean (primitive).
Por otro lado, usar las mismas funciones `String/Number/Boolean` sin `new` es totalmente sano y útil. Ellos convierten un valor al tipo correspondiente: a un string, un number o un boolean (primitivos).

For example, this is entirely valid:
Por ejemplo, esto es perfectamente válido:
```js
let num = Number("123"); // convert a string to number
let num = Number("123"); // convierte string a number
```
````


````warn header="null/undefined have no methods"
The special primitives `null` and `undefined` are exceptions. They have no corresponding "wrapper objects" and provide no methods. In a sense, they are "the most primitive".
````warn header="null/undefined no tienen métodos"
Las primitivas especiales `null` y `undefined` son excepciones. No tienen los "wrapper objects" correspondientes y no proporcionan métodos. En ese sentido son "lo más primitivo".

An attempt to access a property of such value would give the error:
El intento de acceder a una propiedad de tal valor daría error:

```js run
alert(null.test); // error
````

## Summary
## Resumen

- Primitives except `null` and `undefined` provide many helpful methods. We will study those in the upcoming chapters.
- Formally, these methods work via temporary objects, but JavaScript engines are well tuned to optimize that internally, so they are not expensive to call.
- Los tipos primitivos excepto `null` y `undefined` proporcionan muchos métodos útiles. Los estudiaremos en los próximos capítulos.
- Oficialmente, estos métodos trabajan a través de objetos temporales, pero los motores de JavaScript están bien afinados para optimizar esto internamente así que llamarlos no es costoso.
8 changes: 4 additions & 4 deletions 1-js/05-data-types/02-number/1-sum-interface/solution.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@


```js run demo
let a = +prompt("The first number?", "");
let b = +prompt("The second number?", "");
let a = +prompt("¿Primer número?", "");
let b = +prompt("¿Segundo número?", "");

alert( a + b );
```

Note the unary plus `+` before `prompt`. It immediately converts the value to a number.
Observa el más unario `+` antes del `prompt`. Este de inmediato convierte el valor a número.

Otherwise, `a` and `b` would be string their sum would be their concatenation, that is: `"1" + "2" = "12"`.
De otra manera, `a` and `b` serían string y la suma su concatenación: `"1" + "2" = "12"`.
6 changes: 3 additions & 3 deletions 1-js/05-data-types/02-number/1-sum-interface/task.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ importance: 5

---

# Sum numbers from the visitor
# Suma números para el visitante

Create a script that prompts the visitor to enter two numbers and then shows their sum.
Crea un script que pida al visitante que ingrese dos números y muestra su suma.

[demo]

P.S. There is a gotcha with types.
P.D. Hay una triquiñuela con los tipos.
18 changes: 9 additions & 9 deletions 1-js/05-data-types/02-number/2-why-rounded-down/solution.md
Original file line number Diff line number Diff line change
@@ -1,33 +1,33 @@
Internally the decimal fraction `6.35` is an endless binary. As always in such cases, it is stored with a precision loss.
Internamente la fracción decimal de `6.35` es binario sin fin. Como siempre en estos casos, es almacenado con pérdida de precisión.

Let's see:
Veamos:

```js run
alert( 6.35.toFixed(20) ); // 6.34999999999999964473
```

The precision loss can cause both increase and decrease of a number. In this particular case the number becomes a tiny bit less, that's why it rounded down.
La pérdida de precisión puede causar que el número incremente o decremente. En este caso particular el número se vuelve ligeramente menor, por ello es redondeado hacia abajo.

And what's for `1.35`?
¿Y qué pasa con `1.35`?

```js run
alert( 1.35.toFixed(20) ); // 1.35000000000000008882
```

Here the precision loss made the number a little bit greater, so it rounded up.
Aquí la pérdida de precisión hace el número algo mayor, por ello redondea hacia arriba.

**How can we fix the problem with `6.35` if we want it to be rounded the right way?**
**¿Cómo podemos arreglar el problema con `6.35` si queremos redondearlo de manera correcta?**

We should bring it closer to an integer prior to rounding:
Debemos llevarlo más cerca de un entero antes del redondeo:

```js run
alert( (6.35 * 10).toFixed(20) ); // 63.50000000000000000000
```

Note that `63.5` has no precision loss at all. That's because the decimal part `0.5` is actually `1/2`. Fractions divided by powers of `2` are exactly represented in the binary system, now we can round it:
observa que `63.5` no tiene pérdida de precisión en absoluto. Esto es porque la parte decimal `0.5` es realmente `1/2`. Fracciones divididas por potencias de `2` son representadas exactamente en el sistema binario, ahora podemos redondearlo:


```js run
alert( Math.round(6.35 * 10) / 10); // 6.35 -> 63.5 -> 64(rounded) -> 6.4
alert( Math.round(6.35 * 10) / 10); // 6.35 -> 63.5 -> 64(redondeado) -> 6.4
```

10 changes: 5 additions & 5 deletions 1-js/05-data-types/02-number/2-why-rounded-down/task.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,21 @@ importance: 4

---

# Why 6.35.toFixed(1) == 6.3?
# ¿Por qué 6.35.toFixed(1) == 6.3?

According to the documentation `Math.round` and `toFixed` both round to the nearest number: `0..4` lead down while `5..9` lead up.
De acuerdo a la documentación `Math.round` y `toFixed` redondean al número más cercano: `0..4` hacia abajo mientras `5..9` hacia arriba.

For instance:
Por ejemplo:

```js run
alert( 1.35.toFixed(1) ); // 1.4
```

In the similar example below, why is `6.35` rounded to `6.3`, not `6.4`?
En el ejemplo similar que sigue, por qué `6.35` es redondeado a `6.3`, no a `6.4`?

```js run
alert( 6.35.toFixed(1) ); // 6.3
```

How to round `6.35` the right way?
¿Como redondear `6.35` de manera correcta?

Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ function readNumber() {
alert(`Read: ${readNumber()}`);
```

The solution is a little bit more intricate that it could be because we need to handle `null`/empty lines.
La solución es un poco más intrincada de lo que podría porque necesitamos manejar `null`/líneas vacías.

So we actually accept the input until it is a "regular number". Both `null` (cancel) and empty line also fit that condition, because in numeric form they are `0`.
Entonces pedimos ingresos hasta que sea un "número regular". Tanto `null` (cancel) como las líneas vacías encajan en esa condición porque un su forma numérica estos son `0`.

After we stopped, we need to treat `null` and empty line specially (return `null`), because converting them to a number would return `0`.
Una vez detenido el ingreso, necesitamos tratar especialmente los casos `null` y línea vacía (return `null`), porque convertirlos devolverían `0`.

8 changes: 4 additions & 4 deletions 1-js/05-data-types/02-number/3-repeat-until-number/task.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ importance: 5

---

# Repeat until the input is a number
# Repetir hasta que lo ingresado sea un número

Create a function `readNumber` which prompts for a number until the visitor enters a valid numeric value.
Crea una función `readNumber` que pida un número hasta que el visitante ingrese un valor numérico válido.

The resulting value must be returned as a number.
El valor resultante debe ser devuelto como número.

The visitor can also stop the process by entering an empty line or pressing "CANCEL". In that case, the function should return `null`.
El visitante puede también detener el proceso ingresando una linea vacía o presionando "CANCEL". En tal caso la funcion debe devolver `null`.

[demo]

10 changes: 5 additions & 5 deletions 1-js/05-data-types/02-number/4-endless-loop-error/solution.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
That's because `i` would never equal `10`.
Es porque `i` nunca será igual a `10`.

Run it to see the *real* values of `i`:
Ejecuta esto para ver los *reales* valores de `i`:

```js run
let i = 0;
Expand All @@ -10,8 +10,8 @@ while (i < 11) {
}
```

None of them is exactly `10`.
Ninguno de ellos es exactamente `10`.

Such things happen because of the precision losses when adding fractions like `0.2`.
Tales cosas suceden por las pérdidas de precisión cuando sumamos decimales como `0.2`.

Conclusion: evade equality checks when working with decimal fractions.
Conclusión: evita chequeos de igualdad al trabajar con números decimales.
Loading
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy