Merge pull request #137 from jmbothe/master
grammar, usage, punctuation edits, Part 1, sections 2.9 - 2.16
This commit is contained in:
commit
d098c48c8b
8 changed files with 88 additions and 88 deletions
|
@ -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