Merge branch 'master' of https://github.com/iliakan/javascript-tutorial-en
This commit is contained in:
commit
fa4a678d53
16 changed files with 151 additions and 151 deletions
|
@ -11,7 +11,7 @@ So first, let's see how to attach a script to a webpage. For server-side environ
|
|||
|
||||
## The "script" tag
|
||||
|
||||
JavaScript programs can be inserted in any place of HTML with the help of the `<script>` tag.
|
||||
JavaScript programs can be inserted in any part of an HTML document with the help of the `<script>` tag.
|
||||
|
||||
For instance:
|
||||
|
||||
|
@ -49,7 +49,7 @@ The `<script>` tag has a few attributes that are rarely used nowadays, but we ca
|
|||
|
||||
The `type` attribute: <code><script <u>type</u>=...></code>
|
||||
|
||||
: The old standard HTML4 required a script to have a type. Usually it was `type="text/javascript"`. The modern HTML standard assumes this `type` by default, no attribute is required.
|
||||
: The old standard HTML4 required a script to have a type. Usually it was `type="text/javascript"`. The modern HTML standard assumes this `type` by default. No attribute is required.
|
||||
|
||||
The `language` attribute: <code><script <u>language</u>=...></code>
|
||||
: This attribute was meant to show the language of the script. As of now, this attribute makes no sense, the language is JavaScript by default. No need to use it.
|
||||
|
@ -105,7 +105,7 @@ That saves traffic and makes pages faster.
|
|||
```
|
||||
|
||||
````warn header="If `src` is set, the script content is ignored."
|
||||
A single `<script>` tag can't have both `src` attribute and the code inside.
|
||||
A single `<script>` tag can't have both the `src` attribute and the code inside.
|
||||
|
||||
This won't work:
|
||||
|
||||
|
|
|
@ -61,9 +61,9 @@ If you're curious to see a concrete example of such an error, check this code ou
|
|||
[1, 2].forEach(alert)
|
||||
```
|
||||
|
||||
No need to think about the meaning of the brackets `[]` and `forEach` yet. We'll study them later, for now -- it does not matter. Let's just remember the result: it shows `1`, then `2`.
|
||||
No need to think about the meaning of the brackets `[]` and `forEach` yet. We'll study them later, for now it does not matter. Let's just remember the result: it shows `1`, then `2`.
|
||||
|
||||
Now let's add an `alert` before the code. And *not* finish it with a semicolon:
|
||||
Now let's add an `alert` before the code and *not* finish it with a semicolon:
|
||||
|
||||
```js run no-beautify
|
||||
alert("There will be an error")
|
||||
|
@ -94,11 +94,11 @@ alert("There will be an error")[1, 2].forEach(alert)
|
|||
But it should be two separate statements, not a single one. Such a merging in this case is just wrong, hence the error. There are other situations when such a thing happens.
|
||||
````
|
||||
|
||||
It's recommended to put semicolons between statements even if they are separated by newlines. This rule is widely adopted by the community. Let's note once again -- *it is possible* to leave out semicolons most of the time. But it's safer, especially for a beginner -- to use them.
|
||||
It's recommended to put semicolons between statements even if they are separated by newlines. This rule is widely adopted by the community. Let's note once again -- *it is possible* to leave out semicolons most of the time. But it's safer -- especially for a beginner -- to use them.
|
||||
|
||||
## Comments
|
||||
|
||||
As the time goes, the program becomes more and more complex. It becomes necessary to add *comments* which describe what happens and why.
|
||||
As time goes on, the program becomes more and more complex. It becomes necessary to add *comments* which describe what happens and why.
|
||||
|
||||
Comments can be put into any place of the script. They don't affect the execution, because the engine simply ignores them.
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
For a long time JavaScript was evolving without compatibility issues. New features were added to the language, but the old functionality did not change.
|
||||
|
||||
That had the benefit of never breaking the existing codes. But the downside was that any mistake or an imperfect decision made by JavaScript creators got stuck in the language forever.
|
||||
That had the benefit of never breaking existing code. But the downside was that any mistake or an imperfect decision made by JavaScript creators got stuck in the language forever.
|
||||
|
||||
It had been so until 2009 when ECMAScript 5 (ES5) appeared. It added new features to the language and modified some of the existing ones. To keep the old code working, most modifications are off by default. One needs to enable them explicitly with a special directive `"use strict"`.
|
||||
|
||||
|
@ -55,7 +55,7 @@ The differences of `"use strict"` versus the "default" mode are still to be cove
|
|||
|
||||
In the next chapters, as we learn language features, we'll make notes about the differences of the strict mode. Luckily, there are not so many. And they actually make our life better.
|
||||
|
||||
At this point of time it's enough to know about it in general:
|
||||
At this point in time it's enough to know about it in general:
|
||||
|
||||
1. The `"use strict"` directive switches the engine to the "modern" mode, changing the behavior of some built-in features. We'll see the details as we study.
|
||||
2. The strict mode is enabled by `"use strict"` at the top. Also there are several language features like "classes" and "modules" that enable strict mode automatically.
|
||||
|
|
|
@ -95,7 +95,7 @@ There are subtle differences between `let` and `var`, but they do not matter for
|
|||
|
||||
## A real-life analogy
|
||||
|
||||
We can easily grasp the concept of a "variable" if we imagine it as a "box" for data, with a unique-named sticker on it.
|
||||
We can easily grasp the concept of a "variable" if we imagine it as a "box" for data, with a uniquely-named sticker on it.
|
||||
|
||||
For instance, the variable `message` can be imagined as a box labelled `"message"` with the value `"Hello!"` in it:
|
||||
|
||||
|
@ -139,9 +139,9 @@ alert(message); // Hello world!
|
|||
```smart header="Functional languages"
|
||||
It may be interesting to know that there also exist [functional](https://en.wikipedia.org/wiki/Functional_programming) programming languages that forbid changing a variable value. For example, [Scala](http://www.scala-lang.org/) or [Erlang](http://www.erlang.org/).
|
||||
|
||||
In such languages, once the value is stored "in the box" -- it's there forever. If we need to store something else -- the language forces to create a new box (declare a new variable), we can't reuse the old one.
|
||||
In such languages, once the value is stored "in the box", it's there forever. If we need to store something else, the language forces to create a new box (declare a new variable). We can't reuse the old one.
|
||||
|
||||
Though it may seem a little bit odd at first sight, these languages are quite capable of serious development. More than that, there are areas like parallel computations where this limitation confers certain benefits. Studying of such a language (even if not planning to use it soon) is recommended to broaden the mind.
|
||||
Though it may seem a little bit odd at first sight, these languages are quite capable of serious development. More than that, there are areas like parallel computations where this limitation confers certain benefits. Studying such a language (even if not planning to use it soon) is recommended to broaden the mind.
|
||||
```
|
||||
|
||||
## Variable naming [#variable-naming]
|
||||
|
@ -160,7 +160,7 @@ let test123;
|
|||
|
||||
When the name contains multiple words, [camelCase](https://en.wikipedia.org/wiki/CamelCase) is commonly used. That is: words go one after another, each word starts with a capital letter: `myVeryLongName`.
|
||||
|
||||
What's interesting -- the dollar sign `'$'` and the underscore `'_'` also can be used in names. They are regular symbols, just like letters, without any special meaning.
|
||||
What's interesting -- the dollar sign `'$'` and the underscore `'_'` can also be used in names. They are regular symbols, just like letters, without any special meaning.
|
||||
|
||||
These names are valid:
|
||||
|
||||
|
@ -209,7 +209,7 @@ let return = 5; // also can't name it "return", error!
|
|||
|
||||
````warn header="An assignment without `use strict`"
|
||||
|
||||
Normally, we need to define a variable before using it. But in the old times, it was technically possible to create a variable by a mere assignment of the value, without `let`. This still works now if we don't put `use strict`, the behavior is kept for compatibility with old scripts.
|
||||
Normally, we need to define a variable before using it. But in the old times, it was technically possible to create a variable by a mere assignment of the value, without `let`. This still works now if we don't put `use strict`. The behavior is kept for compatibility with old scripts.
|
||||
|
||||
```js run no-strict
|
||||
// note: no "use strict" in this example
|
||||
|
@ -239,7 +239,7 @@ To declare a constant (unchanging) variable, one can use `const` instead of `let
|
|||
const myBirthday = '18.04.1982';
|
||||
```
|
||||
|
||||
The variable declared using `const` are called "constants". They can not be changed. An attempt to do it would cause an error:
|
||||
Variables declared using `const` are called "constants". They cannot be changed. An attempt to do it would cause an error:
|
||||
|
||||
```js run
|
||||
const myBirthday = '18.04.1982';
|
||||
|
@ -254,7 +254,7 @@ When a programmer is sure that the variable should never change, he can use `con
|
|||
|
||||
There is a widespread practice to use constants as aliases for difficult-to-remember values that are known prior to execution.
|
||||
|
||||
Such constants are named using capitals and underscores.
|
||||
Such constants are named using capital letters and underscores.
|
||||
|
||||
Like this:
|
||||
|
||||
|
@ -273,9 +273,9 @@ Benefits:
|
|||
|
||||
- `COLOR_ORANGE` is much easier to remember than `"#FF7F00"`.
|
||||
- It is much easier to mistype in `"#FF7F00"` than in `COLOR_ORANGE`.
|
||||
- When reading the code -- `COLOR_ORANGE` is much more meaningful than `#FF7F00`.
|
||||
- When reading the code, `COLOR_ORANGE` is much more meaningful than `#FF7F00`.
|
||||
|
||||
When should we use capitals for a constant, and when -- name them normally? Let's make that clear.
|
||||
When should we use capitals for a constant, and when should we name them normally? Let's make that clear.
|
||||
|
||||
Being a "constant" just means that the value never changes. But there are constants that are known prior to execution (like a hexadecimal value for red), and there are those that are *calculated* in run-time, during the execution, but do not change after the assignment.
|
||||
|
||||
|
@ -296,7 +296,7 @@ Please name the variables sensibly. Take time to think if needed.
|
|||
|
||||
Variable naming is one of the most important and complex skills in programming. A quick glance at variable names can reveal which code is written by a beginner and which by an experienced developer.
|
||||
|
||||
In a real project, most of the time is spent on modifying and extending the existing code base, rather than writing something completely separate from the scratch. And when we return to the code after some time of doing something else, it's much easier to find the information that is well-labelled. Or, in other words, when the variables have good names.
|
||||
In a real project, most of the time is spent on modifying and extending the existing code base, rather than writing something completely separate from the scratch. And when we return to the code after some time of doing something else, it's much easier to find information that is well-labelled. Or, in other words, when the variables have good names.
|
||||
|
||||
Please spend some time thinking about the right name for a variable before declaring it. That will repay you a lot.
|
||||
|
||||
|
@ -326,7 +326,7 @@ Modern JavaScript minifiers and browsers optimize code well enough, so it won't
|
|||
We can declare variables to store data. That can be done using `var` or `let` or `const`.
|
||||
|
||||
- `let` -- is a modern variable declaration. The code must be in strict mode to use `let` in Chrome (V8).
|
||||
- `var` -- is an old-school variable declaration. Normally we don't use it at all, but we'll cover subtle differences from `let` in the chapter <info:var>, just in case if you'll need them.
|
||||
- `const` -- is like `let`, but the value of variable can't be changed.
|
||||
- `var` -- is an old-school variable declaration. Normally we don't use it at all, but we'll cover subtle differences from `let` in the chapter <info:var>, just in case you need them.
|
||||
- `const` -- is like `let`, but the value of the variable can't be changed.
|
||||
|
||||
Variables should be named in a way that allows to easily understand what's inside.
|
||||
Variables should be named in a way that allows us to easily understand what's inside.
|
||||
|
|
|
@ -10,7 +10,7 @@ message = 123456;
|
|||
|
||||
Programming languages that allow such things are called "dynamically typed", meaning that there are data types, but variables are not bound to any of them.
|
||||
|
||||
There are 7 basic data types in JavaScript. Here we'll study the basics, and in next chapters we'll talk about each of them in detail.
|
||||
There are seven basic data types in JavaScript. Here we'll study the basics, and in the next chapters we'll talk about each of them in detail.
|
||||
|
||||
[cut]
|
||||
|
||||
|
@ -62,7 +62,7 @@ The script will never stop with a fatal error ("die"). At worst we'll get `NaN`
|
|||
|
||||
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>.
|
||||
We'll see more about working with numbers in the chapter <info:number>.
|
||||
|
||||
## A string
|
||||
|
||||
|
@ -82,7 +82,7 @@ In JavaScript, there are 3 types of quotes.
|
|||
|
||||
Double and single quotes are "simple" quotes. There's no difference between them in JavaScript.
|
||||
|
||||
Backticks are "extended functionality" quotes. They allow to embed variables and expressions into a string by wrapping them in `${…}`, for example:
|
||||
Backticks are "extended functionality" quotes. They allow us to embed variables and expressions into a string by wrapping them in `${…}`, for example:
|
||||
|
||||
```js run
|
||||
let name = "John";
|
||||
|
@ -96,7 +96,7 @@ 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.
|
||||
|
||||
Please note that this only can be done in backticks, other quotes do not allow such embedding!
|
||||
Please note that this can only be done in backticks. Other quotes do not allow such embedding!
|
||||
```js run
|
||||
alert( "the result is ${1 + 2}" ); // the result is ${1 + 2} (double quotes do nothing)
|
||||
```
|
||||
|
@ -113,7 +113,7 @@ In JavaScript, there is no such type. There's only one type: `string`. A string
|
|||
|
||||
The boolean type has only two values: `true` and `false`.
|
||||
|
||||
This type is commonly used to store yes/no values: `true` means "yes, correct", and `false` means the "no, incorrect".
|
||||
This type is commonly used to store yes/no values: `true` means "yes, correct", and `false` means "no, incorrect".
|
||||
|
||||
For instance:
|
||||
|
||||
|
@ -178,7 +178,7 @@ alert(x); // "undefined"
|
|||
|
||||
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 in the chapter <info:object> after we know enough about primitives.
|
||||
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 of data and more complex entities. We'll deal with them later in the chapter <info:object> after we know enough about primitives.
|
||||
|
||||
The `symbol` type is used to create unique identifiers for objects. We have to mention it here for completeness, but it's better to study them after objects.
|
||||
|
||||
|
@ -238,10 +238,10 @@ There are 7 basic types in JavaScript.
|
|||
- `object` for more complex data structures.
|
||||
- `symbol` for unique identifiers.
|
||||
|
||||
The `typeof` operator allows to see which type is stored in the variable.
|
||||
The `typeof` operator allows us 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"`.
|
||||
- For `null` returns `"object"` -- that's the error in the language, it's not an object in fact.
|
||||
- For `null` returns `"object"` -- that's an error in the language, it's not an object in fact.
|
||||
|
||||
In the next chapters we'll concentrate on primitive values and once we're familiar with that, then we'll move on to objects.
|
||||
In the next chapters we'll concentrate on primitive values and once we're familiar with them, then we'll move on to objects.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# Type Conversions
|
||||
|
||||
Most of time, operators and functions automatically convert a value to the right type. That's called "type coercion".
|
||||
Most of the time, operators and functions automatically convert a value to the right type. That's called "type coercion".
|
||||
|
||||
For example, `alert` automatically converts any value to a string to show it. Mathematical operations convert values to numbers.
|
||||
|
||||
|
@ -14,7 +14,7 @@ In this chapter we don't cover objects yet. Here we study primitives first. Late
|
|||
|
||||
## ToString
|
||||
|
||||
The string conversion happens when we need a string form of a value.
|
||||
String conversion happens when we need the string form of a value.
|
||||
|
||||
For example, `alert(value)` does it to show the value.
|
||||
|
||||
|
@ -30,7 +30,7 @@ alert(typeof value); // string
|
|||
*/!*
|
||||
```
|
||||
|
||||
The string conversion is mostly obvious. A `false` becomes `"false"`, `null` becomes `"null"` etc.
|
||||
String conversion is mostly obvious. A `false` becomes `"false"`, `null` becomes `"null"` etc.
|
||||
|
||||
## ToNumber
|
||||
|
||||
|
@ -53,7 +53,7 @@ let num = Number(str); // becomes a number 123
|
|||
alert(typeof num); // number
|
||||
```
|
||||
|
||||
The explicit conversion is usually required when we read a value from a string-based source like a text form, but we expect a number to be entered.
|
||||
Explicit conversion is usually required when we read a value from a string-based source like a text form, but we expect a number to be entered.
|
||||
|
||||
If the string is not a valid number, the result of such conversion is `NaN`, for instance:
|
||||
|
||||
|
@ -70,7 +70,7 @@ Numeric conversion rules:
|
|||
|`undefined`|`NaN`|
|
||||
|`null`|`0`|
|
||||
|<code>true and false</code> | `1` and `0` |
|
||||
| `string` | Whitespaces from the start and the end are removed. Then, if the remaining string is empty, the result is `0`, otherwise -- the number is "read" from the string. An error gives `NaN`. |
|
||||
| `string` | Whitespaces from the start and the end are removed. Then, if the remaining string is empty, the result is `0`. Otherwise, the number is "read" from the string. An error gives `NaN`. |
|
||||
|
||||
Examples:
|
||||
|
||||
|
@ -131,9 +131,9 @@ alert( Boolean(" ") ); // spaces, also true (any non-empty string is true)
|
|||
|
||||
There are three most widely used type conversions: to string, to number and to boolean.
|
||||
|
||||
**`ToString`** -- occurs when we output something, can be performed with `String(value)`. The conversion to string is usually obvious for primitive values.
|
||||
**`ToString`** -- Occurs when we output something, can be performed with `String(value)`. The conversion to string is usually obvious for primitive values.
|
||||
|
||||
**`ToNumber`** -- occurs in math operations, can be performed with `Number(value)`.
|
||||
**`ToNumber`** -- Occurs in math operations, can be performed with `Number(value)`.
|
||||
|
||||
The conversion follows the rules:
|
||||
|
||||
|
@ -144,7 +144,7 @@ The conversion 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 becomes `0`. An error gives `NaN`. |
|
||||
|
||||
**`ToBoolean`** -- occurs in logical operations, or can be performed with `Boolean(value)`.
|
||||
**`ToBoolean`** -- Occurs in logical operations, or can be performed with `Boolean(value)`.
|
||||
|
||||
Follows the rules:
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
# Operators
|
||||
|
||||
Many operators are known to us from school. It is an addition `+`, a multiplication `*`, a subtraction `-` and so on.
|
||||
Many operators are known to us from school. They are addition `+`, a multiplication `*`, a subtraction `-` and so on.
|
||||
|
||||
In this chapter we concentrate on aspects that are not covered by the school arithmetic.
|
||||
In this chapter we concentrate on aspects that are not covered by school arithmetic.
|
||||
|
||||
[cut]
|
||||
|
||||
|
@ -28,7 +28,7 @@ Before we move on, let's grasp the common terminology.
|
|||
alert( y - x ); // 2, binary minus subtracts values
|
||||
```
|
||||
|
||||
Formally, we're talking about the two different operators here: the unary negation (single operand, reverses the sign) and the binary subtraction (two operands, subtracts).
|
||||
Formally, we're talking about two different operators here: the unary negation (single operand, reverses the sign) and the binary subtraction (two operands, subtracts).
|
||||
|
||||
## Strings concatenation, binary +
|
||||
|
||||
|
@ -43,7 +43,7 @@ let s = "my" + "string";
|
|||
alert(s); // mystring
|
||||
```
|
||||
|
||||
Note that if any of operands is a string, then the other one is converted to string too.
|
||||
Note that if any of operands is a string, then the other one is converted to a string too.
|
||||
|
||||
For example:
|
||||
|
||||
|
@ -52,9 +52,9 @@ alert( '1' + 2 ); // "12"
|
|||
alert( 2 + '1' ); // "21"
|
||||
```
|
||||
|
||||
See, it doesn't matter whether the first operand is a string or the second one. The rule is simple: if any of operands is a string, then convert the other one into a string as well.
|
||||
See, it doesn't matter whether the first operand is a string or the second one. The rule is simple: if either operand is a string, then convert the other one into a string as well.
|
||||
|
||||
The string concatenation and conversion is the special feature of the binary plus `"+"`. Other arithmetic operators work only with numbers. They always convert their operands to numbers.
|
||||
String concatenation and conversion is a special feature of the binary plus `"+"`. Other arithmetic operators work only with numbers. They always convert their operands to numbers.
|
||||
|
||||
For instance, subtraction and division:
|
||||
|
||||
|
@ -88,7 +88,7 @@ alert( +"" ); // 0
|
|||
|
||||
It actually does the same as `Number(...)`, but shorter.
|
||||
|
||||
A need to convert string to number arises very often. For example, if we are getting values from HTML form fields, then are usually strings.
|
||||
A need to convert string to number arises very often. For example, if we are getting values from HTML form fields, then they are usually strings.
|
||||
|
||||
What if we want to sum them?
|
||||
|
||||
|
@ -116,7 +116,7 @@ alert( +apples + +oranges ); // 5
|
|||
// alert( Number(apples) + Number(oranges) ); // 5
|
||||
```
|
||||
|
||||
From a mathematician's standpoint the abundance of pluses may seem strange. But from a programmer's standpoint -- there's nothing special: unary pluses are applied first, they convert strings to numbers, and then the binary plus sums them up.
|
||||
From a mathematician's standpoint the abundance of pluses may seem strange. But from a programmer's standpoint, there's nothing special: unary pluses are applied first, they convert strings to numbers, and then the binary plus sums them up.
|
||||
|
||||
Why are unary pluses applied to values before the binary one? As we're going to see, that's because of their *higher precedence*.
|
||||
|
||||
|
@ -124,11 +124,11 @@ Why are unary pluses applied to values before the binary one? As we're going to
|
|||
|
||||
If an expression has more than one operator, the execution order is defined by their *precedence*, or, in other words, there's an implicit priority order among the operators.
|
||||
|
||||
From the school we all know that the multiplication in the expression `1 + 2 * 2` should be calculated before the addition. That's exactly the precedence thing. The multiplication is said to have *a higher precedence* than the addition.
|
||||
From school we all know that the multiplication in the expression `1 + 2 * 2` should be calculated before the addition. That's exactly the precedence thing. The multiplication is said to have *a higher precedence* than the addition.
|
||||
|
||||
Parentheses override any precedence, so if we're not satisfied with the order, we can use them, like: `(1 + 2) * 2`.
|
||||
|
||||
There are many operators in JavaScript. Every operator has a corresponding precedence number. The one with the bigger number executes first. If the precedence is same -- the execution order is from left to right.
|
||||
There are many operators in JavaScript. Every operator has a corresponding precedence number. The one with the bigger number executes first. If the precedence is the same, the execution order is from left to right.
|
||||
|
||||
An extract from the [precedence table](https://developer.mozilla.org/en/JavaScript/Reference/operators/operator_precedence) (you don't need to remember this, but note that unary operators are higher than corresponding binary ones):
|
||||
|
||||
|
@ -145,7 +145,7 @@ An extract from the [precedence table](https://developer.mozilla.org/en/JavaScri
|
|||
| 3 | assignment | `=` |
|
||||
| ... | ... | ... |
|
||||
|
||||
As we can see, the "unary plus" has a priority of `16`, higher than `13` for the "addition" (binary plus). That's why in the expression `"+apples + +oranges"` unary pluses work first, and then the addition.
|
||||
As we can see, the "unary plus" has a priority of `16`, which is higher than `13` for the "addition" (binary plus). That's why in the expression `"+apples + +oranges"` unary pluses work first, and then the addition.
|
||||
|
||||
## Assignment
|
||||
|
||||
|
@ -180,7 +180,7 @@ An operator always returns a value. That's obvious for most of them like an addi
|
|||
|
||||
The call `x = value` writes the `value` into `x` *and then returns it*.
|
||||
|
||||
Here's the demo that uses an assignment as the part of a more complex expression:
|
||||
Here's the demo that uses an assignment as part of a more complex expression:
|
||||
|
||||
```js run
|
||||
let a = 1;
|
||||
|
@ -266,13 +266,13 @@ Operators `++` and `--` can be placed both after and before the variable.
|
|||
- When the operator goes after the variable, it is called a "postfix form": `counter++`.
|
||||
- The "prefix form" is when the operator stands before the variable: `++counter`.
|
||||
|
||||
Both of these records do the same: increase `i` by `1`.
|
||||
Both of these records do the same: increase `counter` by `1`.
|
||||
|
||||
Is there any difference? Yes, but we can only see it if we use the returned value of `++/--`.
|
||||
|
||||
Let's clarify. As we know, all operators return a value. Increment/decrement is not an exception here. The prefix form returns the new value, while the postfix form returns the old value (prior to increment/decrement).
|
||||
|
||||
To see the difference -- here's the example:
|
||||
To see the difference, here's the example:
|
||||
|
||||
```js run
|
||||
let counter = 1;
|
||||
|
@ -296,7 +296,7 @@ In the line `(*)` the *postfix* form `counter++` also increments `i`, but return
|
|||
|
||||
To summarize:
|
||||
|
||||
- If the result of increment/decrement is not used, then there is no difference which form to use:
|
||||
- If the result of increment/decrement is not used, then there is no difference in which form to use:
|
||||
|
||||
```js run
|
||||
let counter = 0;
|
||||
|
@ -403,7 +403,7 @@ alert( n ); // 16 (right part evaluated first, same as n *= 8)
|
|||
|
||||
The comma operator `','` is one of most rare and unusual operators. Sometimes it's used to write shorter code, so we need to know it in order to understand what's going on.
|
||||
|
||||
The comma operator allows to evaluate several expressions, dividing them with a comma `','`. Each of them is evaluated, but result of only the last one is returned.
|
||||
The comma operator allows us to evaluate several expressions, dividing them with a comma `','`. Each of them is evaluated, but the result of only the last one is returned.
|
||||
|
||||
For example:
|
||||
|
||||
|
@ -436,4 +436,4 @@ for (*!*a = 1, b = 3, c = a * b*/!*; a < 10; a++) {
|
|||
}
|
||||
```
|
||||
|
||||
Such tricks are used in many JavaScript frameworks, that's why we mention about them. But usually they don't improve the code readability, so we should think well before writing like that.
|
||||
Such tricks are used in many JavaScript frameworks, that's why we mention them. But usually they don't improve the code readability, so we should think well before writing like that.
|
||||
|
|
|
@ -86,7 +86,7 @@ alert( false == 0 ); // true
|
|||
```
|
||||
|
||||
````smart header="A funny consequence"
|
||||
It is possible that in the same time:
|
||||
It is possible that at the same time:
|
||||
|
||||
- Two values are equal.
|
||||
- One of them is `true` as a boolean and the other one is `false` as a boolean.
|
||||
|
@ -103,7 +103,7 @@ alert( Boolean(b) ); // true
|
|||
alert(a == b); // true!
|
||||
```
|
||||
|
||||
From JavaScript standpoint that's quite normal. An equality check converts using the numeric conversion (hence `"0"` becomes `0`), while `Boolean` conversion uses another set of rules.
|
||||
From JavaScript's standpoint that's quite normal. An equality check converts using the numeric conversion (hence `"0"` becomes `0`), while `Boolean` conversion uses another set of rules.
|
||||
````
|
||||
|
||||
## Strict equality
|
||||
|
@ -126,7 +126,7 @@ What to do if we'd like to differentiate `0` from `false`?
|
|||
|
||||
**A strict equality operator `===` checks the equality without type conversion.**
|
||||
|
||||
In other words, if `a` and `b` are of different types then `a === b` immediately returns `false`, without an attempt to convert them.
|
||||
In other words, if `a` and `b` are of different types, then `a === b` immediately returns `false` without an attempt to convert them.
|
||||
|
||||
Let's try it:
|
||||
|
||||
|
@ -142,7 +142,7 @@ The strict equality check operator is a bit longer to write, but makes it obviou
|
|||
|
||||
Let's see more edge cases.
|
||||
|
||||
There's a non-intuitive behavior when `null` or `undefined` is compared with other values.
|
||||
There's a non-intuitive behavior when `null` or `undefined` are compared with other values.
|
||||
|
||||
|
||||
For a strict equality check `===`
|
||||
|
@ -174,7 +174,7 @@ alert( null == 0 ); // (2) false
|
|||
alert( null >= 0 ); // (3) *!*true*/!*
|
||||
```
|
||||
|
||||
Yeah, mathematically that's strange. The last result states that "`null` is equal or greater than zero". Then one of the comparisons above must be correct, but they are both falsy.
|
||||
Yeah, mathematically that's strange. The last result states that "`null` is greater than or equal to zero". Then one of the comparisons above must be correct, but they are both falsy.
|
||||
|
||||
The reason is that an equality check `==` and comparisons `> < >= <=` work differently. Comparisons convert `null` to a number, hence treat it as `0`. That's why (3) `null >= 0` is true and (1) `null > 0` is false.
|
||||
|
||||
|
@ -199,7 +199,7 @@ We've got these results because:
|
|||
|
||||
### Evade problems
|
||||
|
||||
Why did we observe these examples? Should we remember these pecularities all the time? Well, not really. Actually, these tricky things will gradually become familiar over the time, but there's a solid way to evade any problems with them.
|
||||
Why did we observe these examples? Should we remember these peculiarities all the time? Well, not really. Actually, these tricky things will gradually become familiar over time, but there's a solid way to evade any problems with them.
|
||||
|
||||
Just treat any comparison with `undefined/null` except the strict equality `===` with exceptional care.
|
||||
|
||||
|
@ -211,4 +211,4 @@ Don't use comparisons `>= > < <=` with a variable which may be `null/undefined`,
|
|||
- Strings are compared letter-by-letter in the "dictionary" order.
|
||||
- When values of different types are compared, they get converted to numbers (with the exclusion of a strict equality check).
|
||||
- Values `null` and `undefined` equal `==` each other and do not equal any other value.
|
||||
- Be careful when using comparisons like `>` or `<` with variables that can occasionaly be `null/undefined`. Making a separate check for `null/undefined` is a good idea.
|
||||
- Be careful when using comparisons like `>` or `<` with variables that can occasionally be `null/undefined`. Making a separate check for `null/undefined` is a good idea.
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
This part of the tutorial aims to cover JavaScript "as is", without environment-specific tweaks.
|
||||
|
||||
But still we use a browser as the demo environment. So we should know at least few user-interface functions. In this chapter we'll get familiar with the browser functions `alert`, `prompt` and `confirm`.
|
||||
But still we use a browser as the demo environment. So we should know at least a few user-interface functions. In this chapter we'll get familiar with the browser functions `alert`, `prompt` and `confirm`.
|
||||
|
||||
[cut]
|
||||
|
||||
|
@ -40,7 +40,7 @@ It shows a modal window with a text message, an input field for the visitor and
|
|||
`default`
|
||||
: An optional second parameter, the initial value for the input field.
|
||||
|
||||
The visitor may type something in the prompt input field and press OK. Or they can cancel the input by pressing a CANCEL button or hitting the `key:Esc` key.
|
||||
The visitor may type something in the prompt input field and press OK. Or they can cancel the input by pressing the CANCEL button or hitting the `key:Esc` key.
|
||||
|
||||
The call to `prompt` returns the text from the field or `null` if the input was canceled.
|
||||
|
||||
|
|
|
@ -2,13 +2,13 @@
|
|||
|
||||
Sometimes we need to perform different actions based on a condition.
|
||||
|
||||
There is `if` statement for that and also the conditional (ternary) operator for conditional evaluation which we will be referring as “question mark” operator: `"?"` for simplicity.
|
||||
There is the `if` statement for that and also the conditional (ternary) operator for conditional evaluation which we will be referring as the “question mark” operator: `"?"` for simplicity.
|
||||
|
||||
[cut]
|
||||
|
||||
## The "if" statement
|
||||
|
||||
The "if" statement gets a condition, evaluates it and -- if the result is `true` -- executes the code.
|
||||
The "if" statement gets a condition, evaluates it and, if the result is `true`, executes the code.
|
||||
|
||||
For example:
|
||||
|
||||
|
@ -22,7 +22,7 @@ if (year == 2015) alert( 'You are right!' );
|
|||
|
||||
In the example above, the condition is a simple equality check: `year == 2015`, but it can be much more complex.
|
||||
|
||||
If there is more than one command to execute -- we can use a code block in figure brackets:
|
||||
If there is more than one command to execute, we can use a code block in figure brackets:
|
||||
|
||||
```js
|
||||
if (year == 2015) {
|
||||
|
@ -101,7 +101,7 @@ if (year < 2015) {
|
|||
}
|
||||
```
|
||||
|
||||
In the code above JavaScript first checks `year < 2015`, if it is falsy then goes to the next condition `year > 2015`, and otherwise shows the last `alert`.
|
||||
In the code above JavaScript first checks `year < 2015`. If it is falsy it then goes to the next condition `year > 2015`, and otherwise shows the last `alert`.
|
||||
|
||||
There can be more `else if` blocks. The ending `else` is optional.
|
||||
|
||||
|
@ -128,7 +128,7 @@ alert(accessAllowed);
|
|||
|
||||
The so-called "ternary" or "question mark" operator lets us do that shorter and simpler.
|
||||
|
||||
The operator is represented by a question mark `"?"`. The formal term "ternary" means that the operator has 3 operands. It is actually the one and only operator in JavaScript which has that many.
|
||||
The operator is represented by a question mark `"?"`. The formal term "ternary" means that the operator has three operands. It is actually the one and only operator in JavaScript which has that many.
|
||||
|
||||
The syntax is:
|
||||
```js
|
||||
|
@ -151,7 +151,7 @@ Technically, we can omit parentheses around `age > 18`. The question mark operat
|
|||
let accessAllowed = age > 18 ? true : false;
|
||||
```
|
||||
|
||||
...But parentheses make the code more readable. So it's recommended to put them.
|
||||
...But parentheses make the code more readable. So it's recommended to use them.
|
||||
|
||||
````smart
|
||||
In the example above it's possible to evade the question mark operator, because the comparison by itself returns `true/false`:
|
||||
|
@ -214,13 +214,13 @@ let company = prompt('Which company created JavaScript?', '');
|
|||
|
||||
Depending on the condition `company == 'Netscape'`, either the first or the second part after `"?"` gets executed and shows the alert.
|
||||
|
||||
We don't assign a result to a variable here, the idea is to execute different code depending on the condition.
|
||||
We don't assign a result to a variable here. The idea is to execute different code depending on the condition.
|
||||
|
||||
**It is not recommended to use the question mark operator in this way.**
|
||||
|
||||
The notation seem to be shorter than `if`, that appeals to some programmers. But it is less readable.
|
||||
The notation seems to be shorter than `if`, which appeals to some programmers. But it is less readable.
|
||||
|
||||
Here is the same with `if` for comparison:
|
||||
Here is the same code with `if` for comparison:
|
||||
|
||||
```js run no-beautify
|
||||
let company = prompt('Which company created JavaScript?', '');
|
||||
|
|
|
@ -41,7 +41,7 @@ if (1 || 0) { // works just like if( true || false )
|
|||
}
|
||||
```
|
||||
|
||||
Most of the time, OR `||` is used in `if` to test if *any* of given conditions is correct.
|
||||
Most of the time, OR `||` is used in an `if` statement to test if *any* of the given conditions is correct.
|
||||
|
||||
For example:
|
||||
|
||||
|
@ -80,13 +80,13 @@ result = value1 || value2 || value3;
|
|||
|
||||
The OR `"||"` operator does the following:
|
||||
|
||||
- Evalute operands from left to right.
|
||||
- For each operand, convert it to boolean. If the result is `true`, then stop and return that the original value of that operand.
|
||||
- Evaluate operands from left to right.
|
||||
- For each operand, convert it to boolean. If the result is `true`, then stop and return the original value of that operand.
|
||||
- If all other operands have been assessed (i.e. all were `falsy`), return the last operand.
|
||||
|
||||
A value is returned in its original form, without the conversion.
|
||||
|
||||
In other words, a chain of OR `"||"` returns the first truthy value or the last one if no such value found.
|
||||
In other words, a chain of OR `"||"` returns the first truthy value or the last one if no such value is found.
|
||||
|
||||
For instance:
|
||||
|
||||
|
@ -147,7 +147,7 @@ That leads to some interesting usages compared to a "pure, classical, boolean-on
|
|||
|
||||
An assignment is a simple case, other side effects can be involved.
|
||||
|
||||
As we can see, such use case is a "shorter way to do `if`". The first operand is converted to boolean and if it's false then the second one is evaluated.
|
||||
As we can see, such a use case is a "shorter way to do `if`". The first operand is converted to boolean and if it's false then the second one is evaluated.
|
||||
|
||||
Most of time it's better to use a "regular" `if` to keep the code easy to understand, but sometimes that can be handy.
|
||||
|
||||
|
@ -198,7 +198,7 @@ result = value1 && value2 && value3;
|
|||
|
||||
The AND `"&&"` operator does the following:
|
||||
|
||||
- Evalute operands from left to right.
|
||||
- Evaluate operands from left to right.
|
||||
- For each operand, convert it to a boolean. If the result is `false`, stop and return the original value of that operand.
|
||||
- If all other operands have been assessed (i.e. all were truthy), return the last operand.
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
We often have a need to perform similar actions many times in a row.
|
||||
|
||||
For example, when we need to output goods from the list one after another. Or just run the same code for each number from 1 to 10.
|
||||
For example, when we need to output goods from a list one after another. Or just run the same code for each number from 1 to 10.
|
||||
|
||||
*Loops* are a way to repeat the same part of code multiple times.
|
||||
|
||||
|
@ -19,7 +19,7 @@ while (condition) {
|
|||
}
|
||||
```
|
||||
|
||||
While the `condition` is `true` -- the `code` from the loop body is executed.
|
||||
While the `condition` is `true`, the `code` from the loop body is executed.
|
||||
|
||||
For instance, the loop below outputs `i` while `i<3`:
|
||||
|
||||
|
@ -31,7 +31,7 @@ while (i < 3) { // shows 0, then 1, then 2
|
|||
}
|
||||
```
|
||||
|
||||
A single execution of the loop body is called *an iteration*. The loop in the example above makes 3 iterations.
|
||||
A single execution of the loop body is called *an iteration*. The loop in the example above makes three iterations.
|
||||
|
||||
If there were no `i++` in the example above, the loop would repeat (in theory) forever. In practice, the browser provides ways to stop such loops, and for server-side JavaScript we can kill the process.
|
||||
|
||||
|
@ -70,7 +70,7 @@ do {
|
|||
} while (condition);
|
||||
```
|
||||
|
||||
The loop will first execute the body, then check the condition, and while it's truthy -- execute it again and again.
|
||||
The loop will first execute the body, then check the condition and, while it's truthy, execute it again and again.
|
||||
|
||||
For example:
|
||||
|
||||
|
@ -82,7 +82,7 @@ do {
|
|||
} while (i < 3);
|
||||
```
|
||||
|
||||
This form of syntax is rarely used except when you want the body of the loop to execute **at least once** regardless of the condition being truthy. Usually, the other form is preferred: `while(…) {…}`.
|
||||
This form of syntax is rarely used except when you want the body of the loop to execute **at least once** regardless of the condition being truthy. Usually, the other form is preferred: `while(…) {…}`.
|
||||
|
||||
## The "for" loop
|
||||
|
||||
|
@ -231,7 +231,7 @@ alert( 'Sum: ' + sum );
|
|||
|
||||
The `break` directive is activated in the line `(*)` if the user enters an empty line or cancels the input. It stops the loop immediately, passing the control to the first line after the loop. Namely, `alert`.
|
||||
|
||||
The combination: "infinite loop + `break` as needed" is great for situations when the condition must be checked not in beginning/end of the loop, but in the middle. Or even in several places of the body.
|
||||
The combination "infinite loop + `break` as needed" is great for situations when the condition must be checked not in the beginning/end of the loop, but in the middle, or even in several places of the body.
|
||||
|
||||
## Continue to the next iteration [#continue]
|
||||
|
||||
|
@ -266,7 +266,7 @@ for (let i = 0; i < 10; i++) {
|
|||
}
|
||||
```
|
||||
|
||||
From the technical point of view it's identical to the example above. Surely, we can just wrap the code in the `if` block instead of `continue`.
|
||||
From a technical point of view it's identical to the example above. Surely, we can just wrap the code in the `if` block instead of `continue`.
|
||||
|
||||
But as a side-effect we got one more figure brackets nesting level. If the code inside `if` is longer than a few lines, that may decrease the overall readability.
|
||||
````
|
||||
|
@ -360,12 +360,12 @@ outer:
|
|||
for (let i = 0; i < 3; i++) { ... }
|
||||
```
|
||||
|
||||
The `continue` directive can also be used with a label. In this case the execution jumps to the next iteration of the labelled loop.
|
||||
The `continue` directive can also be used with a label. In this case the execution jumps to the next iteration of the labeled loop.
|
||||
|
||||
````warn header="Labels are not a \"goto\""
|
||||
Labels do not allow to jump into an arbitrary place of code.
|
||||
Labels do not allow us to jump into an arbitrary place of code.
|
||||
|
||||
For example, it is impossible to do like this:
|
||||
For example, it is impossible to do this:
|
||||
```js
|
||||
break label; // jumps to label? No.
|
||||
|
||||
|
@ -379,12 +379,12 @@ The call to a `break/continue` is only possible from inside the loop, and the la
|
|||
|
||||
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.
|
||||
- `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.
|
||||
|
||||
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.
|
||||
|
||||
If we don't want to do anything on the current iteration and would like to forward to the next one -- the `continue` directive does it.
|
||||
If we don't want to do anything on the current iteration and would like to forward to the next one, the `continue` directive does it.
|
||||
|
||||
`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.
|
||||
|
|
|
@ -28,9 +28,9 @@ switch(x) {
|
|||
}
|
||||
```
|
||||
|
||||
- The value of `x` is checked for a strict equality to the value from the first `case`, that is: `value1`, then to the second `value2` and so on.
|
||||
- If the equality is found -- `switch` starts to execute the code starting from the corresponding `case`, and to the nearest `break` (or to the end of `switch`).
|
||||
- If no case matched then the `default` code is executed (if exists).
|
||||
- The value of `x` is checked for a strict equality to the value from the first `case` (that is, `value1`) then to the second (`value2`) and so on.
|
||||
- If the equality is found, `switch` starts to execute the code starting from the corresponding `case`, until the nearest `break` (or until the end of `switch`).
|
||||
- If no case is matched then the `default` code is executed (if it exists).
|
||||
|
||||
## An example
|
||||
|
||||
|
@ -58,7 +58,7 @@ switch (a) {
|
|||
|
||||
Here the `switch` starts to compare `a` from the first `case` variant that is `3`. The match fails.
|
||||
|
||||
Then `4`. That's the match, so the execution starts from `case 4` and till the nearest `break`.
|
||||
Then `4`. That's a match, so the execution starts from `case 4` until the nearest `break`.
|
||||
|
||||
**If there is no `break` then the execution continues with the next `case` without any checks.**
|
||||
|
||||
|
@ -89,8 +89,8 @@ alert( 'Too big' );
|
|||
alert( "I don't know such values" );
|
||||
```
|
||||
|
||||
````smart header="Any expresion can be a `switch/case` argument"
|
||||
Both `switch` and case allow arbitrary expressions.
|
||||
````smart header="Any expression can be a `switch/case` argument"
|
||||
Both `switch` and `case` allow arbitrary expressions.
|
||||
|
||||
For example:
|
||||
|
||||
|
@ -141,7 +141,7 @@ switch (a) {
|
|||
|
||||
Now both `3` and `5` show the same message.
|
||||
|
||||
The ability to "group" cases a side-effect of how `switch/case` works without `break`. Here the execution of `case 3` starts from the line `(*)` and goes through `case 5`, because there's no `break`.
|
||||
The ability to "group" cases is a side-effect of how `switch/case` works without `break`. Here the execution of `case 3` starts from the line `(*)` and goes through `case 5`, because there's no `break`.
|
||||
|
||||
## Type matters
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ The call `showMessage()` executes the code of the function. Here we will see the
|
|||
|
||||
This example clearly demonstrates one of the main purposes of functions: to evade code duplication.
|
||||
|
||||
If we ever need to change the message or the way it is shown -- it's enough to modify the code in one place: the function which outputs it.
|
||||
If we ever need to change the message or the way it is shown, it's enough to modify the code in one place: the function which outputs it.
|
||||
|
||||
## Local variables
|
||||
|
||||
|
@ -105,7 +105,7 @@ alert( userName ); // *!*Bob*/!*, the value was modified by the function
|
|||
|
||||
The outer variable is only used if there's no local one. So an occasional modification may happen if we forget `let`.
|
||||
|
||||
If a same-named variable is declared inside the function then it *shadows* the outer one. For instance, in the code below the function uses the local `userName`, the outer one is ignored:
|
||||
If a same-named variable is declared inside the function then it *shadows* the outer one. For instance, in the code below the function uses the local `userName`. The outer one is ignored:
|
||||
|
||||
```js run
|
||||
let userName = 'John';
|
||||
|
@ -130,12 +130,12 @@ Variables declared outside of any function, such as the outer `userName` in the
|
|||
|
||||
Global variables are visible from any function (unless shadowed by locals).
|
||||
|
||||
Usually, a function declares all variables specific to its task, and global variables only store project-level data, so important that it really must be seen from anywhere. Modern code has few or no globals, most variables reside in their functions.
|
||||
Usually, a function declares all variables specific to its task, and global variables only store project-level data, so important that it really must be seen from anywhere. Modern code has few or no globals. Most variables reside in their functions.
|
||||
```
|
||||
|
||||
## Parameters
|
||||
|
||||
We can pass arbitrary data to function using parameters (also called *function arguments*) .
|
||||
We can pass arbitrary data to functions using parameters (also called *function arguments*) .
|
||||
|
||||
In the example below, the function has two parameters: `from` and `text`.
|
||||
|
||||
|
@ -183,7 +183,7 @@ For instance, the aforementioned function `showMessage(from, text)` can be calle
|
|||
showMessage("Ann");
|
||||
```
|
||||
|
||||
That's not an error. Such call would output `"Ann: undefined"`. There's no `text`, so it's assumed that `text === undefined`.
|
||||
That's not an error. Such a call would output `"Ann: undefined"`. There's no `text`, so it's assumed that `text === undefined`.
|
||||
|
||||
If we want to use a "default" `text` in this case, then we can specify it after `=`:
|
||||
|
||||
|
@ -255,7 +255,7 @@ alert( result ); // 3
|
|||
|
||||
The directive `return` can be in any place of the function. When the execution reaches it, the function stops, and the value is returned to the calling code (assigned to `result` above).
|
||||
|
||||
There may be many occurences of `return` in a single function. For instance:
|
||||
There may be many occurrences of `return` in a single function. For instance:
|
||||
|
||||
```js run
|
||||
function checkAge(age) {
|
||||
|
@ -340,7 +340,7 @@ Functions are actions. So their name is usually a verb. It should briefly, but a
|
|||
|
||||
It is a widespread practice to start a function with a verbal prefix which vaguely describes the action. There must be an agreement within the team on the meaning of the prefixes.
|
||||
|
||||
For instance, functions that start with `"show"` -- usually show something.
|
||||
For instance, functions that start with `"show"` usually show something.
|
||||
|
||||
Function starting with...
|
||||
|
||||
|
@ -359,20 +359,20 @@ createForm(..) // creates a form (and usually returns it)
|
|||
checkPermission(..) // checks a permission, returns true/false
|
||||
```
|
||||
|
||||
With prefixes at place, a glance at a function name gives an understanding what kind of work it does and what kind of value it returns.
|
||||
With prefixes in place, a glance at a function name gives an understanding what kind of work it does and what kind of value it returns.
|
||||
|
||||
```smart header="One function -- one action"
|
||||
A function should do exactly what is suggested by its name, no more.
|
||||
|
||||
Two independant actions usually deserve two functions, even if they are usually called together (in that case we can make a 3rd function that calls those two).
|
||||
Two independent actions usually deserve two functions, even if they are usually called together (in that case we can make a 3rd function that calls those two).
|
||||
|
||||
Few examples of breaking this rule:
|
||||
A few examples of breaking this rule:
|
||||
|
||||
- `getAge` -- would be bad if it shows an `alert` with the age (should only get).
|
||||
- `createForm` -- would be bad if it modifies the document, adding a form to it (should only create it and return).
|
||||
- `checkPermission` -- would be bad if displays the `access granted/denied` message (should only perform the check and return the result).
|
||||
|
||||
These examples assume common meanings of prefixes. What they mean for you is determined by you and your team. Maybe it's pretty normal for your code to behave differently. But you should have a firm understanding of what a prefix means, what a prefixed function can and what it cannot do. All same-prefixed functions should obey the rules. And the team should share the knowledge.
|
||||
These examples assume common meanings of prefixes. What they mean for you is determined by you and your team. Maybe it's pretty normal for your code to behave differently. But you should have a firm understanding of what a prefix means, what a prefixed function can and cannot do. All same-prefixed functions should obey the rules. And the team should share the knowledge.
|
||||
```
|
||||
|
||||
```smart header="Ultrashort function names"
|
||||
|
@ -385,7 +385,7 @@ These are exceptions. Generally functions names should be concise, but descripti
|
|||
|
||||
## Functions == Comments
|
||||
|
||||
Functions should be short and do exactly one thing. If that thing is big, maybe it's worth to split the function into few smaller functions. Sometimes following this rule may not be that easy, but it's a definitely good thing.
|
||||
Functions should be short and do exactly one thing. If that thing is big, maybe it's worth it to split the function into a few smaller functions. Sometimes following this rule may not be that easy, but it's definitely a good thing.
|
||||
|
||||
A separate function is not only easier to test and debug -- its very existence is a great comment!
|
||||
|
||||
|
@ -440,7 +440,7 @@ function name(parameters, delimited, by, comma) {
|
|||
}
|
||||
```
|
||||
|
||||
- Values passed to function as parameters are copied to its local variables.
|
||||
- Values passed to a function as parameters are copied to its local variables.
|
||||
- A function may access outer variables. But it works only from inside out. The code outside of the function doesn't see its local variables.
|
||||
- A function can return a value. If it doesn't then its result is `undefined`.
|
||||
|
||||
|
@ -454,4 +454,4 @@ Function naming:
|
|||
- A function is an action, so function names are usually verbal.
|
||||
- There exist many well-known function prefixes like `create…`, `show…`, `get…`, `check…` and so on. Use them to hint what a function does.
|
||||
|
||||
Functions are the main building blocks of scripts. Now we covered the basics, so we actually can start creating and using them. But that's only the beginning of the path. We are going to return to them many times, going more deeply in their advanced features.
|
||||
Functions are the main building blocks of scripts. Now we've covered the basics, so we actually can start creating and using them. But that's only the beginning of the path. We are going to return to them many times, going more deeply into their advanced features.
|
||||
|
|
|
@ -22,7 +22,7 @@ let sayHi = function() {
|
|||
};
|
||||
```
|
||||
|
||||
Here the function is created and assigned to the variable explicitly, like any other value. No matter, how the function is defined -- it's just a value, stored in the variable `sayHi`.
|
||||
Here the function is created and assigned to the variable explicitly, like any other value. No matter how the function is defined, it's just a value stored in the variable `sayHi`.
|
||||
|
||||
|
||||
The meaning of these code samples is the same: "create a function and put it into the variable `sayHi`".
|
||||
|
@ -39,9 +39,9 @@ alert( sayHi ); // shows the function code
|
|||
*/!*
|
||||
```
|
||||
|
||||
Please note that the last line does not run the function, because there are no parentheses after `sayHi`. There are programming languages where any mention of a function name causes the execution, but JavaScript is not like that.
|
||||
Please note that the last line does not run the function, because there are no parentheses after `sayHi`. There are programming languages where any mention of a function name causes its execution, but JavaScript is not like that.
|
||||
|
||||
In JavaScript, a function is a value and we can deal with that as a value. The code above shows its string representation, that is the source code.
|
||||
In JavaScript, a function is a value and we can deal with it as a value. The code above shows its string representation, that is the source code.
|
||||
|
||||
It is a special value of course, in the sense that we can call it like `sayHi()`.
|
||||
|
||||
|
@ -60,7 +60,7 @@ func(); // Hello // (3) run the copy (it works)!
|
|||
sayHi(); // Hello // this still works too (why wouldn't it)
|
||||
```
|
||||
|
||||
That's what happens above in detail:
|
||||
Here's what happens above in detail:
|
||||
|
||||
1. Function Declaration `(1)` creates the function and puts it into the variable named `sayHi`.
|
||||
2. Line `(2)` copies it into variable `func`.
|
||||
|
@ -81,7 +81,7 @@ Everything would work the same. Even more obvious what's going on, right?
|
|||
|
||||
|
||||
````smart header="Why there's a semicolon at the end?"
|
||||
There might be a question, why Function Expression has a semicolon `;` at the end, and Function Declaration does not:
|
||||
There might be a question, why does Function Expression have a semicolon `;` at the end, and Function Declaration does not:
|
||||
|
||||
```js
|
||||
function sayHi() {
|
||||
|
@ -94,8 +94,8 @@ let sayHi = function() {
|
|||
```
|
||||
|
||||
The answer is simple:
|
||||
- There's no need in `;` at the end of code blocks and syntax structures that use them like `if { ... }`, `for { }`, `function f { }` etc.
|
||||
- A Function Expression is used inside the statement: `let sayHi = ...;`, as a value. It's not a code block. The semicolon `;` is recommended at the end of statements, no matter what is the value. So the semicolon here is not related to Function Expression itself in any way, it just terminates the statement.
|
||||
- There's no need for `;` at the end of code blocks and syntax structures that use them like `if { ... }`, `for { }`, `function f { }` etc.
|
||||
- A Function Expression is used inside the statement: `let sayHi = ...;`, as a value. It's not a code block. The semicolon `;` is recommended at the end of statements, no matter what is the value. So the semicolon here is not related to the Function Expression itself in any way, it just terminates the statement.
|
||||
````
|
||||
|
||||
## Callback functions
|
||||
|
@ -135,13 +135,13 @@ function showCancel() {
|
|||
ask("Do you agree?", showOk, showCancel);
|
||||
```
|
||||
|
||||
Before we'll explore how we can write it in a much shorter way, let's note that in the browser (and on the server-side in some cases) such functions are quite popular.
|
||||
Before we explore how we can write it in a much shorter way, let's note that in the browser (and on the server-side in some cases) such functions are quite popular.
|
||||
|
||||
The major difference between a real-life implementation and the example above is that real-life functions use more complex ways to interact with the user than a simple `confirm`. In the browser such a function usually draws a nice-looking question window. But that's another story.
|
||||
|
||||
**The arguments of `ask` are called *callback functions* or just *callbacks*. The idea is that we pass a function and expect it to be "called back" in certain circumstances.**
|
||||
|
||||
So, `showOk` becomes the callback for the "yes" answer and `showCancel` -- for the "no" answer.
|
||||
So, `showOk` becomes the callback for the "yes" answer, and `showCancel` for the "no" answer.
|
||||
|
||||
We can use Function Expressions to write the same much shorter:
|
||||
|
||||
|
@ -198,9 +198,9 @@ First, the syntax: how to see what is what in the code.
|
|||
};
|
||||
```
|
||||
|
||||
The more subtle difference is *when* a function is created by JavaScript engine.
|
||||
The more subtle difference is *when* a function is created by the JavaScript engine.
|
||||
|
||||
**Function Expression is created when the execution reaches it and is usable since then.**
|
||||
**Function Expression is created when the execution reaches it and is usable from then on.**
|
||||
|
||||
Once the execution flow passes to the right side of the assignment `let sum = function…` -- here we go, the function is created and can be used (assigned, called etc) from now on.
|
||||
|
||||
|
@ -226,7 +226,7 @@ function sayHi(name) {
|
|||
}
|
||||
```
|
||||
|
||||
Function Declaration `sayHi` is created when JavaScript is preparing to start the script and is visible everywhere in it.
|
||||
The Function Declaration `sayHi` is created when JavaScript is preparing to start the script and is visible everywhere in it.
|
||||
|
||||
...And if there were Function Expression, then it wouldn't work:
|
||||
|
||||
|
@ -245,11 +245,11 @@ Function Expressions are created when the execution reaches them. That would hap
|
|||
|
||||
### Function Declaration in a block
|
||||
|
||||
When Function Declaration is made within a code block, it is visible everywhere inside that block. But not outside of it.
|
||||
When a Function Declaration is made within a code block, it is visible everywhere inside that block. But not outside of it.
|
||||
|
||||
Sometimes that's handy to declare a local function only needed in that only block. But that feature may also cause problems.
|
||||
Sometimes that's handy to declare a local function only needed in that block alone. But that feature may also cause problems.
|
||||
|
||||
For instance, let's imagine that we need to declare a function `welcome()` depending on the `age` variable that we get in run time. And then we plan to use it sometimes later.
|
||||
For instance, let's imagine that we need to declare a function `welcome()` depending on the `age` variable that we get in run time. And then we plan to use it some time later.
|
||||
|
||||
The code below doesn't work:
|
||||
|
||||
|
@ -275,7 +275,7 @@ welcome(); // Error: welcome is not defined
|
|||
*/!*
|
||||
```
|
||||
|
||||
The Function Declaration is visible only inside the code block where it resides.
|
||||
A Function Declaration is visible only inside the code block where it resides.
|
||||
|
||||
We can call it from within the block, but not from outside:
|
||||
|
||||
|
@ -420,7 +420,7 @@ let sayHi = () => alert("Hello!");
|
|||
sayHi();
|
||||
```
|
||||
|
||||
Arrow functions can be used same way as Function Expressions.
|
||||
Arrow functions can be used the same way as Function Expressions.
|
||||
|
||||
For instance, here's the rewritten example with `welcome()`:
|
||||
|
||||
|
@ -436,11 +436,11 @@ welcome(); // ok now
|
|||
|
||||
The syntax may appear unfamiliar and not very readable at first, but that quickly changes as the eyes get used to the structure.
|
||||
|
||||
Arrow functions are very convenient for simple one-line actions, when we're just lazy to write many words.
|
||||
Arrow functions are very convenient for simple one-line actions, when we're just too lazy to write many words.
|
||||
|
||||
```smart header="Multiline arrow functions"
|
||||
|
||||
The examples above took arguments from the left of `=>` and evaluate the right-side expression with them.
|
||||
The examples above took arguments from the left of `=>` and evaluated the right-side expression with them.
|
||||
|
||||
Sometimes we need something a little bit more complex, like multiple expressions or statements. It is also possible, but we should enclose them in figure brackets. Then use a normal `return` within them.
|
||||
|
||||
|
@ -460,23 +460,23 @@ alert( sum(1, 2) ); // 3
|
|||
```smart header="More to come"
|
||||
Here we praised arrow functions for brevity. But that's not all! Arrow functions have other interesting features. We'll return to them later in the chapter <info:arrow-functions>.
|
||||
|
||||
As for now, we can already use them for one-line actions and callbacks.
|
||||
For now, we can already use them for one-line actions and callbacks.
|
||||
```
|
||||
|
||||
## Summary
|
||||
|
||||
- Functions are values. They can be assigned, copied or declared in any place of the code.
|
||||
- If the function is declared as a separate statement, in the main code flow -- that's called "Function Declaration".
|
||||
- If the function is created as a part of an expression -- it's "Function Expression".
|
||||
- If the function is declared as a separate statement in the main code flow, that's called a "Function Declaration".
|
||||
- If the function is created as a part of an expression, it's called a "Function Expression".
|
||||
- Function Declarations are processed before the code block is executed. They are visible everywhere in the block.
|
||||
- Function Expressions are created when the execution flow reaches them.
|
||||
|
||||
|
||||
In most cases when we need to declare a function, Function Declaration is preferable, because it is visible prior to the declaration itself. That gives more flexibility in code organization. And is usually more readable.
|
||||
In most cases when we need to declare a function, Function Declaration is preferable, because it is visible prior to the declaration itself. That gives us more flexibility in code organization. And is usually more readable.
|
||||
|
||||
So we should use Function Expression only when Function Declaration does not fit the task. We've seen a couple of examples of that in the chapter. And will see more in the future.
|
||||
So we should use Function Expression only when Function Declaration does not fit the task. We've seen a couple of examples of that in the chapter, and will see more in the future.
|
||||
|
||||
Arrow functions are handy for one-liners. They come in two flavors:
|
||||
|
||||
1. Without figure brackets: `(...args) => expression` -- the right side is an expression: the function evaluates it and returns the result.
|
||||
2. With figure brackets: `(...args) => { body }` -- brackets allow to write multiple statements inside the function, but we need an explicit `return` to return something.
|
||||
2. With figure brackets: `(...args) => { body }` -- brackets allow us to write multiple statements inside the function, but we need an explicit `return` to return something.
|
||||
|
|
|
@ -41,7 +41,7 @@ for(;;) {
|
|||
}
|
||||
```
|
||||
|
||||
...But even if we can put an "extra" semicolon somewhere, that's not an error, it will be ignored.
|
||||
...But even if we can put an "extra" semicolon somewhere, that's not an error. It will be ignored.
|
||||
|
||||
More in: <info:structure>.
|
||||
|
||||
|
@ -57,7 +57,7 @@ To fully enable all features of modern JavaScript, we should start scripts with
|
|||
|
||||
The directive must be at the top of a script or at the beginning of a function.
|
||||
|
||||
Without `"use strict"`, everything still works, but some features behave in old-fashion, "compatible" way. We'd generally prefer the modern behavior.
|
||||
Without `"use strict"`, everything still works, but some features behave in the old-fashion, "compatible" way. We'd generally prefer the modern behavior.
|
||||
|
||||
Some modern features of the language (like classes that we'll study in the future) enable strict mode implicitly.
|
||||
|
||||
|
@ -74,9 +74,9 @@ Can be declared using:
|
|||
A variable name can include:
|
||||
- Letters and digits, but the first character may not be a digit.
|
||||
- Characters `$` and `_` are normal, on par with letters.
|
||||
- Non-latin alphabets and hieroglyphs are also allowed, but commonly not used.
|
||||
- Non-Latin alphabets and hieroglyphs are also allowed, but commonly not used.
|
||||
|
||||
Variables are dynamically typed -- they can store any value:
|
||||
Variables are dynamically typed. They can store any value:
|
||||
|
||||
```js
|
||||
let x = 5;
|
||||
|
@ -113,7 +113,7 @@ We're using a browser as a working environment, so basic UI functions will be:
|
|||
[`alert(message)`](mdn:api/Window/alert)
|
||||
: Output a `message`.
|
||||
|
||||
All these functions are *modal*, they pause the code execution and prevent the visitor from interaction with the page until he answers.
|
||||
All these functions are *modal*, they pause the code execution and prevent the visitor from interacting with the page until he answers.
|
||||
|
||||
For instance:
|
||||
|
||||
|
@ -129,12 +129,12 @@ More in: <info:alert-prompt-confirm>.
|
|||
|
||||
## Operators
|
||||
|
||||
JavaScript supports following operators:
|
||||
JavaScript supports the following operators:
|
||||
|
||||
Arithmetical
|
||||
: Regular: `* + - /`, also `%` for the remainder and `**` for power of a number.
|
||||
|
||||
Binary plus `+` concatenates strings. And if any of the operands is a string -- the other one is converted to string too:
|
||||
Binary plus `+` concatenates strings. And if any of the operands is a string, the other one is converted to string too:
|
||||
|
||||
```js run
|
||||
alert( '1' + 2 ); // '12', string
|
||||
|
@ -228,7 +228,7 @@ Details in: <info:switch>.
|
|||
|
||||
## Functions
|
||||
|
||||
We covered 3 ways to create a function in JavaScript:
|
||||
We covered three ways to create a function in JavaScript:
|
||||
|
||||
1. Function Declaration: the function in the main code flow
|
||||
|
||||
|
@ -258,7 +258,7 @@ We covered 3 ways to create a function in JavaScript:
|
|||
// expression at the right side
|
||||
let sum = (a, b) => a + b;
|
||||
|
||||
// or multiline syntax with { ... }, need return here:
|
||||
// or multi-line syntax with { ... }, need return here:
|
||||
let sum = (a, b) => {
|
||||
// ...
|
||||
return a + b;
|
||||
|
@ -272,7 +272,7 @@ We covered 3 ways to create a function in JavaScript:
|
|||
```
|
||||
|
||||
|
||||
- Functions may have local variables -- those declared inside its body. Such variables are only visible inside the function.
|
||||
- Functions may have local variables: those declared inside its body. Such variables are only visible inside the function.
|
||||
- Parameters can have default values: `function sum(a=1, b=2) {...}`.
|
||||
- Functions always return something. If there's no `return` statement, then the result is `undefined`.
|
||||
|
||||
|
@ -286,4 +286,4 @@ More: see <info:function-basics>, <info:function-expressions-arrows>.
|
|||
|
||||
## More to come
|
||||
|
||||
That was a brief list of JavaScript features. As of now we studied only basics. Further in the tutorial you'll find more specials and advanced features of JavaScript.
|
||||
That was a brief list of JavaScript features. As of now we've studied only basics. Further in the tutorial you'll find more specials and advanced features of JavaScript.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue