This commit is contained in:
Ilya Kantor 2017-01-03 01:36:58 +03:00
parent 9ad9063d00
commit 97a0f22ff0
99 changed files with 1161 additions and 1208 deletions

View file

@ -1,10 +1,10 @@
# Hello, world!
The tutorial that you're reading is about core Javascript, that is platform-independant. So you'll be able to learn how to use Node.JS and other things based on that knowledge.
The tutorial that you're reading is about the core Javascript, that is platform-independant. So you'll be able to learn how to use Node.JS and other things based on that knowledge.
But we need a working environment to run our scripts, and browser is probably a good choice. Also we'll use few browser-specific commands like `alert`, but will keep their amount to the minimum.
But we need a working environment to run our scripts, and, just because this book is online, the browser is probably a good choice. We'll use a few browser-specific commands like `alert`, but will keep their amount to the minimum.
So we'll start with attaching a script to the webpage. For other environments like Node.JS there are other, probably even easier ways to run it.
So here we'll see how to attach a script to the webpage, that's simple enough. For server-side environments you can just execute it with a command like `"node my.js"` for Node.JS.
[cut]

View file

@ -1,6 +1,6 @@
# Code structure
The first overall thing to know is the code structure.
The first thing to study is the building blocks of the code.
[cut]
@ -54,8 +54,8 @@ The code outputs `6`, because JavaScript does not insert semicolons here. It is
Errors which occur in such cases are quite hard to find and fix.
````smart header="An example of the error"
If you're curious to see a concrete example, check this code out:
````smart header="An example of an error"
If you're curious to see a concrete example of such an error, check this code out:
```js run
[1, 2].forEach(alert)
@ -63,34 +63,37 @@ If you're curious to see a concrete example, check this code out:
It shows `1` then `2`.
No need to think about the meaning of the brackets `[]` and `forEach`, for now -- it does not matter. Let's just remember the result.
No need to think about the meaning of the brackets `[]` and `forEach` yet. We'll study them, for now -- it does not matter. Let's just remember the result.
Now let's put 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" ) // shown
alert( "There will be an error" )
[1, 2].forEach(alert) // doesn't work any more!
[1, 2].forEach(alert)
```
Now if we run it, only the first `alert` is shown, and then an error.
But everything is fine again if we add a semicolon after `alert`:
```js run
alert( "All fine now" ); // shown
alert( "All fine now" );
[1, 2].forEach(alert) // this works too
[1, 2].forEach(alert)
```
Now we have the "All fine now" message and then `1` and `2`.
The error in the no-semicolon variant occurs because automatic semicolon insertion rules are complex, and in particular, JavaScript does not imply a semicolon before square brackets `[...]`.
And, because the semicolon is not auto-inserted, the code is treated as a single statement, like this:
And, because the semicolon is not auto-inserted, the code in the first example is treated as a single statement, like this:
```js run no-beautify
alert( "There will be an error" )[1, 2].forEach(alert)
```
And in this particular case, that's just wrong, hence the error. There are other situations when such thing happens.
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 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 time. But it's safer, especially for a beginner -- to put them.
@ -105,12 +108,12 @@ Comments can be put into any place of the script. They don't affect the executio
The rest of the line is a comment. It may occupy a full line of its own or follow a statement.
Like this:
Like here:
```js run
// This shows "Hello" (the comment occupies a line of its own)
// This comment occupies a line of its own
alert( 'Hello' );
alert( 'World' ); // ...this shows "World" (the comment follows a statement)
alert( 'World' ); // This comment follows the statement
```
**Multiline comments start with a slash and a star <code>"/&#42;"</code> and end with a star and a slash <code>"&#42;/"</code>.**
@ -125,7 +128,7 @@ alert( 'Hello' );
alert( 'World' );
```
The content of comments is ignored, so if we put a code inside <code>/&#42; ... &#42;/</code> or after `//` it won't execute.
The content of comments is ignored, so if we put a code inside <code>/&#42; ... &#42;/</code> it won't execute.
Sometimes it comes handy to temporarily disable a part of the code:

View file

@ -43,13 +43,13 @@ Besides regular numbers there are so-called "special numeric values" which also
- `NaN` represents a computational error. It is a result of an incorrect or an undefined mathematical operation, for instance:
```js run
alert( "not a number" / 2 ); // NaN
alert( "not a number" / 2 ); // NaN, such division is erroneous
```
`NaN` is sticky. Any further operation on `NaN` would give `NaN`:
```js run
alert( "not a number" / 2 + 5 ); // NaN + 5 is still NaN
alert( "not a number" / 2 + 5 ); // NaN
```
So, if there's `NaN` somewhere in a mathematical expression, it propagates to the whole result.
@ -66,6 +66,8 @@ We'll see more into working with numbers in the chapter <info:number>.
## A string
A string in Javascript must be quoted.
```js
let str = "Hello";
let str2 = 'Single quotes are ok too';
@ -78,7 +80,7 @@ In JavaScript, there are 3 types of quotes.
2. Single quotes: `'Hello'`.
3. Backticks: <code>&#96;Hello&#96;</code>.
Double and single quotes are similar, "simple" quotes.
Double and single quotes are "simple" quotes. They mark the beginning and the end of the string, that's all. 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:
@ -94,10 +96,15 @@ 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 other quotes do not allow such embedding!
```js run
alert( "the result is ${1 + 2}" ); // the result is ${1 + 2} (double quotes do nothing)
```
We'll cover strings more thoroughly in the chapter <info:string>.
```smart header="There is no *character* type."
In some languages, there is a special "character" type for a single character. For example, in the C language it is `char`.
In some languages, there is a special "character" type for a single character. For example, in the C language and in Java it is `char`.
In JavaScript, there is no such type. There's only one type: `string`. A string may consist of only one character or many of them.
```
@ -111,8 +118,8 @@ This type is commonly used to store yes/no values: `true` means "yes, correct",
For instance:
```js
let checked1 = true; // yes, the form field is checked
let checked2 = false; // no, the form field is not checked
let nameChecked = true; // yes, the form field name is checked
let ageChecked = false; // no, the form field age is not checked
```
Boolean values also come as the result of comparisons:

View file

@ -380,6 +380,59 @@ For example, [jQuery](http://jquery.com) framework defines a function `$`, [LoDa
These are exceptions. Generally functions names should be concise, but descriptive.
```
## 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 parts.
Sometimes following this rule may be not easy, but it's a definitely good thing.
...So why functions equal comments?
A separate function is not only easier to test and debug -- its very existence is a great comment!
For instance, compare the two functions `showPrimes(n)` below. Each one outputs [prime numbers](https://en.wikipedia.org/wiki/Prime_number) up to `n`.
The first variant uses a label:
```js
function showPrimes(n) {
nextPrime: for (let i = 2; i < n; i++) {
for (let j = 2; j < i; j++) {
if (i % j == 0) continue nextPrime;
}
alert( i ); // a prime
}
}
```
The second variant uses an additional function `isPrime(n)` to test for primality:
```js
function showPrimes(n) {
for (let i = 2; i < n; i++) {
*!*if (!isPrime(i)) continue;*/!*
alert(i); // a prime
}
}
function isPrime(n) {
for (let i = 2; i < n; i++) {
if ( n % i == 0) return false;
}
return true;
}
```
The second variant is easier to understand isn't it? Instead of the code piece we see a name of the action (`isPrime`). Sometimes people refer to such code as *self-describing*.
```summary
So the idea is: functions can be created even if we don't intend to reuse them. They structure the code and make it readable.
```
## Summary
A function declaration looks like this:

View file

@ -95,7 +95,7 @@ The answer is simple:
- 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.
````
## Anonymous functions
## Callback functions
Let's see an example where function expressions come really handy.
@ -134,9 +134,13 @@ ask("Do you agree?", showOk, showCancel);
The code looks kind of too simple, right? Why would anyone need such `ask`?
...It turns out that in the browser such functions are very required, the minor difference is that they ask not with a simple `confirm`, but output a much richer looking question window. But that's another story.
...It turns out 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.
Right now let's see how we can write the same much shorter:
The arguments of `ask` are called *callback functions* or just *callbacks*. The idea is that we pass the functions and expect them to be "called back" in certain circumstances.
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:
```js run no-beautify
function ask(question, yes, no) {
@ -153,9 +157,9 @@ ask(
*/!*
```
Here functions are declared right inside the `ask(...)` call. They have no name (anonymous) and are not accessible outside of `ask`, but that's just what we need.
Here functions are declared right inside the `ask(...)` call. They have no name, and so are called *anonymous*. Such functions are not accessible outside of `ask`, but that's just what we want here.
Such code appears very naturally, it's in the spirit of Javascript.
Such code appears in our scripts very naturally, it's in the spirit of Javascript.
```smart header="A function is a value representing an \"action\""
@ -405,7 +409,17 @@ let double = n => n*2;
alert( double(3) ); // 6
```
If there are no arguments, we can put empty brackets. For instance, here's the rewritten example with `welcome()`:
If there are no arguments, we can put empty brackets:
```js run
let sayHi = () => alert("Hello!");
sayHi();
```
Arrow functions can be used same way as Function Expressions.
For instance, here's the rewritten example with `welcome()`:
```js run
let age = prompt("What is your age?", 18);
@ -439,45 +453,26 @@ alert( sum(1, 2) ); // 3
```
```smart header="More to come"
Here we praised arrow functions for shortness. But that's not all! Arrow functions have other interesting features. We'll return to them later and see where else they shine.
Here we praised arrow functions for shortness. 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.
As for now, we can already use them for one-line actions and callbacks.
```
## Summary
[todo review]
- 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 a Function Declaration.
- If the function is created as a part of an expression -- it's a Function Expression.
- Function Declarations are processed before the code block is executed. They are visible everywhere in the block (or the script).
- 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.
- Function Expressions allow to specify an optional name for internal needs (Named Function Expression).
If we simple want to create a function, then in most cases Function Declaration is preferable.
In most cases Function Declaration is preferable, because it is visible prior to the declaration itself. And is usually more readable.
Novice programmers sometimes tend to overuse Function Expression by creating many functions with `let func = function()`, but compare, which code is 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.
```js no-beautify
let f = function() { /* expression */ }
Arrow functions are handy for one-liners. The come in two flavors:
function f() { /* declaration */ }
```
Function Declaration is shorter and more obvious. The additional bonus -- it can be called before the actual declaration.
**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.
We also touched two other ways to create a function:
- Arrow functions are handy for one-liners. The come in two flavours:
1. Without figure brackets: `(...args) => expression` -- returns the evaluated `expression`.
2. With brackets: `(...args) => { body }` -- need an explicit `return` statement to return something, but can be more complex.
- `new Function(args, body)`
This syntax allows to create a function from a string, that may be composed dynamically during the execution.
1. Without figure brackets: `(...args) => expression` -- returns the evaluated `expression`. The right side must be a single expression.
2. With figure brackets: `(...args) => { body }` -- they need an explicit `return` statement to return something, but can be more complex and contain multiple statements.

View file

@ -1,10 +1,8 @@
# JavaScript specials: all together
# Javascript specials
[todo finish me. is this needed?]
This chapter aims to list features of JavaScript that we've learned, paying special attention to subtle moments.
This chapter aims to list features of JavaScript that we've learned, paying special attention to unobvious moments.
That's especially useful if you came from another language or, just as a recap.
That's especially useful if you came from another language or just as a recap.
[cut]
@ -37,13 +35,13 @@ Semicolons are not required after code blocks `{...}` and syntax constructs with
```js
function f() {
// no semicolon after function declaration
// no semicolon needed after function declaration
}
for(;;) { /* no semicolon */ }
for(;;) { /* no semicolon after the loop */ }
```
...But even if we can put a semicolon there, that's not an error, extra semicolons do nothing.
...But even if we can put an "extra" semicolon somewhere, that's not an error, it will be ignored.
More in: <info:structure>.
@ -61,7 +59,7 @@ 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-fasion, "compatible" way. We'd generally prefer the modern behavior.
Later we'll get acquanted with advanced features of the language that enable strict mode implicitly.
Advanced features of the language (like classes that we'll study in the future) that enable strict mode implicitly.
More in: <info:strict-mode>.
@ -94,7 +92,13 @@ There are 7 data types:
- `undefined` -- a type with a single value `undefined`, meaning "not assigned",
- `object` and `symbol` -- for complex data structures and unique identifiers, we didn't learn them yet.
More in: <info:variables>, <info:types>.
The `typeof` operator returns the type for a value, with two special behaviors:
```js
typeof null == "object" // error in the language
typeof function(){} == "function" // functions are treated specially
```
More in: <info:variables> and <info:types>.
## Interaction
@ -117,8 +121,8 @@ For instance:
let userName = prompt("Your name?", "Alice");
let isTeaWanted = confirm("Do you want some tea?");
alert( "Visitor: " + userName );
alert( "Tea wanted: " + isTeaWanted );
alert( "Visitor: " + userName ); // Alice
alert( "Tea wanted: " + isTeaWanted ); // true
```
More in: <info:uibasic>.
@ -130,7 +134,7 @@ JavaScript supports following operators:
Arithmetical
: Regular: `* + - /`, also `%` for the remainder and `**` for power of a number.
Binary plus `+` contatenates strings.
Binary plus `+` concatenates strings.
If any of the operands is a string -- the other one is converted to string too:
@ -143,7 +147,8 @@ Assignments
: There is a simple assignment: `a = b` and combined ones like `a *= 2`.
Bitwise
: Bitwise operators work with integers on bit-level: see the [docs](mdn:JavaScript/Reference/Operators/Bitwise_Operators) when they are needed.
: Bitwise operators work with integers on bit-level: see the [docs](mdn:JavaScript/Refereno
ce/Operators/Bitwise_Operators) when they are needed.
Ternary
: The only operator with three parameters: `cond ? resultA : result B`
@ -152,189 +157,140 @@ Logical operators
: Logical AND `&&` and OR `||` perform short-circuit evaluation and then return the value where it stopped.
Comparisons
: Equality check `===` immediately fails if types are different.
Other comparisons perform type conversions, usually to a number:
: Equality check `==` for values of different types converts them to a number (except `null` and `undefined` that equal each other and nothing else), so these are equal:
```js run
alert( 0 == false ); // true
alert( true > 0 ); // true
alert( 0 == '' ); // true
```
Other comparisons convert to a number as well.
The strict equality operator `===` doesn't do the conversion: different types always mean different values for it, so:
Values `null` and `undefined` are special: they equal `==` each other and don't equal anything else.
Greater/less comparisons compare strings character-by-character, other types are converted to a number.
Others
Logical operators
: There are few others, like a comma operator.
More in: <info:operators>, <info:comparison>.
More in: <info:operators>, <info:comparison>, <info:logical-ops>.
## Логические операторы
## Loops
В JavaScript есть логические операторы: И (обозначается `&&`), ИЛИ (обозначается `||`) и НЕ (обозначается `!`). Они интерпретируют любое значение как логическое.
Не стоит путать их с [побитовыми операторами](/bitwise-operators) И, ИЛИ, НЕ, которые тоже есть в JavaScript и работают с числами на уровне битов.
Как и в большинстве других языков, в логических операторах используется "короткий цикл" вычислений. Например, вычисление выражения `1 && 0 && 2` остановится после первого И `&&`, т.к. понятно что результат будет ложным (ноль интерпретируется как `false`).
**Результатом логического оператора служит последнее значение в коротком цикле вычислений.**
Можно сказать и по-другому: значения хоть и интерпретируются как логические, но то, которое в итоге определяет результат, возвращается без преобразования.
Например:
```js run
alert( 0 && 1 ); // 0
alert( 1 && 2 && 3 ); // 3
alert( null || 1 || 2 ); // 1
```
Подробнее: <info:logical-ops>.
## Циклы
- Поддерживаются три вида циклов:
- We covered 3 types of loops:
```js
// 1
while (условие) {
while (condition) {
...
}
// 2
do {
...
} while (условие);
} while (condition);
// 3
for let i = 0; i < 10; i++) {
for(let i = 0; i < 10; i++) {
...
}
```
- Переменную можно объявлять прямо в цикле, но видна она будет и за его пределами.
- Поддерживаются директивы `break/continue` для выхода из цикла/перехода на следующую итерацию.
Для выхода одновременно из нескольких уровней цикла можно задать метку.
- The variable declared in `for(let...)` loop is visible only inside the loop. But we can also omit `let` and reuse an existing variable.
- Directives `break/continue` allow to exit the whole loop/current iteration. Use labels to break nested loops.
Синтаксис: "`имя_метки:`", ставится она только перед циклами и блоками, например:
Details in: <info:while-for>.
```js
*!*outer:*/!*
for(;;) {
...
for(;;) {
...
*!*break outer;*/!*
}
}
```
Later we'll study more types of loops to deal with objects.
Переход на метку возможен только изнутри цикла, и только на внешний блок по отношению к данному циклу. В произвольное место программы перейти нельзя.
## The "switch" construct
Подробнее: <info:while-for>.
The "switch" construct can replace multiple `if` checks. It uses `===` for comparisons.
## Конструкция switch
При сравнениях в конструкции `switch` используется оператор `===`.
Например:
For instance:
```js run
let age = prompt('Ваш возраст', 18);
let age = prompt('Your age?', 18);
switch (age) {
case 18:
alert( 'Никогда не сработает' ); // результат prompt - строка, а не число
alert("Won't work"); // the result of prompt is a string, not a number число
case "18": // вот так - сработает!
alert( 'Вам 18 лет!' );
case "18":
alert("This works!"");
break;
default:
alert( 'Любое значение, не совпавшее с case' );
alert("Any value not equal to one above");
}
```
Подробнее: <info:switch>.
Details in: <info:switch>.
## Функции
## Functions
Синтаксис функций в JavaScript:
We covered 3 ways to create a function in Javascript:
```js run
// function имя(список параметров) { тело }
function sum(a, b) {
let result = a + b;
1. Function Declaration: the function in the main code flow
return result;
}
```js
function sum(a, b) {
let result = a + b;
// использование:
alert( sum(1, 2) ); // 3
```
- `sum` -- имя функции, ограничения на имя функции -- те же, что и на имя переменной.
- Переменные, объявленные через `let` внутри функции, видны везде внутри этой функции, блоки `if`, `for` и т.п. на видимость не влияют.
- Параметры копируются в локальные переменные `a`, `b`.
- Функция без `return` считается возвращающей `undefined`. Вызов `return` без значения также возвращает `undefined`:
```js run no-beautify
function f() { }
alert( f() ); // undefined
return result;
}
```
Подробнее: <info:function-basics>.
2. Function Expression: the function in the context of an expression
## Function Declaration и Expression
```js
let sum = function(a, b) {
let result = a + b;
Функция в JavaScript является обычным значением.
return result;
}
```
Её можно создать в любом месте кода и присвоить в переменную, вот так:
Function expression can have a name, like `sum = function name(a, b)`, but that `name` is only visible inside that function.
```js run
let sum = function(a, b) {
let result = a + b;
3. Arrow functions:
return result;
}
```js
// expression at the right side
let sum = (a, b) => a + b;
alert( sum(1, 2) ); // 3
```
// or multiline syntax with { ... }, need return here:
let sum = (a, b) => {
// ...
return a + b;
}
Такой синтаксис, при котором функция объявляется в контексте выражения (в данном случае, выражения присваивания), называется Function Expression, а обычный синтаксис, при котором функция объявляется в основном потоке кода -- Function Declaration.
// without arguments
let sayHi = () => alert("Hello");
Функции, объявленные через Function Declaration, отличаются от Function Expression тем, что интерпретатор создаёт их при входе в область видимости (в начале выполнения скрипта), так что они работают до объявления.
// with a single argument
let double = n => n * 2;
```
Обычно это удобно, но может быть проблемой, если нужно объявить функцию в зависимости от условия. В этом случае, а также в других ситуациях, когда хочется создать функцию "здесь и сейчас", используют Function Expression.
Детали: <info:function-declaration-expression>.
- 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`.
## Named Function Expression
Если объявление функции является частью какого-либо выражения, например `let f = function...` или любого другого, то это Function Expression.
| Function Declaration | Function Expression |
|----------------------|---------------------|
| visible in the whole code block | created when the execution reaches it |
| - | can have a name, visible only inside the function |
В этом случае функции можно присвоить "внутреннее" имя, указав его после `function`. Оно будет видно только внутри этой функции и позволяет обратиться к функции изнутри себя. Обычно это используется для рекурсивных вызовов.
More: see <info:function-basics>, <info:function-expressions-arrows>.
Например, создадим функцию для вычисления факториала как Function Expression и дадим ей имя `me`:
## More to come
```js run
let factorial = function me(n) {
return (n == 1) ? n : n * me(n - 1);
}
That was a brief list of Javascript specials that we need to know to code well.
alert( factorial(5) ); // 120
*!*
alert( me ); // ошибка, нет такой переменной
*/!*
```
Ограничение видимости для имени не работает в IE8-, но вызов с его помощью работает во всех браузерах.
Более развёрнуто: <info:named-function-expression>.
## Итого
В этой главе мы повторили основные особенности JavaScript, знание которых необходимо для обхода большинства "граблей", да и просто для написания хорошего кода.
Это, конечно, лишь основы. Дальше вы узнаете много других особенностей и приёмов программирования на этом языке.
As of now that were only basics. Further in the tutorial you'll find more specials and advanced features of Javascript.