refactor
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 44 KiB |
Before Width: | Height: | Size: 8.3 KiB After Width: | Height: | Size: 8.3 KiB |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
242
1-js/2-first-steps/05-types/article.md
Normal file
|
@ -0,0 +1,242 @@
|
|||
# Data types
|
||||
|
||||
There are 7 data types in JavaScript.
|
||||
|
||||
Here we will get the common understanding of them. In the next chapters we'll talk about each type in detail.
|
||||
|
||||
[cut]
|
||||
|
||||
## A number
|
||||
|
||||
```js
|
||||
let n = 123;
|
||||
n = 12.345;
|
||||
```
|
||||
|
||||
A *number* type serves both for integer and floating point numbers.
|
||||
|
||||
There are many operations for numbers, e.g. multiplication `*`, division `/`, addition `+`, substraction `-` and so on.
|
||||
|
||||
Besides regular numbers there are so-called "special numeric values" which also belong to that type: `Infinity`, `-Infinity` and `NaN`.
|
||||
|
||||
- `Infinity` represents the mathematical [Infinity](https://en.wikipedia.org/wiki/Infinity). It is a value that's greater than any number.
|
||||
|
||||
We can get it as a result of division by zero:
|
||||
|
||||
```js run
|
||||
alert( 1 / 0 ); // Infinity
|
||||
```
|
||||
|
||||
Or just mention it in the code directly:
|
||||
|
||||
```js run
|
||||
alert( Infinity ); // Infinity
|
||||
```
|
||||
- `NaN` represents a computational error. It is a result of an incorrect or an undefined mathematical operation, for instance:
|
||||
|
||||
```js run
|
||||
alert( "not a number" / 2 ); // NaN
|
||||
```
|
||||
|
||||
`NaN` is sticky. Any further operation on `NaN` would give `NaN`:
|
||||
|
||||
```js run
|
||||
alert( "not a number" / 2 + 5 ); // NaN + 5 is still NaN
|
||||
```
|
||||
|
||||
So, in a long mathematical expression if we have `NaN` in one place, it propagates to the whole result.
|
||||
|
||||
```smart header="Mathematical operations are safe"
|
||||
Doing maths is safe in JavaScript. We can do anything: divide by zero, treat non-numeric strings as numbers, etc.
|
||||
|
||||
The script will never stop with a fatal error ("die"). At worst we'll get `NaN` as the result.
|
||||
```
|
||||
|
||||
Special numeric values formally belong to the "number" type. Of course they are not numbers in a common sense of this word.
|
||||
|
||||
We'll see more into working with numbers in the chapter <info:number>.
|
||||
|
||||
## A string
|
||||
|
||||
```js
|
||||
let str = "Hello";
|
||||
let str2 = 'Single quotes are ok too';
|
||||
let phrase = `can embed ${str}`;
|
||||
```
|
||||
|
||||
In JavaScript, there are 3 types of quotes.
|
||||
|
||||
1. Double quotes: `"Hello"`.
|
||||
2. Single quotes: `'Hello'`.
|
||||
3. Backticks: <code>`Hello`</code>.
|
||||
|
||||
Double and single quotes are similar, "simple" quotes.
|
||||
|
||||
Backticks are "extended functionality" quotes. They allow to embed variables and expressions into a string by wrapping them in `${…}`, for example:
|
||||
|
||||
```js run
|
||||
let name = "John";
|
||||
|
||||
// embed variable
|
||||
alert( `Hello, ${name}!` ); // Hello, John!
|
||||
|
||||
// embed expression
|
||||
alert( `the result is ${1 + 2}` ); // the result is 3
|
||||
```
|
||||
|
||||
The expression inside `${…}` is evaluated and the result becomes a part of the string. We can put anything there: a variable like `name` or an arithmetical expression like `1 + 2` or something more complex.
|
||||
|
||||
We'll cover strings more thoroughly in the chapter <info:string>.
|
||||
|
||||
```smart header="There is no *character* type."
|
||||
In some languages, there is a special "character" type for a single character. For example, in the C language it is `char`.
|
||||
|
||||
In JavaScript, there is no such type. There's only one type: `string`. A string may consist of only one character or many of them.
|
||||
```
|
||||
|
||||
## A boolean (logical)
|
||||
|
||||
The boolean type has only two values: `true` and `false`.
|
||||
|
||||
This type is commonly used to store yes/no values.
|
||||
|
||||
For instance:
|
||||
|
||||
```js no-beautify
|
||||
let checked = true; // the form field is checked
|
||||
checked = false; // the form field is not checked
|
||||
```
|
||||
|
||||
Boolean values also come as the result of comparisons:
|
||||
|
||||
```js run
|
||||
let isGreater = 4 > 1;
|
||||
|
||||
alert( isGreater ); // true (the comparison result is "yes")
|
||||
```
|
||||
|
||||
We'll cover booleans more deeply while discussing logical operators.
|
||||
|
||||
## The "null" value
|
||||
|
||||
The special `null` value does not belong to any type described above.
|
||||
|
||||
It forms a separate type of its own, which contains only the `null` value:
|
||||
|
||||
```js
|
||||
let age = null;
|
||||
```
|
||||
|
||||
In JavaScript `null` is not a "reference to a non-existing object" or a "null pointer" like in some other languages.
|
||||
|
||||
It's just a special value which has the sense of "nothing", "empty" or "value unknown".
|
||||
|
||||
The code above states that the `age` is unknown or empty for some reason.
|
||||
|
||||
## The "undefined" value
|
||||
|
||||
The special value `undefined` stands apart. It makes a type of its own, just like `null`.
|
||||
|
||||
The sense of `undefined` is "value is not assigned".
|
||||
|
||||
If a variable is declared, but not assigned, then its value is exactly `undefined`:
|
||||
|
||||
```js run
|
||||
let x;
|
||||
|
||||
alert( x ); // shows "undefined"
|
||||
```
|
||||
|
||||
Technically, it is possible to assign to `undefined`:
|
||||
|
||||
```js run
|
||||
let x = 123;
|
||||
|
||||
x = undefined;
|
||||
|
||||
alert( x ); // "undefined"
|
||||
```
|
||||
|
||||
...But it's not recommended to do that. Normally, we use `null` to write an "empty" or an "unknown" value into the variable, and `undefined` is only used for checks, to see if the variable is assigned or similar.
|
||||
|
||||
## Objects and Symbols
|
||||
|
||||
The `object` type is special.
|
||||
|
||||
All other types are called "primitive", because their values can contain only a single thing (be it a string or a number or whatever).
|
||||
|
||||
In contrast, objects are used to store collections data and more complex entities. We'll deal with them later after we know enough about primitives.
|
||||
|
||||
The `symbol` type is used to create unique identifiers, mainly used to store data in objects. We'll return to them as soon as we cover objects.
|
||||
|
||||
|
||||
[todo when ? chapter?]
|
||||
[todo move tasks]
|
||||
|
||||
## The typeof operator [#type-typeof]
|
||||
[todo we need typeof in types]
|
||||
|
||||
The `typeof` operator returns the type of the argument. It's useful when we want to process values of different types differently, or just want to make a quick check.
|
||||
|
||||
It supports two forms of syntax:
|
||||
|
||||
1. As an operator: `typeof x`.
|
||||
2. Function style: `typeof(x)`.
|
||||
|
||||
In other words, it works both with the brackets or without them. The result is the same.
|
||||
|
||||
The call to `typeof x` returns a string, which has the type name:
|
||||
|
||||
```js
|
||||
typeof undefined // "undefined"
|
||||
|
||||
typeof 0 // "number"
|
||||
|
||||
typeof true // "boolean"
|
||||
|
||||
typeof "foo" // "string"
|
||||
|
||||
typeof Symbol("id") // "symbol"
|
||||
|
||||
*!*
|
||||
typeof Math // "object" (1)
|
||||
*/!*
|
||||
|
||||
*!*
|
||||
typeof null // "object" (2)
|
||||
*/!*
|
||||
|
||||
*!*
|
||||
typeof alert // "function" (3)
|
||||
*/!*
|
||||
```
|
||||
|
||||
The last three lines may be a little unobvious so here's explanations:
|
||||
|
||||
1. `Math` is a built-in object that provides mathematical operations. We will learn it in the chapter <info:number>. Here it servers as an example, nothing more.
|
||||
2. The result of `typeof null` equals to `"object"`. That's wrong. It is an officially recognized error in `typeof`, kept for compatibility. Of course, `null` is not an object. It is a special value with a separate type of its own. So, again, that's an error in the language.
|
||||
3. The result of `typeof alert` is `"function"`, because `alert` is a function of the language. We'll study functions in the near future and see that actually functions belong to the object type. But `typeof` treats them differently. That's very convenient in practice.
|
||||
|
||||
|
||||
## Summary
|
||||
|
||||
There are 7 basic types in JavaScript.
|
||||
|
||||
- `number` for numbers of any kind, can convert into it using `Number(value)`.
|
||||
- `string` for strings and characters, can convert into it using `String(value)`.
|
||||
- `boolean` for `true`/`false`, can convert into it using `Boolean(value)`.
|
||||
- `null` for unknown values (a standalone type that has a single value `null`).
|
||||
- `undefined` for unassigned values (a standalone type that has a single value `undefined`).
|
||||
- `object` for more complex data structures.
|
||||
- `symbol` for unique identifiers.
|
||||
|
||||
The `typeof` operator allows to see which type is stored in the variable.
|
||||
|
||||
- Two forms: `typeof x` or `typeof(x)`.
|
||||
- Returns a string with the name of the type, like `"string"`.
|
||||
- Mistreats `null` as an `object` -- the old official error in the language.
|
||||
|
||||
In nearest chapters we'll concentrate on understanding how to operate on primitives and once we're familiar with that, then we'll move on to objects.
|
||||
|
||||
|
||||
|
|
@ -12,6 +12,14 @@ message = 123456;
|
|||
|
||||
There are also cases when we need to explicitly convert between types to ensure that we store the right data the right way or to use special features of a certain type.
|
||||
|
||||
[cut]
|
||||
|
||||
```smart header="No objects here"
|
||||
In this chapter we don't cover objects yet. They provide special facilities for conversion, interesting, but we'd better understand primitives first, then extend to objects in the next steps.
|
||||
```
|
||||
|
||||
[todo where? link?]
|
||||
|
||||
## ToString
|
||||
|
||||
The string conversion happens when we need a string form of a value.
|
||||
|
@ -134,56 +142,17 @@ alert( Boolean(" ") ); // also true (any non-empty string is true)
|
|||
```
|
||||
````
|
||||
|
||||
````warn header="Empty objects are truthy"
|
||||
All objects become `true`:
|
||||
|
||||
```js run
|
||||
alert( Boolean([]) ); // true, even if empty array
|
||||
alert( Boolean({}) ); // true, even if empty object
|
||||
```
|
||||
````
|
||||
|
||||
|
||||
## ToPrimitive
|
||||
|
||||
A string or numeric conversion of an object is a two-stage process. The object is first converted to a primitive value, and then ToString/ToNumber rules are applied to it.
|
||||
|
||||
The conversion is customizable on a per-object basis, so we'll study it later when we go deeper into objects. [todo in the chapter?]
|
||||
|
||||
Examples:
|
||||
|
||||
- When a plain object is converted into a string, is becomes `[object Object]`:
|
||||
|
||||
```js run
|
||||
alert( {} ); // [object Object]
|
||||
alert( {name: "John"} ); // [object Object]
|
||||
```
|
||||
|
||||
- An array becomes a comma-delimited list of items:
|
||||
|
||||
```js run
|
||||
let arr = [1, 2, 3];
|
||||
|
||||
alert( arr ); // 1,2,3
|
||||
alert( String(arr) === '1,2,3' ); // true
|
||||
```
|
||||
|
||||
We'll return to it in the chapter [todo].
|
||||
|
||||
```smart header="ToBoolean is always true"
|
||||
Here `ToBoolean` was not mentioned, because it provides no customizability for objects
|
||||
|
||||
The rule is simple: all objects are truthy.
|
||||
```
|
||||
|
||||
|
||||
## Summary
|
||||
|
||||
There exist three most widely used type conversions: to string, to number and to boolean.
|
||||
|
||||
The conversion to string is usully obvious for primitive values and depends on the object type for objects. For instance, arrays turn into a comma-delimited list of elements.
|
||||
- `ToString` -- happens in output, can be called with `String(value)`.
|
||||
|
||||
To number follows the rules:
|
||||
The conversion to string is usully obvious for primitive values.
|
||||
|
||||
- `ToNumber` -- happens in math operations, can be called with `Number(value)`.
|
||||
|
||||
The conversion follows the rules:
|
||||
|
||||
| Value | Becomes... |
|
||||
|-------|-------------|
|
||||
|
@ -192,7 +161,7 @@ To number follows the rules:
|
|||
|<code>true / false</code> | `1 / 0` |
|
||||
| `string` | The string is read "as is", whitespaces from both sides are ignored. An empty string is `0`. An error gives `NaN`. |
|
||||
|
||||
To boolean:
|
||||
- ToBoolean -- happens in logical operatiosn, can be called with `Boolean(value)`.
|
||||
|
||||
| Value | Becomes... |
|
||||
|-------|-------------|
|
||||
|
@ -204,5 +173,5 @@ Most of these rules are easy to understand and memorize. The notable exceptions
|
|||
- `undefined` is `NaN` as a number.
|
||||
- `"0"` is true as a boolean.
|
||||
|
||||
Objects can define their own methods of converting to a string or a number, we'll see them later. But they can't redefine the conversion to boolean.
|
||||
Objects are not covered here, we'll return to them in the special object-only chapter.
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
|
||||
|
||||
```js run
|
||||
let salaries = [ 100, 160, 130 ];
|
||||
|
||||
let sum = 0;
|
||||
for(let salary of salaries) {
|
||||
sum += salary;
|
||||
}
|
||||
|
||||
alert( sum ); // 390
|
||||
```
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
importance: 5
|
||||
|
||||
---
|
||||
|
||||
# Sum the array
|
||||
|
||||
Write the code to get the sum of the array using `for..of` loop and store in the variable `sum`:
|
||||
|
||||
```js
|
||||
let salaries = [ 100, 160, 130 ];
|
||||
```
|
||||
|
||||
Should be `390` here.
|
|
@ -1,425 +0,0 @@
|
|||
# Data types
|
||||
|
||||
There are 7 data types in JavaScript.
|
||||
|
||||
Here we will get the common understanding of them. In the next chapters we'll talk about each type in detail.
|
||||
|
||||
[cut]
|
||||
|
||||
## A number
|
||||
|
||||
```js
|
||||
let n = 123;
|
||||
n = 12.345;
|
||||
```
|
||||
|
||||
A *number* type serves both for integer and floating point numbers.
|
||||
|
||||
There are many operations for numbers, e.g. multiplication `*`, division `/`, addition `+`, substraction `-` and so on.
|
||||
|
||||
Besides regular numbers there are so-called "special numeric values" which also belong to that type: `Infinity`, `-Infinity` and `NaN`.
|
||||
|
||||
- `Infinity` represents the mathematical [Infinity](https://en.wikipedia.org/wiki/Infinity). It is a value that's greater than any number.
|
||||
|
||||
We can get it as a result of division by zero:
|
||||
|
||||
```js run
|
||||
alert( 1 / 0 ); // Infinity
|
||||
```
|
||||
|
||||
Or just mention it in the code directly:
|
||||
|
||||
```js run
|
||||
alert( Infinity ); // Infinity
|
||||
```
|
||||
- `NaN` represents a computational error. It is a result of an incorrect or an undefined mathematical operation, for instance:
|
||||
|
||||
```js run
|
||||
alert( "not a number" / 2 ); // NaN
|
||||
```
|
||||
|
||||
`NaN` is sticky. Any further operation on `NaN` would give `NaN`:
|
||||
|
||||
```js run
|
||||
alert( "not a number" / 2 + 5 ); // NaN
|
||||
```
|
||||
|
||||
So, in a long mathematical expression if we have `NaN` in one place, it propagates to the whole result.
|
||||
|
||||
```smart header="Mathematical operations are safe"
|
||||
Doing maths is safe in JavaScript. We can do anything: divide by zero, treat non-numeric strings as numbers, etc.
|
||||
|
||||
The script will never stop ("die") on that. At worst we'll get `NaN` as the result.
|
||||
```
|
||||
|
||||
Special numeric values formally belong to the "number" type. Of course they are not numbers in a common sense of this word.
|
||||
|
||||
We'll see more into working with numbers in the chapter <info:number>.
|
||||
|
||||
## A string
|
||||
|
||||
```js
|
||||
let str = "Hello";
|
||||
let str2 = 'Single quotes are ok too';
|
||||
let phrase = `can embed ${str}`;
|
||||
```
|
||||
|
||||
In JavaScript, there are 3 types of quotes.
|
||||
|
||||
1. Double quotes: `"Hello"`.
|
||||
2. Single quotes: `'Hello'`.
|
||||
3. Backticks: <code>`Hello`</code>.
|
||||
|
||||
Double and single quotes are similar, "simple" quotes.
|
||||
|
||||
Backticks are "extended functionality" quotes. They allow to embed variables and expressions into a string by wrapping them in `${…}`, for example:
|
||||
|
||||
```js run
|
||||
let name = "John";
|
||||
|
||||
// embed variable
|
||||
alert( `Hello, ${name}!` ); // Hello, John!
|
||||
|
||||
// embed expression
|
||||
alert( `the result is ${1 + 2}` ); // the result is 3
|
||||
```
|
||||
|
||||
The expression inside `${…}` is evaluated and the result becomes a part of the string. We can put anything there: a variable like `name` or an arithmetical expression like `1 + 2` or something more complex.
|
||||
|
||||
We'll cover strings more thoroughly in the chapter <info:string>.
|
||||
|
||||
```smart header="There is no *character* type."
|
||||
In some languages, there is a special "character" type for a single character. For example, in the C language it is `char`.
|
||||
|
||||
In JavaScript, there is no such type. There's only one type: `string`. A string may consist of only one character or many of them.
|
||||
```
|
||||
|
||||
## A boolean (logical)
|
||||
|
||||
The boolean type has only two values: `true` and `false`.
|
||||
|
||||
This type is commonly used to store yes/no values.
|
||||
|
||||
For instance:
|
||||
|
||||
```js no-beautify
|
||||
let checked = true; // the form field is checked
|
||||
checked = false; // the form field is not checked
|
||||
```
|
||||
|
||||
Boolean values also come as the result of comparisons:
|
||||
|
||||
```js run
|
||||
let isGreater = 4 > 1;
|
||||
|
||||
alert( isGreater ); // true (the comparison result is "yes")
|
||||
```
|
||||
|
||||
We'll cover booleans more deeply while discussing logical operators.
|
||||
|
||||
## The "null" value
|
||||
|
||||
The special `null` value does not belong to any type described above.
|
||||
|
||||
It forms a separate type of its own, which contains only the `null` value:
|
||||
|
||||
```js
|
||||
let age = null;
|
||||
```
|
||||
|
||||
In JavaScript `null` is not a "reference to a non-existing object" or a "null pointer" like in some other languages.
|
||||
|
||||
It's just a special value which has the sense of "nothing", "empty" or "value unknown".
|
||||
|
||||
The code above states that the `age` is unknown or empty for some reason.
|
||||
|
||||
## The "undefined" value
|
||||
|
||||
The special value `undefined` stands apart. It makes a type of its own, just like `null`.
|
||||
|
||||
The sense of `undefined` is "value is not assigned".
|
||||
|
||||
If a variable is declared, but not assigned, then its value is exactly `undefined`:
|
||||
|
||||
```js run
|
||||
let x;
|
||||
|
||||
alert( x ); // shows "undefined"
|
||||
```
|
||||
|
||||
Technically, it is possible to assign to `undefined`:
|
||||
|
||||
```js run
|
||||
let x = 123;
|
||||
|
||||
x = undefined;
|
||||
|
||||
alert( x ); // "undefined"
|
||||
```
|
||||
|
||||
...But it's not recommended to do that. Normally, we use `null` to write an "empty" or an "unknown" value into the variable, and `undefined` is only used for checks, to see if the variable is assigned or similar.
|
||||
|
||||
|
||||
## Objects
|
||||
|
||||
The `object` type is special.
|
||||
|
||||
All other types are called "primitive", because their values can contain only a single thing (be it a string or a number or whatever).
|
||||
|
||||
In contrast, objects are used to store *keyed collections* of various data and more complex entities.
|
||||
|
||||
An object is defined with the figure brackets `{…}` with an optional list of "key: value" pairs. In programming that's sometimes called an "associative array" or a "hash".
|
||||
|
||||
A `key` is a string, `value` can be anything.
|
||||
|
||||
For instance, here we create a `user` object with two properties:
|
||||
|
||||
```js
|
||||
let user = { // an object
|
||||
name: "John", // key "name" has value "John"
|
||||
age: 30 // key "age" has value 30
|
||||
};
|
||||
```
|
||||
|
||||
The `user` object can be imagined as a cabinet with two signed files labelled "name" and "age".
|
||||
|
||||

|
||||
|
||||
Both values (also called "fields" or "properties") are accessible using the dot notation:
|
||||
|
||||
```js
|
||||
// get fields of the object:
|
||||
alert( user.name ); // John
|
||||
alert( user.age ); // 30
|
||||
```
|
||||
|
||||
Also we can add new information to the user any time later:
|
||||
|
||||
```js
|
||||
user.isAdmin = true;
|
||||
```
|
||||
|
||||

|
||||
|
||||
...Or remove it with the help of `delete` operator:
|
||||
|
||||
```js
|
||||
delete user.age;
|
||||
```
|
||||
|
||||

|
||||
|
||||
If the string which denotes the key (also called a "property name") has multiple words, then the dot notation won't work:
|
||||
|
||||
```js
|
||||
// this would give a syntax error
|
||||
user.likes to swim? = true;
|
||||
```
|
||||
|
||||
That's because, the dot requires the property name to be a valid variable identifier. That is: no spaces and other limitations.
|
||||
|
||||
There's a "square bracket notation" that works with any string:
|
||||
|
||||
```js
|
||||
user["likes to swim?"] = true;
|
||||
```
|
||||
|
||||
Square brackets are also the way to access a property by the name from the variable:
|
||||
|
||||
```js
|
||||
let key = "likes to swim?";
|
||||
user[key] = true; // same as above
|
||||
```
|
||||
|
||||
Here we have a variable `key` which contains the property name, probably evaluated or calculated at run-time.
|
||||
|
||||
Most of time, the dot is used to access object properties, but when we need a complex property name or to pass the name as a variable, then -- we go square brackets.
|
||||
|
||||
What we've just seen is called a "plain object", or just `Object`.
|
||||
|
||||
There are many other kinds of objects in Javascript:
|
||||
|
||||
- `Array` to store ordered data collections,
|
||||
- `Date` to store the information about the date and time,
|
||||
- `Error` to store the information about an error.
|
||||
- ...And so on.
|
||||
|
||||
Sometimes people say something like "Array type" or "Date type", but formally they are not types of their own, but belong to a single "object" data type. And they extend it in various ways.
|
||||
|
||||
Objects in JavaScript are very powerful. Here we've just scratched the surface of the topic that is really huge. We'll be closely working with objects and learning more about them in further parts of the tutorial.
|
||||
|
||||
````smart header="A trailing comma"
|
||||
|
||||
[todo: move to 4-object ?]
|
||||
Experienced developers sometimes add one more comma to the end of an object, like this:
|
||||
|
||||
```js
|
||||
let user = {
|
||||
name: "John",
|
||||
age: 30,
|
||||
isAdmin: true*!*,*/!* // extra comma
|
||||
};
|
||||
```
|
||||
|
||||
That's called a "trailing comma" and is allowed by the language.
|
||||
|
||||
Sometimes the reason is pure lazyness: when in the development process the last property becomes unneeded and is removed, the programmer forgets to delete the comma at the end of newly last one.
|
||||
|
||||
But from the other side that "lazyness" is justified, because the same line can be safely moved between objects -- from the first position to the middle or to the last -- without bookkeeping commas. That's a good thing.
|
||||
|
||||
Actual decision whether to add trailing commas or not depends on you. Some people like them, some find them ugly.
|
||||
````
|
||||
|
||||
## Arrays
|
||||
|
||||
As we’ve just seen, objects in Javascript store arbitrary keyed values.
|
||||
|
||||
But quite often we find that we need an *ordered collection*, where we have a 1st, a 2nd, a 3rd element and so on. For example, we need that to store a list of something: users, goods, HTML elements etc. It not convenient to use an object here, because it provides no methods to manage the order of elements. We can’t easily access the n-th element in an object. Also we can’t insert a new property “before” the existing ones, and so on. Objects are just not meant for such use.
|
||||
|
||||
There exists a special data structure named "an array", to store ordered collections.
|
||||
|
||||
An array is created using square brackets:
|
||||
|
||||
```js
|
||||
let empty = []; // empty array
|
||||
|
||||
let fruits = ["Apple", "Orange", "Plum"]; // array with 3 values
|
||||
```
|
||||
|
||||
Individual items are accessed using brackets `[]`, the first item has zero index:
|
||||
|
||||
```js run
|
||||
let fruits = ["Apple", "Orange", "Plum"]; // array with 3 values
|
||||
|
||||
alert( fruits[0] ); // Apple
|
||||
alert( fruits[1] ); // Orange
|
||||
alert( fruits[2] ); // Plum
|
||||
|
||||
// how many elements (last index + 1)
|
||||
alert( fruits.length ); // 3
|
||||
```
|
||||
|
||||
Please note that arrays do not form a separate language type. They are based on objects. But they greatly extend them with features of their own, methods to add, remove, extract elements from the array, to sort arrays and more. We'll cover them in the chapter <info:array>.
|
||||
|
||||
## Symbol type
|
||||
|
||||
The `symbol` type is used in conjunction with objects. Probably we won't need them soon, but it's the 7th and the last type of the language, so we must mention it here for the sake of completeness.
|
||||
|
||||
A "symbol" represents an unique identifier with a given name.
|
||||
|
||||
A value of this type can be created using `Symbol(name)`:
|
||||
|
||||
```js
|
||||
// id is a symbol with the name "id"
|
||||
let id = Symbol("id");
|
||||
```
|
||||
|
||||
Symbols in JavaScript are different from symbols in Ruby language (if you are familiar with it, please don't get trapped by the same word). Two symbols with the same name are not the same:
|
||||
|
||||
```js run
|
||||
let id1 = Symbol("id");
|
||||
let id2 = Symbol("id");
|
||||
|
||||
*!*
|
||||
alert(id1 == id2); // false
|
||||
*/!*
|
||||
```
|
||||
|
||||
Symbols is a special primitive type used for identifiers, which are guaranteed to be unique. So, even if we create many symbols with the same name, they are still unique.
|
||||
|
||||
The use case for symbols is to create "concealed" properties of an object, that no other part of code can occasionally access or overwrite.
|
||||
|
||||
For instance, if we want to store an "identifier" for the object `user`, we can create a symbol with the name `id` for it:
|
||||
|
||||
```js run
|
||||
let user = { name: "John" };
|
||||
let id = Symbol("id");
|
||||
|
||||
user[id] = "ID Value";
|
||||
alert( user[id] ); // we can access the data using the symbol as the key
|
||||
```
|
||||
|
||||
Now let's imagine that another script wants to have his own "id" property inside `user`, for his own purposes. That may be another javascript library, so the scripts are completely unaware for each other.
|
||||
|
||||
No problem. It can create its own `Symbol("id")`. There will be no conflict, because symbols are always different, even if they have the same name.
|
||||
|
||||
Please note if we used a string `"id"` instead of a symbol for the same purpose, then there could be a conflict:
|
||||
|
||||
```js run
|
||||
let user = { name: "John" };
|
||||
|
||||
// our script
|
||||
user.id = "ID Value";
|
||||
|
||||
// ...if later another script the uses same name for its purposes...
|
||||
|
||||
user.id = "ID 2"
|
||||
// then boom! overwritten! it did not mean to harm the colleague, but did it!
|
||||
```
|
||||
|
||||
Two `Symbol("id")` are not equal, that's why they would allow to store values safely.
|
||||
|
||||
|
||||
Symbols are widely used by the JavaScript language itself to store "system" properties which we'll learn in later chapters.
|
||||
|
||||
## The typeof operator [#type-typeof]
|
||||
|
||||
The `typeof` operator returns the type of the argument. It's useful when we want to process values of different types differently, or just want to make a quick check.
|
||||
|
||||
It supports two forms of syntax:
|
||||
|
||||
1. As an operator: `typeof x`.
|
||||
2. Function style: `typeof(x)`.
|
||||
|
||||
In other words, it works both with the brackets or without them. The result is the same.
|
||||
|
||||
The call to `typeof x` returns a string, which has the type name:
|
||||
|
||||
```js
|
||||
typeof undefined // "undefined"
|
||||
|
||||
typeof 0 // "number"
|
||||
|
||||
typeof true // "boolean"
|
||||
|
||||
typeof "foo" // "string"
|
||||
|
||||
typeof Symbol("id") // "symbol"
|
||||
|
||||
typeof {} // "object"
|
||||
|
||||
*!*
|
||||
typeof [] // "object" (1)
|
||||
*/!*
|
||||
|
||||
*!*
|
||||
typeof null // "object" (2)
|
||||
*/!*
|
||||
|
||||
*!*
|
||||
typeof alert // "function" (3)
|
||||
*/!*
|
||||
```
|
||||
|
||||
The last three lines may be a little unobvious so here's explanations:
|
||||
|
||||
1. The array is not a type of its own, it is based on object, that's why `typeof []` is `"object"`.
|
||||
2. The result of `typeof null` equals to `"object"`. That's wrong. It is an officially recognized error in `typeof`, kept for compatibility. Of course, `null` is not an object. It is a special value with a separate type of its own. So, again, that's an error in the language.
|
||||
3. The result of `typeof alert` is `"function"`, because `alert` is a function of the language. We'll study functions in the near future and see that actually functions belong to the object type. But `typeof` treats them differently. That's very convenient in practice.
|
||||
|
||||
|
||||
|
||||
## Summary
|
||||
|
||||
There are 7 basic types in JavaScript.
|
||||
|
||||
- `number` for numbers of any kind, can convert into it using `Number(value)`.
|
||||
- `string` for strings and characters, can convert into it using `String(value)`.
|
||||
- `boolean` for `true`/`false`, can convert into it using `Boolean(value)`.
|
||||
- `null` for unknown values.
|
||||
- `undefined` for unassigned values.
|
||||
- `symbol` for unique identifiers.
|
||||
- `object` for more complex data structures.
|
||||
|
||||
The `typeof` operator allows to see which type is stored in the variable.
|
||||
|
Before Width: | Height: | Size: 3.8 KiB |
Before Width: | Height: | Size: 8.6 KiB |
Before Width: | Height: | Size: 4.3 KiB |
Before Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 7.6 KiB |
Before Width: | Height: | Size: 3.8 KiB |
Before Width: | Height: | Size: 8.6 KiB |
Before Width: | Height: | Size: 4.3 KiB |
Before Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 7.6 KiB |
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 54 KiB |
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 38 KiB |
Before Width: | Height: | Size: 92 KiB After Width: | Height: | Size: 92 KiB |
|
@ -349,95 +349,13 @@ label: for(...)
|
|||
The call to a `break/continue` is only possible from inside the loop, and the label must be somewhere upwards from the directive.
|
||||
````
|
||||
|
||||
## The "for..in" loop
|
||||
|
||||
To walk over all keys of an object, there exists a special form of the loop: `for..in`. This is a completely different thing from the `for(;;)` construct that we've studied before.
|
||||
|
||||
The syntax:
|
||||
|
||||
```js
|
||||
for(key in object) {
|
||||
// executes the body for each key among object properties
|
||||
}
|
||||
```
|
||||
|
||||
For instance, let's output all properties of `user`:
|
||||
|
||||
```js run
|
||||
let user = {
|
||||
name: "John",
|
||||
age: 30,
|
||||
isAdmin: true
|
||||
};
|
||||
|
||||
for(let key in user) {
|
||||
// keys
|
||||
alert( key ); // name, age, 30
|
||||
// values for the keys
|
||||
alert( user[key] ); // John, 30, true
|
||||
}
|
||||
```
|
||||
|
||||
Note that all "for" constructs allow to declare the looping variable inside the loop, like `key` here. We could use another variable name here instead of `key`, for instance, "prop" is also widely used for iterations.
|
||||
|
||||
|
||||
## The "for..of" loop
|
||||
|
||||
And the third (the last one) kind of the `for` loop. Again it has a totally different meaning from what we've seen before.
|
||||
|
||||
This form iterates over arrays.
|
||||
|
||||
Actually, we can do it with the `for(;;)` loop:
|
||||
|
||||
```js run
|
||||
let fruits = ["Apple", "Orange", "Plum"];
|
||||
|
||||
// iterates over all elements:
|
||||
// i is the number of the current element
|
||||
// fruits[i] is the value of the current element
|
||||
for(let i = 0; i < fruits.length; i++) {
|
||||
alert( fruits[i] ); // Apple, then Orange, then Plum
|
||||
}
|
||||
```
|
||||
|
||||
The "generic" `for(;;)` loop works well even in most outdated browsers.
|
||||
|
||||
The `for..of` syntax is shorter:
|
||||
|
||||
```js run
|
||||
let fruits = ["Apple", "Orange", "Plum"];
|
||||
|
||||
// iterates over all elements:
|
||||
// fruit is the value of the current element
|
||||
for(let fruit of fruits) {
|
||||
alert( fruit );
|
||||
}
|
||||
```
|
||||
|
||||
The `for..of` doesn't give access to the number of the current element, just its value, but in most cases that's enough.
|
||||
|
||||
````smart header="Iterables"
|
||||
Later we'll learn the concept of *iterable* objects in Javascript. An iterable object must implement special functionality that allows to use `for..of` on it.
|
||||
|
||||
There are many iterable objects. For instance, a string is iterable, `for..of` will list characters in the example:
|
||||
|
||||
```js run
|
||||
for(let char of "test") {
|
||||
alert( char ); t, then e, then s, then t
|
||||
}
|
||||
```
|
||||
````
|
||||
|
||||
|
||||
## Summary
|
||||
|
||||
There are 5 types of loops in JavaScript:
|
||||
We covered 3 types of loops:
|
||||
|
||||
- `while` -- the condition is checked before each iteration.
|
||||
- `do..while` -- the condition is checked after each iteration.
|
||||
- `for(;;)` -- the condition is checked before each iteration, additional settings available.
|
||||
- `for(key in obj)` -- to iterate over object properties.
|
||||
- `for(item of array)` -- to iterate over array items.
|
||||
|
||||
To make an "infinite" loop, usually the `while(true)` construct is used. Such a loop, just like any other, can be stopped with the `break` directive.
|
||||
|
||||
|
@ -445,5 +363,3 @@ If we don't want to do anything more on this iteration and would like to forward
|
|||
|
||||
`Break/continue` support labels before the loop. A label is the only way for `break/continue` to escape the nesting and go to the outer loop.
|
||||
|
||||
To get an array of object property names, there is a method `Object.keys(obj)`.
|
||||
|