This commit is contained in:
Ilya Kantor 2017-03-19 17:09:37 +03:00
parent e2443e8de6
commit 75e30539ef
73 changed files with 195 additions and 195 deletions

View file

@ -1,6 +1,6 @@
# Hello, world! # Hello, world!
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. 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, 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. 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.
@ -133,4 +133,4 @@ The example above can be split into two scripts to work:
- A script in an external file can be inserted with `<script src="path/to/script.js"></script>`. - A script in an external file can be inserted with `<script src="path/to/script.js"></script>`.
There is much more about browser scripts and their interaction with the web-page. But let's keep in mind that this part of the tutorial is devoted to Javascript language. So we shouldn't distract ourselves from it. We'll be using a browser as a way to run Javascript, very convenient for online reading, but yet one of many. There is much more about browser scripts and their interaction with the web-page. But let's keep in mind that this part of the tutorial is devoted to JavaScript language. So we shouldn't distract ourselves from it. We'll be using a browser as a way to run JavaScript, very convenient for online reading, but yet one of many.

View file

@ -66,7 +66,7 @@ We'll see more into working with numbers in the chapter <info:number>.
## A string ## A string
A string in Javascript must be quoted. A string in JavaScript must be quoted.
```js ```js
let str = "Hello"; let str = "Hello";
@ -80,7 +80,7 @@ In JavaScript, there are 3 types of quotes.
2. Single quotes: `'Hello'`. 2. Single quotes: `'Hello'`.
3. Backticks: <code>&#96;Hello&#96;</code>. 3. Backticks: <code>&#96;Hello&#96;</code>.
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. 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: Backticks are "extended functionality" quotes. They allow to embed variables and expressions into a string by wrapping them in `${…}`, for example:

View file

@ -167,4 +167,4 @@ Most of these rules are easy to understand and memorize. The notable exceptions
- `undefined` is `NaN` as a number. - `undefined` is `NaN` as a number.
- `"0"` is true as a boolean. - `"0"` is true as a boolean.
Objects are not covered here, we'll return to them later in the chapter <info:object-toprimitive>, devoted exclusively to objects, after we learn more basic things about Javascript. Objects are not covered here, we'll return to them later in the chapter <info:object-toprimitive>, devoted exclusively to objects, after we learn more basic things about JavaScript.

View file

@ -32,7 +32,7 @@ Before we move on, let's grasp the common terminology.
## Strings concatenation, binary + ## Strings concatenation, binary +
Now let's see special features of Javascript operators, beyond school arithmetics. Now let's see special features of JavaScript operators, beyond school arithmetics.
Usually the plus operator `'+'` sums numbers. Usually the plus operator `'+'` sums numbers.

View file

@ -1,6 +1,6 @@
# Interaction: alert, prompt, confirm # Interaction: alert, prompt, confirm
This part of the tutorial aims to cover Javascript "as is", without environment-specific tweaks. 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. But still we use a browser as the demo environment. So we should know at least few user-interface functions.

View file

@ -207,7 +207,7 @@ function showMessage(from, text = anotherFunction()) {
````smart header="Default parameters old-style" ````smart header="Default parameters old-style"
Old editions of Javascript did not support default parameters. So there are alternative ways to support them, that you can find mostly in the old scripts. Old editions of JavaScript did not support default parameters. So there are alternative ways to support them, that you can find mostly in the old scripts.
For instance, an explicit check for being `undefined`: For instance, an explicit check for being `undefined`:
@ -322,7 +322,7 @@ For long expressions, it may be tempting sometimes to put them on a separate lin
return return
(some + long + expression + or + whatever * f(a) + f(b)) (some + long + expression + or + whatever * f(a) + f(b))
``` ```
That doesn't work, because Javascript assumes a semicolon after `return` in that case: That doesn't work, because JavaScript assumes a semicolon after `return` in that case:
```js ```js
return*!*;*/!* return*!*;*/!*

View file

@ -1,6 +1,6 @@
# Function expressions and arrows # Function expressions and arrows
In Javascript a function is not a "magical language structure", but a special kind of value. In JavaScript a function is not a "magical language structure", but a special kind of value.
The syntax that we used before is called *Function Declaration*: The syntax that we used before is called *Function Declaration*:
@ -159,7 +159,7 @@ ask(
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. 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 in our scripts 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\"" ```smart header="A function is a value representing an \"action\""

View file

@ -1,4 +1,4 @@
# Javascript specials # JavaScript specials
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 subtle moments.
@ -233,7 +233,7 @@ Details in: <info:switch>.
## Functions ## Functions
We covered 3 ways to create a function in Javascript: We covered 3 ways to create a function in JavaScript:
1. Function Declaration: the function in the main code flow 1. Function Declaration: the function in the main code flow
@ -291,6 +291,6 @@ More: see <info:function-basics>, <info:function-expressions-arrows>.
## More to come ## More to come
That was a brief list of Javascript specials that we need to know to code well. That was a brief list of JavaScript specials that we need to know to code well.
As of now that were only basics. Further in the tutorial you'll find more specials and advanced features of Javascript. As of now that were only basics. Further in the tutorial you'll find more specials and advanced features of JavaScript.

View file

@ -54,7 +54,7 @@ Should look like this:
![](chrome-sources-breakpoint.png) ![](chrome-sources-breakpoint.png)
A *breakpoint* is a point of code where the debugger will automatically pause the Javascript execution. A *breakpoint* is a point of code where the debugger will automatically pause the JavaScript execution.
While the code is paused, we can examine current variables, execute commands in the console etc. That is -- debug it. While the code is paused, we can examine current variables, execute commands in the console etc. That is -- debug it.
@ -128,7 +128,7 @@ There are buttons for it at the right-top:
The execution has resumed, reached another breakpoint inside `say()` and paused there. Take a look at the "Call stack" at the right. It has increased by one more call. We're inside `say()` now. The execution has resumed, reached another breakpoint inside `say()` and paused there. Take a look at the "Call stack" at the right. It has increased by one more call. We're inside `say()` now.
<span class="devtools" style="background-position:-137px -76px"></span> -- make a step (run the next command), but *not go into the function*, hotkey `key:F10`. <span class="devtools" style="background-position:-137px -76px"></span> -- make a step (run the next command), but *not go into the function*, hotkey `key:F10`.
: If we click it now, `alert` will be shown. The important thing is that if `alert` were not native, but a Javascript function, then the execution would "step over it", skipping the function internals. : If we click it now, `alert` will be shown. The important thing is that if `alert` were not native, but a JavaScript function, then the execution would "step over it", skipping the function internals.
<span class="devtools" style="background-position:-72px -76px"></span> -- make a step, hotkey `key:F11`. <span class="devtools" style="background-position:-72px -76px"></span> -- make a step, hotkey `key:F11`.
: The same as the previous one, but "steps in" nested functions. Clicking this will step through all script actions one by one. : The same as the previous one, but "steps in" nested functions. Clicking this will step through all script actions one by one.

View file

@ -258,7 +258,7 @@ There are many open style guides, so there we could just accept the one we like
There exist more there in the wild. There exist more there in the wild.
As you become more mature in Javascript programming, you might want to read them all to pick up the common principles. As you become more mature in JavaScript programming, you might want to read them all to pick up the common principles.
## Style checkers ## Style checkers
@ -280,7 +280,7 @@ Here are simple steps to start using it:
1. Install [Node.JS](https://nodejs.org/), necessary to run them. 1. Install [Node.JS](https://nodejs.org/), necessary to run them.
2. Install eslint: `npm i -g eslint` (npm is Node.JS package installer). 2. Install eslint: `npm i -g eslint` (npm is Node.JS package installer).
3. Create a config file `.eslintrc` in your Javascript project (the dot at the start is mandatory). 3. Create a config file `.eslintrc` in your JavaScript project (the dot at the start is mandatory).
An example of `.eslintrc`: An example of `.eslintrc`:

View file

@ -182,7 +182,7 @@ For instance, for ESLint you should do the following:
1. Install Node.JS (can take from the <http://nodejs.org>). 1. Install Node.JS (can take from the <http://nodejs.org>).
2. Install ESLint with the command `npm install -g eslint`. 2. Install ESLint with the command `npm install -g eslint`.
3. Create a config file named `.eslintrc` in the root of your Javascript project (in the folder that contains all your files). 3. Create a config file named `.eslintrc` in the root of your JavaScript project (in the folder that contains all your files).
Here's an example of `.eslintrc`: Here's an example of `.eslintrc`:

View file

@ -36,7 +36,7 @@ Enough words. Let's see the example.
Let's say we want to make a function `pow(x, n)` that raises `x` to an integer power `n`. We assume that `n≥0`. Let's say we want to make a function `pow(x, n)` that raises `x` to an integer power `n`. We assume that `n≥0`.
That task is quite simple, there's even a `**` operator in Javascript that can do that, but here we concentrate not on the function itself, but on the development flow, that can be applied to more complex tasks as well. That task is quite simple, there's even a `**` operator in JavaScript that can do that, but here we concentrate not on the function itself, but on the development flow, that can be applied to more complex tasks as well.
Before creating the code of `pow`, we can imagine what the function should do and describe it using BDD. Before creating the code of `pow`, we can imagine what the function should do and describe it using BDD.
@ -304,7 +304,7 @@ The basic functionality of `pow` is complete. The first iteration of the develop
As it was said, the function `pow(x, n)` is meant to work with positive integer values `n`. As it was said, the function `pow(x, n)` is meant to work with positive integer values `n`.
To indicate a mathematical error, Javascript functions usually return `NaN`. Let's do the same for invalid values of `n`. To indicate a mathematical error, JavaScript functions usually return `NaN`. Let's do the same for invalid values of `n`.
Let's first add the behavior to the spec(!): Let's first add the behavior to the spec(!):
@ -408,4 +408,4 @@ In real life that's sometimes not that easy. Sometimes it's difficult to write a
Later in the tutorial you will meet many tasks with tests baked-in. So you will more practical examples. Later in the tutorial you will meet many tasks with tests baked-in. So you will more practical examples.
Writing tests requires good Javascript knowledge. But we're just starting to learn it. So, to settle down everything, as of now you're not required to write tests, but you should already be able to read them even if they are a little bit more complex than in this chapter. Writing tests requires good JavaScript knowledge. But we're just starting to learn it. So, to settle down everything, as of now you're not required to write tests, but you should already be able to read them even if they are a little bit more complex than in this chapter.

View file

@ -1,9 +1,9 @@
# Objects # Objects
As we know, there are 7 language types in Javascript. Six of them are called "primitive", because their values contain only a single thing (be it a string or a number or whatever). As we know, there are 7 language types in JavaScript. Six of them are called "primitive", because their values contain only a single thing (be it a string or a number or whatever).
In contrast, objects are used to store keyed collections of various data and more complex entities. In Javascript, objects penetrate almost every aspect of the language. So we must understand them first before going in-depth anywhere else. In contrast, objects are used to store keyed collections of various data and more complex entities. In JavaScript, objects penetrate almost every aspect of the language. So we must understand them first before going in-depth anywhere else.
[cut] [cut]
@ -544,7 +544,7 @@ So, copying an object variable creates one more reference to the same object.
But what if we need to duplicate an object? Create an independant copy, a clone? But what if we need to duplicate an object? Create an independant copy, a clone?
That's also doable, but a little bit more difficult, because there's no built-in method for that in Javascript. Actually, that's rarely needed, copying by reference is good most of the time. That's also doable, but a little bit more difficult, because there's no built-in method for that in JavaScript. Actually, that's rarely needed, copying by reference is good most of the time.
But if we really want that, then we need to create a new object and replicate the structure of the existing one by iterating over its properties and copying them on the primitive level. But if we really want that, then we need to create a new object and replicate the structure of the existing one by iterating over its properties and copying them on the primitive level.
@ -661,7 +661,7 @@ alert(clone.sizes.width); // 51, see the result from the other one
To fix that, we should use the cloning loop that examines each value of `user[key]` and, if it's an object, then replicate it's structure as well. That is called a "deep cloning". To fix that, we should use the cloning loop that examines each value of `user[key]` and, if it's an object, then replicate it's structure as well. That is called a "deep cloning".
There's a standard algorithm for deep cloning that handles the case above and more complex cases, called the [Structured cloning algorithm](w3c.github.io/html/infrastructure.html#internal-structured-cloning-algorithm). Not to reinvent the wheel, we can use a working implementation of it from the Javascript library [lodash](https://lodash.com), the method is called [_.cloneDeep(obj)](https://lodash.com/docs#cloneDeep). There's a standard algorithm for deep cloning that handles the case above and more complex cases, called the [Structured cloning algorithm](w3c.github.io/html/infrastructure.html#internal-structured-cloning-algorithm). Not to reinvent the wheel, we can use a working implementation of it from the JavaScript library [lodash](https://lodash.com), the method is called [_.cloneDeep(obj)](https://lodash.com/docs#cloneDeep).
@ -688,7 +688,7 @@ To make a "real copy" (a clone) we can use `Object.assign` or [_.cloneDeep(obj)
What we've studied in this chapter is called a "plain object", or just `Object`. What we've studied in this chapter is called a "plain object", or just `Object`.
There are many other kinds of objects in Javascript: There are many other kinds of objects in JavaScript:
- `Array` to store ordered data collections, - `Array` to store ordered data collections,
- `Date` to store the information about the date and time, - `Date` to store the information about the date and time,

View file

@ -1,14 +1,14 @@
# Garbage collection # Garbage collection
Memory management in Javascript is performed automatically and invisibly to us. We create primitives, objects, functions... All that takes memory. Memory management in JavaScript is performed automatically and invisibly to us. We create primitives, objects, functions... All that takes memory.
What happens when something is not needed any more? How Javascript engine discovers that and cleans up? What happens when something is not needed any more? How JavaScript engine discovers that and cleans up?
[cut] [cut]
## Reachability ## Reachability
The main concept of memory management in Javascript is *reachability*. The main concept of memory management in JavaScript is *reachability*.
Simply put, "reachable" values are those that are accessible or useable somehow. They are guaranteed to be stored in memory. Simply put, "reachable" values are those that are accessible or useable somehow. They are guaranteed to be stored in memory.
@ -27,7 +27,7 @@ Simply put, "reachable" values are those that are accessible or useable somehow.
For instance, if there's an object in a local variable, and that object has a property referencing another object, that object is considered reachable. And those that it references -- are also reachable. Detailed examples to follow. For instance, if there's an object in a local variable, and that object has a property referencing another object, that object is considered reachable. And those that it references -- are also reachable. Detailed examples to follow.
There's a background process in the Javascript engine that is called [garbage collector](https://en.wikipedia.org/wiki/Garbage_collection_(computer_science)). It monitors all objects and removes those that became unreachable. There's a background process in the JavaScript engine that is called [garbage collector](https://en.wikipedia.org/wiki/Garbage_collection_(computer_science)). It monitors all objects and removes those that became unreachable.
## A simple example ## A simple example
@ -185,7 +185,7 @@ Now the objects that could not be visited in the process are considered unreacha
That's the concept how garbage collection works. That's the concept how garbage collection works.
Javascript engines apply many optimizations to make it run faster and not affect the execution. JavaScript engines apply many optimizations to make it run faster and not affect the execution.
Some of the optimizations: Some of the optimizations:

View file

@ -31,7 +31,7 @@ alert(id1 == id2); // false
*/!* */!*
``` ```
If you are familiar with Ruby or another language that also has some sort of "symbols" -- please don't be misguided. Javascript symbols are different. If you are familiar with Ruby or another language that also has some sort of "symbols" -- please don't be misguided. JavaScript symbols are different.
## "Hidden" properties ## "Hidden" properties
@ -48,7 +48,7 @@ user[id] = "ID Value";
alert( user[id] ); // we can access the data using the symbol as the key alert( user[id] ); // we can access the data using the symbol as the key
``` ```
Now let's imagine that another script wants to have his own "id" property inside `user`, for his own purposes. That may be another Javascript library, so the scripts are completely unaware for each other. Now let's imagine that another script wants to have his own "id" property inside `user`, for his own purposes. That may be another JavaScript library, so the scripts are completely unaware for each other.
No problem. It can create its own `Symbol("id")`. No problem. It can create its own `Symbol("id")`.
@ -178,7 +178,7 @@ Symbols inside the registry are called *global symbols*. If we want an applicati
```smart header="That sounds like Ruby" ```smart header="That sounds like Ruby"
In some programming languages, like Ruby, there's a single symbol per name. In some programming languages, like Ruby, there's a single symbol per name.
In Javascript, as we can see, that's right for global symbols. In JavaScript, as we can see, that's right for global symbols.
``` ```
### Symbol.keyFor ### Symbol.keyFor
@ -210,7 +210,7 @@ For non-global symbols, the name is only used for debugging purposes.
## System symbols ## System symbols
There exist many "system" symbols that Javascript uses internally, and we can use them to fine-tune various aspects of our objects. There exist many "system" symbols that JavaScript uses internally, and we can use them to fine-tune various aspects of our objects.
They are listed in the specification in the [Well-known symbols](https://tc39.github.io/ecma262/#sec-well-known-symbols) table: They are listed in the specification in the [Well-known symbols](https://tc39.github.io/ecma262/#sec-well-known-symbols) table:
@ -231,7 +231,7 @@ Other symbols will also become familiar when we study the corresponding language
- Symbols are useful if we want to create a field that only those who know the symbol can access. - Symbols are useful if we want to create a field that only those who know the symbol can access.
- Symbols don't appear in `for..in` loops. - Symbols don't appear in `for..in` loops.
- Symbols created with `Symbol(name)` are always different, even if they have the same name. If we want same-named symbols to be equal, then we should use the global registry: `Symbol.for(name)` returns (creates if needed) a global symbol with the given name. Multiple calls return the same symbol. - Symbols created with `Symbol(name)` are always different, even if they have the same name. If we want same-named symbols to be equal, then we should use the global registry: `Symbol.for(name)` returns (creates if needed) a global symbol with the given name. Multiple calls return the same symbol.
- There are system symbols used by Javascript and accessible as `Symbol.*`. We can use them to alter some built-in behaviors. - There are system symbols used by JavaScript and accessible as `Symbol.*`. We can use them to alter some built-in behaviors.
Technically, symbols are not 100% hidden. There is a build-in method [Object.getOwnPropertySymbols(obj)](mdn:js/Object/getOwnPropertySymbols) that allows to get all symbols. Also there is a method named [Reflect.ownKeys(obj)](mdn:js/Reflect/ownKeys) that returns *all* keys of an object including symbolic ones. So they are not really hidden. Technically, symbols are not 100% hidden. There is a build-in method [Object.getOwnPropertySymbols(obj)](mdn:js/Object/getOwnPropertySymbols) that allows to get all symbols. Also there is a method named [Reflect.ownKeys(obj)](mdn:js/Reflect/ownKeys) that returns *all* keys of an object including symbolic ones. So they are not really hidden.

View file

@ -15,7 +15,7 @@ The error message in most browsers does not give understanding what went wrong.
**The error appears because a semicolon is missing after `user = {...}`.** **The error appears because a semicolon is missing after `user = {...}`.**
Javascript does not assume a semicolon before a bracket `(user.go)()`, so it reads the code like: JavaScript does not assume a semicolon before a bracket `(user.go)()`, so it reads the code like:
```js no-beautify ```js no-beautify
let user = { go:... }(user.go)() let user = { go:... }(user.go)()

View file

@ -36,4 +36,4 @@ Modify the code of `up` and `down` to make the calls chainable, like this:
ladder.up().up().down().showStep(); // 1 ladder.up().up().down().showStep(); // 1
``` ```
Such approach is widely used across Javascript libraries. Such approach is widely used across JavaScript libraries.

View file

@ -11,7 +11,7 @@ let user = {
And, in the real world, a user can `act`: to select something from the shopping cart, to login, to logout etc. And, in the real world, a user can `act`: to select something from the shopping cart, to login, to logout etc.
Let's implement the same in Javascript using functions in properties. Let's implement the same in JavaScript using functions in properties.
[cut] [cut]
@ -164,7 +164,7 @@ If we used `this.name` instead of `user.name` inside the `alert`, then the code
## "this" is not bound ## "this" is not bound
In Javascript, "this" keyword behaves unlike most other programming languages. First, it can be used in any function. In JavaScript, "this" keyword behaves unlike most other programming languages. First, it can be used in any function.
There's no syntax error in the code like that: There's no syntax error in the code like that:
@ -227,7 +227,7 @@ Here we are not to judge whether this language design decision is good or bad. W
## Internals: Reference Type ## Internals: Reference Type
```warn header="In-depth language feature" ```warn header="In-depth language feature"
This section covers advanced topic that may interest those who want to know Javascript better. This section covers advanced topic that may interest those who want to know JavaScript better.
If you want to go on faster, it can be skipped or postponed. If you want to go on faster, it can be skipped or postponed.
``` ```
@ -279,7 +279,7 @@ hi(); // Error, because this is undefined
That's because a function is a value of its own. It does not carry the object. So `hi = user.hi` saves it into the variable, and then on the last line it is completely standalone. That's because a function is a value of its own. It does not carry the object. So `hi = user.hi` saves it into the variable, and then on the last line it is completely standalone.
**To make `user.hi()` calls work, Javascript uses a trick -- the dot `'.'` returns not a function, but a value of the special [Reference Type](https://tc39.github.io/ecma262/#sec-reference-specification-type).** **To make `user.hi()` calls work, JavaScript uses a trick -- the dot `'.'` returns not a function, but a value of the special [Reference Type](https://tc39.github.io/ecma262/#sec-reference-specification-type).**
The Reference Type is a "specification type". We can't explicitly use it, but it is used internally by the language. The Reference Type is a "specification type". We can't explicitly use it, but it is used internally by the language.

View file

@ -24,7 +24,7 @@ Still, there are still valid reasons why we should know how to-primitive convers
- Simple object-as-string output (`alert` and alike) is useable sometimes. - Simple object-as-string output (`alert` and alike) is useable sometimes.
- Many built-in objects implement their own to-primitive conversion, we need to know how to work with that. - Many built-in objects implement their own to-primitive conversion, we need to know how to work with that.
- Sometimes an unexpected conversion happens, and we should understand what's going on. - Sometimes an unexpected conversion happens, and we should understand what's going on.
- The final one. There are quizzes and questions on interviews that rely on that knowledge. Looks like people think it's a good sign that person understands Javascript if he knows type conversions well. - The final one. There are quizzes and questions on interviews that rely on that knowledge. Looks like people think it's a good sign that person understands JavaScript if he knows type conversions well.
## ToPrimitive ## ToPrimitive
@ -81,7 +81,7 @@ When a built-in function (like `alert` or mathematical functions) or an operator
Please note -- there are only three hints. That simple. There is no "boolean" hint (all objects are `true` in boolean context) or anything else. And if we treat `"default"` and `"number"` the same, like most built-ins do, then there are only two conversions. Please note -- there are only three hints. That simple. There is no "boolean" hint (all objects are `true` in boolean context) or anything else. And if we treat `"default"` and `"number"` the same, like most built-ins do, then there are only two conversions.
**To do the conversion, Javascript tries to find and call three object methods:** **To do the conversion, JavaScript tries to find and call three object methods:**
1. Call `obj[Symbol.toPrimitive](hint)` if the method exists, 1. Call `obj[Symbol.toPrimitive](hint)` if the method exists,
2. Otherwise if hint is `"string"` 2. Otherwise if hint is `"string"`
@ -126,7 +126,7 @@ As we can see from the code, `user` becomes a self-descriptive string or a money
Methods `toString` and `valueOf` come from ancient times. They are not symbols (symbols did not exist that long ago), but rather "regular" string-named methods. They provide an alternative "old-style" way to implement the conversion. Methods `toString` and `valueOf` come from ancient times. They are not symbols (symbols did not exist that long ago), but rather "regular" string-named methods. They provide an alternative "old-style" way to implement the conversion.
If there's no `Symbol.toPrimitive` then Javascript tries to find them and try in the order: If there's no `Symbol.toPrimitive` then JavaScript tries to find them and try in the order:
- `toString -> valueOf` for "string" hint. - `toString -> valueOf` for "string" hint.
- `valueOf -> toString` otherwise. - `valueOf -> toString` otherwise.

View file

@ -210,7 +210,7 @@ john = {
We can use constructor functions to make multiple similar objects. But the topic is much deeper than described here. So we'll return it later and cover more in-depth. We can use constructor functions to make multiple similar objects. But the topic is much deeper than described here. So we'll return it later and cover more in-depth.
As of now, it's important to understand what `new` is, because Javascript provides constructor functions for many built-in language objects: like `Date` for dates, `Set` for sets and others that we plan to study. As of now, it's important to understand what `new` is, because JavaScript provides constructor functions for many built-in language objects: like `Date` for dates, `Set` for sets and others that we plan to study.

View file

@ -34,7 +34,7 @@ There exist many built-in objects, including those that work with dates, errors,
But features come at a price! But features come at a price!
Objects are "heavier" than primitives. They require additional resources to support the internal machinery. But properties and methods are useful in programming, Javascript engines try to optimize them, so the price is usually fair. Objects are "heavier" than primitives. They require additional resources to support the internal machinery. But properties and methods are useful in programming, JavaScript engines try to optimize them, so the price is usually fair.
## A primitive as an object ## A primitive as an object
@ -85,7 +85,7 @@ We'll see more specific methods in chapters <info:number> and <info:string>.
````warn header="Constructors `String/Number/Boolean` are for internal use only" ````warn header="Constructors `String/Number/Boolean` are for internal use only"
Some languages like Java allow to create "wrapper objects" for primitives explicitly using syntax like `new Number(1)` or `new Boolean(false)`. Some languages like Java allow to create "wrapper objects" for primitives explicitly using syntax like `new Number(1)` or `new Boolean(false)`.
In Javascript that's also possible for historical reasons, but highly not recommended. Things will go crazy in many places. In JavaScript that's also possible for historical reasons, but highly not recommended. Things will go crazy in many places.
For instance: For instance:

View file

@ -331,7 +331,7 @@ There is a special built-in method [Object.is](mdn:js/Object/is) that compares v
In all other cases, `Object.is(a, b)` is the same as `a === b`. In all other cases, `Object.is(a, b)` is the same as `a === b`.
This way of comparison is often used in Javascript specification. When an internal algorithm needs to compare two values for being exactly the same, it uses `Object.is` (internally called [SameValue](https://tc39.github.io/ecma262/#sec-samevalue)). This way of comparison is often used in JavaScript specification. When an internal algorithm needs to compare two values for being exactly the same, it uses `Object.is` (internally called [SameValue](https://tc39.github.io/ecma262/#sec-samevalue)).
``` ```

View file

@ -110,7 +110,7 @@ Of course, that refers only for the quotes that are same as the enclosing ones.
alert( `I'm the Walrus!` ); // I'm the Walrus! alert( `I'm the Walrus!` ); // I'm the Walrus!
``` ```
Note that the backslash `\` serves for the correct reading of the string by Javascript, then disappears. The in-memory string has no `\`. You can clearly see that in `alert` from the examples above. Note that the backslash `\` serves for the correct reading of the string by JavaScript, then disappears. The in-memory string has no `\`. You can clearly see that in `alert` from the examples above.
But what if we need exactly a backslash `\` in the string? But what if we need exactly a backslash `\` in the string?
@ -451,7 +451,7 @@ Let's recap the methods to avoid any confusion:
```smart header="Which one to choose?" ```smart header="Which one to choose?"
All of them can do the job. Formally, `substr` has a minor drawback: it is described not in the core Javascript specification, but in Annex B, which covers browser-only features that exist mainly for historical reasons. So, non-browser environments may fail to support it. But in practice it works everywhere. All of them can do the job. Formally, `substr` has a minor drawback: it is described not in the core JavaScript specification, but in Annex B, which covers browser-only features that exist mainly for historical reasons. So, non-browser environments may fail to support it. But in practice it works everywhere.
The author finds himself using `slice` almost all the time. The author finds himself using `slice` almost all the time.
``` ```
@ -572,7 +572,7 @@ alert( '😂'.length ); // 2, FACE WITH TEARS OF JOY
alert( '𩷶'.length ); // 2, a rare chinese hieroglyph alert( '𩷶'.length ); // 2, a rare chinese hieroglyph
``` ```
Note that surrogate pairs did not exist at the time when Javascript was created, and thus are not correctly processed by the language! Note that surrogate pairs did not exist at the time when JavaScript was created, and thus are not correctly processed by the language!
We actually have a single symbol in each of the strings above, but the `length` shows the length of `2`. We actually have a single symbol in each of the strings above, but the `length` shows the length of `2`.

View file

@ -123,7 +123,7 @@ A stack is usually illustrated as a pack of cards: new cards are added to the to
For stacks, the latest pushed item is received first, that's also called LIFO (Last-In-First-Out) principle. For queues, we have FIFO (First-In-First-Out). For stacks, the latest pushed item is received first, that's also called LIFO (Last-In-First-Out) principle. For queues, we have FIFO (First-In-First-Out).
Arrays in Javascript can work both as a queue and as a stack. They allow to add/remove elements both to/from the beginning or the end. Arrays in JavaScript can work both as a queue and as a stack. They allow to add/remove elements both to/from the beginning or the end.
In computer science the data structure that allows it is called [deque](https://en.wikipedia.org/wiki/Double-ended_queue). In computer science the data structure that allows it is called [deque](https://en.wikipedia.org/wiki/Double-ended_queue).
@ -235,7 +235,7 @@ The ways to misuse an array:
- Make holes, like: add `arr[0]` and then `arr[1000]` (and nothing between them). - Make holes, like: add `arr[0]` and then `arr[1000]` (and nothing between them).
- Fill the array in the reverse order, like `arr[1000]`, `arr[999]` and so on. - Fill the array in the reverse order, like `arr[1000]`, `arr[999]` and so on.
Please think of arrays as about special structures to work with the *ordered data*. They provide special methods for that. Arrays are carefully tuned inside Javascript engines to work with contiguous ordered data, please use them this way. And if you need arbitrary keys, chances are high that you actually require a regular object `{}`. Please think of arrays as about special structures to work with the *ordered data*. They provide special methods for that. Arrays are carefully tuned inside JavaScript engines to work with contiguous ordered data, please use them this way. And if you need arbitrary keys, chances are high that you actually require a regular object `{}`.
## Performance ## Performance

View file

@ -28,7 +28,7 @@ The method `result.includes(str)` internally walks the array `result` and compar
So if there are `100` elements in `result` and no one matches `str`, then it will walk the whole `result` and do exactly `100` comparisons. And if `result` is large, like `10000`, then there would be `10000` comparisons. So if there are `100` elements in `result` and no one matches `str`, then it will walk the whole `result` and do exactly `100` comparisons. And if `result` is large, like `10000`, then there would be `10000` comparisons.
That's not a problem by itself, because Javascript engines are very fast, so walk `10000` array is a matter of microseconds. That's not a problem by itself, because JavaScript engines are very fast, so walk `10000` array is a matter of microseconds.
But we do such test for each element of `arr`, in the `for` loop. But we do such test for each element of `arr`, in the `for` loop.

View file

@ -5,7 +5,7 @@
Arrays by themselves are iterable. But not only arrays. Strings are iterable too, and many other built-in objects as well. Arrays by themselves are iterable. But not only arrays. Strings are iterable too, and many other built-in objects as well.
Iterables are widely used by the core Javascript, as we'll see many operators and built-in methods rely on them. Iterables are widely used by the core JavaScript, as we'll see many operators and built-in methods rely on them.
[cut] [cut]

View file

@ -32,7 +32,7 @@ For plain objects, the following methods are available:
The first difference is that we have to call `Object.keys(obj)`, and not `obj.keys()`. The first difference is that we have to call `Object.keys(obj)`, and not `obj.keys()`.
Why so? There main reason is flexibility. Remember, objects are a base of all complex structures in Javascript. So we may have an object of our own like `order` that implements its own `order.values()` method. And we still can call `Object.values(order)` on it. Why so? There main reason is flexibility. Remember, objects are a base of all complex structures in JavaScript. So we may have an object of our own like `order` that implements its own `order.values()` method. And we still can call `Object.values(order)` on it.
The second difference is that `Object.*` methods return "real" array objects, not just an iterable. That's mainly for historical reasons. The second difference is that `Object.*` methods return "real" array objects, not just an iterable. That's mainly for historical reasons.

View file

@ -1,6 +1,6 @@
# Destructuring assignment # Destructuring assignment
The two most used data structures in Javascript are `Object` and `Array`. The two most used data structures in JavaScript are `Object` and `Array`.
Objects allow to pack many pieces of information into a single entity and arrays allow to store ordered collections. So we can make an object or an array and handle it as a single thing, maybe pass to a function call. Objects allow to pack many pieces of information into a single entity and arrays allow to store ordered collections. So we can make an object or an array and handle it as a single thing, maybe pass to a function call.
@ -326,7 +326,7 @@ let title, width, height;
{title, width, height} = {title: "Menu", width: 200, height: 100}; {title, width, height} = {title: "Menu", width: 200, height: 100};
``` ```
The problem is that Javascript treats `{...}` in the main code flow (not inside another expression) as a code block. Such code blocks can be used to group statements, like this: The problem is that JavaScript treats `{...}` in the main code flow (not inside another expression) as a code block. Such code blocks can be used to group statements, like this:
```js run ```js run
{ {
@ -337,7 +337,7 @@ The problem is that Javascript treats `{...}` in the main code flow (not inside
} }
``` ```
To show Javascript that it's not a code block, we can wrap the whole assignment in brackets `(...)`: To show JavaScript that it's not a code block, we can wrap the whole assignment in brackets `(...)`:
```js run ```js run
let title, width, height; let title, width, height;

View file

@ -408,7 +408,7 @@ alert( date );
Note that unlike many other systems, timestamps in JavaScript are in milliseconds, not in seconds. Note that unlike many other systems, timestamps in JavaScript are in milliseconds, not in seconds.
Also, sometimes we need more precise time measurements. Javascript itself does not have a way to measure time in microseconds (1 millionth of a second), but most environments provide it. Also, sometimes we need more precise time measurements. JavaScript itself does not have a way to measure time in microseconds (1 millionth of a second), but most environments provide it.
For instance, browser has [performance.now()](mdn:api/Performance/now) that gives the number of milliseconds from the start of page loading, but adds 3 digits after the point to it. So totally it becomes microsecond percision: For instance, browser has [performance.now()](mdn:api/Performance/now) that gives the number of milliseconds from the start of page loading, but adds 3 digits after the point to it. So totally it becomes microsecond percision:

View file

@ -29,9 +29,9 @@ Luckily, there's no need to write the code to handle all this. The task has been
## JSON.stringify ## JSON.stringify
The [JSON](http://en.wikipedia.org/wiki/JSON) (JavaScript Object Notation) is a general format to represent values and objects. It is described as in [RFC 4627](http://tools.ietf.org/html/rfc4627) standard. Initially it was made for Javascript, but many other languages have libraries to handle it as well. So it's easy to use JSON for data exchange when the client uses Javascript and the server is written on Ruby/PHP/Java/Whatever. The [JSON](http://en.wikipedia.org/wiki/JSON) (JavaScript Object Notation) is a general format to represent values and objects. It is described as in [RFC 4627](http://tools.ietf.org/html/rfc4627) standard. Initially it was made for JavaScript, but many other languages have libraries to handle it as well. So it's easy to use JSON for data exchange when the client uses JavaScript and the server is written on Ruby/PHP/Java/Whatever.
Javascript provides methods: JavaScript provides methods:
- `JSON.stringify` to convert objects into JSON. - `JSON.stringify` to convert objects into JSON.
- `JSON.parse` to convert JSON back into an object. - `JSON.parse` to convert JSON back into an object.
@ -102,7 +102,7 @@ alert( JSON.stringify(true) ); // true
alert( JSON.stringify([1, 2, 3]) ); // [1,2,3] alert( JSON.stringify([1, 2, 3]) ); // [1,2,3]
``` ```
JSON is data-only cross-language specification, so some Javascript-specific object properties are skipped by `JSON.stringify`. JSON is data-only cross-language specification, so some JavaScript-specific object properties are skipped by `JSON.stringify`.
Namely: Namely:
@ -292,7 +292,7 @@ The third argument of `JSON.stringify(value, replacer, spaces)` is the number of
Previously, all stringified objects had no indents and extra spaces. That's fine if we want to send an object over a network. The `spacer` argument is used exclusively for a nice output. Previously, all stringified objects had no indents and extra spaces. That's fine if we want to send an object over a network. The `spacer` argument is used exclusively for a nice output.
Here `spacer = 2` tells Javascript to show nested objects on multiple lines, with indentation of 2 spaces inside an object: Here `spacer = 2` tells JavaScript to show nested objects on multiple lines, with indentation of 2 spaces inside an object:
```js run ```js run
let user = { let user = {
@ -463,7 +463,7 @@ It looks like this:
let str = '{"title":"Conference","date":"2017-11-30T12:00:00.000Z"}'; let str = '{"title":"Conference","date":"2017-11-30T12:00:00.000Z"}';
``` ```
...And now we reed to *deserialize* it, to turn back into Javascript object. ...And now we reed to *deserialize* it, to turn back into JavaScript object.
Let's do it by calling `JSON.parse`: Let's do it by calling `JSON.parse`:
@ -522,6 +522,6 @@ alert( schedule.meetups[1].date.getDate() ); // works!
- JSON is a data format that has its own independent standard and libraries for most programming languages. - JSON is a data format that has its own independent standard and libraries for most programming languages.
- JSON supports plain objects, arrays, strings, numbers, booleans and `null`. - JSON supports plain objects, arrays, strings, numbers, booleans and `null`.
- Javascript provides methods [JSON.stringify](mdn:js/JSON/stringify) to serialize into JSON and [JSON.parse](mdn:js/JSON/parse) to read from JSON. - JavaScript provides methods [JSON.stringify](mdn:js/JSON/stringify) to serialize into JSON and [JSON.parse](mdn:js/JSON/parse) to read from JSON.
- Both methods support transformer functions for smart reading/writing. - Both methods support transformer functions for smart reading/writing.
- If an object has `toJSON`, then it is called by `JSON.stringify`. - If an object has `toJSON`, then it is called by `JSON.stringify`.

View file

@ -37,4 +37,4 @@ P.S. Naturally, the formula is the fastest solution. It uses only 3 operations f
The loop variant is the second in terms of speed. In both the recursive and the loop variant we sum the same numbers. But the recursion involves nested calls and execution stack management. That also takes resources, so it's slower. The loop variant is the second in terms of speed. In both the recursive and the loop variant we sum the same numbers. But the recursion involves nested calls and execution stack management. That also takes resources, so it's slower.
P.P.S. The standard describes a "tail call" optimization: if the recursive call is the very last one in the function (like in `sumTo` above), then the outer function will not need to resume the execution and we don't need to remember its execution context. In that case `sumTo(100000)` is countable. But if your Javascript engine does not support it, there will be an error: maximum stack size exceeded, because there's usually a limitation on the total stack size. P.P.S. The standard describes a "tail call" optimization: if the recursive call is the very last one in the function (like in `sumTo` above), then the outer function will not need to resume the execution and we don't need to remember its execution context. In that case `sumTo(100000)` is countable. But if your JavaScript engine does not support it, there will be an error: maximum stack size exceeded, because there's usually a limitation on the total stack size.

View file

@ -98,7 +98,7 @@ function pow(x, n) {
The maximal number of nested calls (including the first one) is called *recursion depth*. In our case, it there will be exactly `n`. The maximal number of nested calls (including the first one) is called *recursion depth*. In our case, it there will be exactly `n`.
The maximal recursion depth is limited by Javascript engine. We can make sure about 10000, some engines allow more, but 100000 is probably out of limit for the majority of them. There are automatic optimizations that help to alleviate this ("tail calls optimizations"), but they are not yet supported everywhere and work only in simple cases. The maximal recursion depth is limited by JavaScript engine. We can make sure about 10000, some engines allow more, but 100000 is probably out of limit for the majority of them. There are automatic optimizations that help to alleviate this ("tail calls optimizations"), but they are not yet supported everywhere and work only in simple cases.
That limits the application of recursion, but it still remains very wide. There are many tasks where recursive way of thinking gives simpler code, easier to maintain. That limits the application of recursion, but it still remains very wide. There are many tasks where recursive way of thinking gives simpler code, easier to maintain.
@ -164,7 +164,7 @@ To calculate `x*pow(x, n-1)`, we need to make a subcall of `pow` with new argume
### pow(2, 2) ### pow(2, 2)
To do a nested call, Javascript remembers the current execution context in the *execution context stack*. To do a nested call, JavaScript remembers the current execution context in the *execution context stack*.
Here we call the same function `pow`, but it absolutely doesn't matter. The process is the same for all functions: Here we call the same function `pow`, but it absolutely doesn't matter. The process is the same for all functions:

View file

@ -1,6 +1,6 @@
# Rest parameters and spread operator # Rest parameters and spread operator
Many Javascript built-in functions support on arbitrary number of arguments. Many JavaScript built-in functions support on arbitrary number of arguments.
For instance: For instance:

View file

@ -1,7 +1,7 @@
# Closure # Closure
Javascript is a very function-oriented language, it gives a lot of freedom. A function can be created at one moment, then passed as a value to another variable or function and called from a totally different place much later. JavaScript is a very function-oriented language, it gives a lot of freedom. A function can be created at one moment, then passed as a value to another variable or function and called from a totally different place much later.
We know that a function can access variables outside of it. And this feature is used quite often. We know that a function can access variables outside of it. And this feature is used quite often.
@ -9,7 +9,7 @@ But what happens when outer variables change? Does a function get a new value or
Also, what happens when a variable with the function travels to another place of the code and is called from there -- will it get access to outer variables in the new place? Also, what happens when a variable with the function travels to another place of the code and is called from there -- will it get access to outer variables in the new place?
There is no general programming answer for these questions. Different languages behave differently. Here we'll cover Javascript. There is no general programming answer for these questions. Different languages behave differently. Here we'll cover JavaScript.
[cut] [cut]
@ -65,7 +65,7 @@ Let's formulate two questions for the seed, and then study internal mechanics pi
To understand what's going on, let's first discuss what a "variable" technically is. To understand what's going on, let's first discuss what a "variable" technically is.
In Javascript, every running function, code block and the script as a whole have an associated object named *Lexical Environment*. In JavaScript, every running function, code block and the script as a whole have an associated object named *Lexical Environment*.
The Lexical Environment object consists of two parts: The Lexical Environment object consists of two parts:
@ -186,7 +186,7 @@ And if a function is called multiple times, then each invocation will have its o
``` ```
```smart header="Lexical Environment is a specification object" ```smart header="Lexical Environment is a specification object"
"Lexical Environment" is a specification object. We can't get this object in our code and manipulate it directly. Javascript engines also may optimize it, discard variables that are unused in the code and perform other stuff. "Lexical Environment" is a specification object. We can't get this object in our code and manipulate it directly. JavaScript engines also may optimize it, discard variables that are unused in the code and perform other stuff.
``` ```
@ -361,11 +361,11 @@ So, the result is `"Pete"` here.
```smart header="Closures" ```smart header="Closures"
There is a general programming term "closure", that developers generally should know. There is a general programming term "closure", that developers generally should know.
A [closure](https://en.wikipedia.org/wiki/Closure_(computer_programming)) is a function that remembers its outer variables and can access them. In some languages, that's not possible, or a function should be written in a special way to make it happen. But as explained above, in Javascript all functions are naturally closures (there is only one exclusion, to be covered in <info:new-function>). A [closure](https://en.wikipedia.org/wiki/Closure_(computer_programming)) is a function that remembers its outer variables and can access them. In some languages, that's not possible, or a function should be written in a special way to make it happen. But as explained above, in JavaScript all functions are naturally closures (there is only one exclusion, to be covered in <info:new-function>).
That is: they automatically remember where they are created using a hidden `[[Environment]]` property, and all of them can access outer variables. That is: they automatically remember where they are created using a hidden `[[Environment]]` property, and all of them can access outer variables.
When on an interview a frontend developer gets a question about "what's a closure?", a valid answer would be a definition of the closure and an explanation that all functions in Javascript are closures, and maybe few more words about technical details: the `[[Environment]]` property and how Lexical Environments work. When on an interview a frontend developer gets a question about "what's a closure?", a valid answer would be a definition of the closure and an explanation that all functions in JavaScript are closures, and maybe few more words about technical details: the `[[Environment]]` property and how Lexical Environments work.
``` ```
## Code blocks and loops, IIFE ## Code blocks and loops, IIFE
@ -439,7 +439,7 @@ They look like this:
Here a Function Expression is created and immediately called. So the code executes right now and has its own private variables. Here a Function Expression is created and immediately called. So the code executes right now and has its own private variables.
The Function Expression is wrapped with brackets `(function {...})`, because when Javascript meets `"function"` in the main code flow, it understands it as a start of Function Declaration. But a Function Declaration must have a name, so there will be an error: The Function Expression is wrapped with brackets `(function {...})`, because when JavaScript meets `"function"` in the main code flow, it understands it as a start of Function Declaration. But a Function Declaration must have a name, so there will be an error:
```js run ```js run
// Error: Unexpected token ( // Error: Unexpected token (
@ -452,7 +452,7 @@ function() { // <-- JavaScript cannot find function name, meets ( and gives erro
}(); }();
``` ```
We can say "okay, let it be Function Declaration, let's add a name", but it won't work. Javascript does not allow Function Declarations to be called immediately: We can say "okay, let it be Function Declaration, let's add a name", but it won't work. JavaScript does not allow Function Declarations to be called immediately:
```js run ```js run
// syntax error because of brackets below // syntax error because of brackets below
@ -461,9 +461,9 @@ function go() {
}(); // <-- can't call Function Declaration immediately }(); // <-- can't call Function Declaration immediately
``` ```
So the brackets are needed to show Javascript that the function is created in the context of another expression, and hence it's a Function Expression. Needs no name and can be called immediately. So the brackets are needed to show JavaScript that the function is created in the context of another expression, and hence it's a Function Expression. Needs no name and can be called immediately.
There are other ways to tell Javascript that we mean Function Expression: There are other ways to tell JavaScript that we mean Function Expression:
```js run ```js run
// Ways to create IIFE // Ways to create IIFE
@ -555,7 +555,7 @@ Lexical Environment objects that we've been talking about are subjects to same m
As we've seen, in theory while a function is alive, all outer variabels are also retained. As we've seen, in theory while a function is alive, all outer variabels are also retained.
But in practice, Javascript engines try to optimize that. They analyze variable usage and if it's easy to see that an outer variable is not used -- it is removed. But in practice, JavaScript engines try to optimize that. They analyze variable usage and if it's easy to see that an outer variable is not used -- it is removed.
**An important side effect in V8 (Chrome, Opera) is that such variable will become unavailable in debugging.** **An important side effect in V8 (Chrome, Opera) is that such variable will become unavailable in debugging.**
@ -677,7 +677,7 @@ alert(phrase); // Error, phrase is not defined
alert(phrase); // Error: phrase is not defined alert(phrase); // Error: phrase is not defined
``` ```
As we can see, `var` pierces through `if`, `for` or other code blocks. That's because long time ago in Javascript blocks had no Lexical Environments. And `var` is a reminiscence of that. As we can see, `var` pierces through `if`, `for` or other code blocks. That's because long time ago in JavaScript blocks had no Lexical Environments. And `var` is a reminiscence of that.
`var` declarations are processed when the function starts (or script starts for globals). `var` declarations are processed when the function starts (or script starts for globals).
: In other words, `var` variables are defined from the beginning of the function. : In other words, `var` variables are defined from the beginning of the function.

View file

@ -2,9 +2,9 @@
# Global object # Global object
When Javascript was created, there was an idea of a "global object" that provides all global variables and functions. It was planned that multiple in-browser scripts would use that single global object and share variables through it. When JavaScript was created, there was an idea of a "global object" that provides all global variables and functions. It was planned that multiple in-browser scripts would use that single global object and share variables through it.
Since then, Javascript greatly evolved, and that idea of linking code through global variables became much less appealing. In modern Javascript, the concept of modules too its place. Since then, JavaScript greatly evolved, and that idea of linking code through global variables became much less appealing. In modern JavaScript, the concept of modules too its place.
But the global object still remains in the specification. But the global object still remains in the specification.
@ -119,7 +119,7 @@ Usually, it's not a good idea to use it, but here are some examples you can meet
3. To take the variable from the right window. That's probably the most valid use case. 3. To take the variable from the right window. That's probably the most valid use case.
A browser may open multiple windows and tabs. A window may also embed another one in `<iframe>`. Every browser window has its own `window` object and global variables. Javascript allows windows that come from the same site (same protocol, host, port) to access variables from each other. A browser may open multiple windows and tabs. A window may also embed another one in `<iframe>`. Every browser window has its own `window` object and global variables. JavaScript allows windows that come from the same site (same protocol, host, port) to access variables from each other.
That use is a little bit beyound our scope for now, but it looks like: That use is a little bit beyound our scope for now, but it looks like:
```html run ```html run

View file

@ -1,11 +1,11 @@
# Function object, NFE # Function object, NFE
As we already know, functions in Javascript are values. As we already know, functions in JavaScript are values.
Every value in Javascript has the type. What type of value is a function? Every value in JavaScript has the type. What type of value is a function?
In Javascript, a function is an object. In JavaScript, a function is an object.
A good way to imagine functions is as callable "action objects". We can not only call them, but also treat them as objects: add/remove properties, pass by reference etc. A good way to imagine functions is as callable "action objects". We can not only call them, but also treat them as objects: add/remove properties, pass by reference etc.
@ -127,7 +127,7 @@ function ask(question, ...handlers) {
ask("Question?", () => alert('You said yes'), result => alert(result)); ask("Question?", () => alert('You said yes'), result => alert(result));
``` ```
This is a particular case of so-called [polymorphism](https://en.wikipedia.org/wiki/Polymorphism_(computer_science)) -- treating arguments differently depending on their type or, in our case depending on the `length`. The idea does have a use in Javascript libraries. This is a particular case of so-called [polymorphism](https://en.wikipedia.org/wiki/Polymorphism_(computer_science)) -- treating arguments differently depending on their type or, in our case depending on the `length`. The idea does have a use in JavaScript libraries.
## Custom properties ## Custom properties
@ -347,7 +347,7 @@ Here we covered their properties:
If the function is declared as a Function Expression (not in the main code flow), and it carries the name, then it is called Named Function Expression. The name can be used inside to reference itself, for recursive calls or such. If the function is declared as a Function Expression (not in the main code flow), and it carries the name, then it is called Named Function Expression. The name can be used inside to reference itself, for recursive calls or such.
Also, functions may carry additional properties. Many well-known Javascript libraries make a great use of this feature. Also, functions may carry additional properties. Many well-known JavaScript libraries make a great use of this feature.
They create a "main" function and attach many other "helper" functions to it. For instance, the [jquery](https://jquery.com) library creates a function named `$`. The [lodash](https://lodash.com) library creates a function `_`. And then adds `_.clone`, `_.keyBy` and other properties to (see the [docs](https://lodash.com/docs) when you want learn more about them). Actually, they do it to less pollute the global space, so that a single library gives only one global variable. That lowers the chance of possible naming conflicts. They create a "main" function and attach many other "helper" functions to it. For instance, the [jquery](https://jquery.com) library creates a function named `$`. The [lodash](https://lodash.com) library creates a function `_`. And then adds `_.clone`, `_.keyBy` and other properties to (see the [docs](https://lodash.com/docs) when you want learn more about them). Actually, they do it to less pollute the global space, so that a single library gives only one global variable. That lowers the chance of possible naming conflicts.

View file

@ -91,7 +91,7 @@ Our new function needs to interact with the main script.
Maybe we want it to be able to access outer local variables? Maybe we want it to be able to access outer local variables?
But the problem is that before Javascript is published to production, it's compressed using a *minifier* -- a special program that shrinks code by removing extra comments, spaces and -- what's important, renames local variables into shorter ones. But the problem is that before JavaScript is published to production, it's compressed using a *minifier* -- a special program that shrinks code by removing extra comments, spaces and -- what's important, renames local variables into shorter ones.
For instance, if a function has `let userName`, minifier replaces it `let a` (or another letter if this one is occupied), and does it everywhere. That's usually a safe thing to do, because the variable is local, nothing outside the function can access it. And inside the function minifier replaces every mention of it. Minifiers are smart, they analyze the code structure, not just find-and-replace, so that's ok. For instance, if a function has `let userName`, minifier replaces it `let a` (or another letter if this one is occupied), and does it everywhere. That's usually a safe thing to do, because the variable is local, nothing outside the function can access it. And inside the function minifier replaces every mention of it. Minifiers are smart, they analyze the code structure, not just find-and-replace, so that's ok.

View file

@ -7,7 +7,7 @@ There are two methods for it:
- `setTimeout` allows to run a function once after the given interval of time. - `setTimeout` allows to run a function once after the given interval of time.
- `setInterval` allows to run of the function regularly with the given interval between the runs. - `setInterval` allows to run of the function regularly with the given interval between the runs.
These methods are not a part of Javascript specification. But most environments have the internal scheduler and provide these methods. In particular, they are supported in all browsers and Node.JS. These methods are not a part of JavaScript specification. But most environments have the internal scheduler and provide these methods. In particular, they are supported in all browsers and Node.JS.
[cut] [cut]
@ -57,7 +57,7 @@ setTimeout(sayHi, 1000, "John", "Hello"); // Hello, John
*/!* */!*
``` ```
If the first argument is a string, then Javascript creates a function from it. If the first argument is a string, then JavaScript creates a function from it.
So, this will also work: So, this will also work:
@ -245,7 +245,7 @@ So we can split the long text to pieces. First 100 lines, then plan another 100
As a simpler example -- here's a counting function from `1` to `1000000000`. As a simpler example -- here's a counting function from `1` to `1000000000`.
If you run it, the CPU will hang. For server-side JS that's clearly noticeable, and if you are running it in-browser, then try to scroll and click other buttons on the page -- you'll see that whole Javascript actually is paused, no other actions work until it finishes. If you run it, the CPU will hang. For server-side JS that's clearly noticeable, and if you are running it in-browser, then try to scroll and click other buttons on the page -- you'll see that whole JavaScript actually is paused, no other actions work until it finishes.
```js run ```js run
let i = 0; let i = 0;
@ -348,7 +348,7 @@ setTimeout(function run() {
First timers run immediately (just as written in the spec), and then the delay comes into play. That limitation comes from ancient times and many scripts rely on it, so it exists for historical reasons. First timers run immediately (just as written in the spec), and then the delay comes into play. That limitation comes from ancient times and many scripts rely on it, so it exists for historical reasons.
For server-side Javascript, that limitation does not exist. Also, there are other ways to schedule an immediate asynchronous job. In Node.JS that's [process.nextTick](https://nodejs.org/api/process.html) and [setImmediate](https://nodejs.org/api/timers.html). For server-side JavaScript, that limitation does not exist. Also, there are other ways to schedule an immediate asynchronous job. In Node.JS that's [process.nextTick](https://nodejs.org/api/process.html) and [setImmediate](https://nodejs.org/api/timers.html).
```` ````
## Summary ## Summary

View file

@ -1,6 +1,6 @@
# Decorators and forwarding, call/apply # Decorators and forwarding, call/apply
Javascript gives exceptional flexibility when dealing with functions. They can be passed around, used as objects, and now we'll see how to *forward* calls between them and *decorate* them. JavaScript gives exceptional flexibility when dealing with functions. They can be passed around, used as objects, and now we'll see how to *forward* calls between them and *decorate* them.
[cut] [cut]
@ -307,7 +307,7 @@ If we look more closely, there's a minor difference between such uses of `call`
So, these calls complement to each other. Where we expect an iterable, `call` works, where we expect an array-like, `apply` works. So, these calls complement to each other. Where we expect an iterable, `call` works, where we expect an array-like, `apply` works.
And if `args` is both iterable and array-like, like a real array, then we technically could use any of them, but `apply` will probably be faster, because it's a single operation. Most Javascript engines internally optimize is better than a pair `call + spread`. And if `args` is both iterable and array-like, like a real array, then we technically could use any of them, but `apply` will probably be faster, because it's a single operation. Most JavaScript engines internally optimize is better than a pair `call + spread`.
One of most important uses of `apply` is passing the call to another function, like this: One of most important uses of `apply` is passing the call to another function, like this:

View file

@ -13,7 +13,7 @@ Suddenly, `this` just stops working right. The situation is typical for novice d
## Loosing "this" ## Loosing "this"
We already know that in Javascript it's easy to loose `this`. Once a method is passed somewhere separately from the object -- `this` is lost. We already know that in JavaScript it's easy to loose `this`. Once a method is passed somewhere separately from the object -- `this` is lost.
Here's how it may happen with `setTimeout`: Here's how it may happen with `setTimeout`:
@ -195,7 +195,7 @@ for (let key in user) {
} }
``` ```
Javascript libraries also provide functions for convenient mass binding , e.g. [_.bindAll(obj)](http://lodash.com/docs#bindAll) in lodash. JavaScript libraries also provide functions for convenient mass binding , e.g. [_.bindAll(obj)](http://lodash.com/docs#bindAll) in lodash.
```` ````
@ -479,7 +479,7 @@ The currying requires the function to have a known fixed number of arguments.
```smart header="A little more than currying" ```smart header="A little more than currying"
By definition, currying should convert `sum(a, b, c)` into `sum(a)(b)(c)`. By definition, currying should convert `sum(a, b, c)` into `sum(a)(b)(c)`.
But most implementations of currying in Javascript are advanced, as described: they also keep the function callable in the multi-argument variant. But most implementations of currying in JavaScript are advanced, as described: they also keep the function callable in the multi-argument variant.
``` ```
## Summary ## Summary
@ -492,6 +492,6 @@ But most implementations of currying in Javascript are advanced, as described: t
Partials are convenient when we don't want to repeat the same argument over and over again. Like if we have a `send(from, to)` function, and `from` should always be the same for our task, we can get a partial and go on with it. Partials are convenient when we don't want to repeat the same argument over and over again. Like if we have a `send(from, to)` function, and `from` should always be the same for our task, we can get a partial and go on with it.
- *Currying* is a transform that makes `f(a,b,c)` callable as `f(a)(b)(c)`. Javascript implementations usually both keep the function callable normally and return the partial if arguments count is not enough. - *Currying* is a transform that makes `f(a,b,c)` callable as `f(a)(b)(c)`. JavaScript implementations usually both keep the function callable normally and return the partial if arguments count is not enough.
Currying is great when we want easy partials. As we've seen in the logging example: the universal function `log(date, importance, message)` after currying gives us partials when called with one argument like `log(date)` or two arguments `log(date, importance)`. Currying is great when we want easy partials. As we've seen in the logging example: the universal function `log(date, importance, message)` after currying gives us partials when called with one argument like `log(date)` or two arguments `log(date, importance)`.

View file

@ -6,7 +6,7 @@ Let's revisit arrow functions.
Arrow functions are not just a "shorthand" for writing small stuff. Arrow functions are not just a "shorthand" for writing small stuff.
Javascript is full of situations where we need to write a small function, that's executed somewhere else. JavaScript is full of situations where we need to write a small function, that's executed somewhere else.
For instance: For instance:
@ -14,7 +14,7 @@ For instance:
- `setTimeout(func)` -- `func` is executed by the built-in scheduler. - `setTimeout(func)` -- `func` is executed by the built-in scheduler.
- ...there are more. - ...there are more.
It's very in the spirit of Javascript to create a function and pass it somewhere. It's very in the spirit of JavaScript to create a function and pass it somewhere.
And in such functions we usually don't want to leave the current context. And in such functions we usually don't want to leave the current context.

View file

@ -11,11 +11,11 @@ For instance, we have a `user` object with its properties and methods, and want
## [[Prototype]] ## [[Prototype]]
In Javascript, objects have a special hidden property `[[Prototype]]` (as named in the specification), that is either `null` or references another object. That object is called "a prototype": In JavaScript, objects have a special hidden property `[[Prototype]]` (as named in the specification), that is either `null` or references another object. That object is called "a prototype":
![prototype](object-prototype-empty.png) ![prototype](object-prototype-empty.png)
That `[[Prototype]]` has a "magical" meaning. When we want to read a property from `object`, and it's missing, Javascript automatically takes it from the prototype. In programming, such thing is called a "prototypal inheritance". Many cool language features and approaches are based on it. That `[[Prototype]]` has a "magical" meaning. When we want to read a property from `object`, and it's missing, JavaScript automatically takes it from the prototype. In programming, such thing is called a "prototypal inheritance". Many cool language features and approaches are based on it.
The property `[[Prototype]]` is internal and hidden, but there are many ways to set it. The property `[[Prototype]]` is internal and hidden, but there are many ways to set it.
@ -36,7 +36,7 @@ rabbit.__proto__ = animal;
Please note that `__proto__` is *not the same* as `[[Prototype]]`. That's a getter/setter for it. We'll talk about other ways of setting it later, as for now `__proto__` will do just fine. Please note that `__proto__` is *not the same* as `[[Prototype]]`. That's a getter/setter for it. We'll talk about other ways of setting it later, as for now `__proto__` will do just fine.
So now if we look for something in `rabbit` and it's missing, Javascript automatically takes it from `animal`. So now if we look for something in `rabbit` and it's missing, JavaScript automatically takes it from `animal`.
For instance: For instance:
@ -126,7 +126,7 @@ alert(longEar.jumps); // true (from rabbit)
There are actually only two limitations: There are actually only two limitations:
1. The references can't go in circles. Javascript will throw an error if we try to assign `__proto__` in circle. 1. The references can't go in circles. JavaScript will throw an error if we try to assign `__proto__` in circle.
2. The value of `__proto__` can be either an object or `null`. All other values (like primitives) are ignored. 2. The value of `__proto__` can be either an object or `null`. All other values (like primitives) are ignored.
Also it may be obvious, but still: there can be only one `[[Prototype]]`. An object may not inherit from two others. Also it may be obvious, but still: there can be only one `[[Prototype]]`. An object may not inherit from two others.
@ -246,8 +246,8 @@ In other words, methods are shared, but the state will be not.
## Summary ## Summary
- In Javascript, all objects have a hidden `[[Prototype]]` property that's either another object or `null`. - In JavaScript, all objects have a hidden `[[Prototype]]` property that's either another object or `null`.
- We can use `obj.__proto__` to access it (there are other ways too, to be covered soon). - We can use `obj.__proto__` to access it (there are other ways too, to be covered soon).
- The object references by `[[Prototype]]` is called a "prototype". - The object references by `[[Prototype]]` is called a "prototype".
- If we want to read a property of `obj` or call a method, and it doesn't exist, then Javascript tries to find it in the prototype. Write/delete operations work directly on the object, they don't use the prototype (unless the property is actually a setter). - If we want to read a property of `obj` or call a method, and it doesn't exist, then JavaScript tries to find it in the prototype. Write/delete operations work directly on the object, they don't use the prototype (unless the property is actually a setter).
- If we call `obj.method()`, and the `method` is taken from the prototype, `this` still references `obj`. So methods always work with the current objects even if they are inherited. - If we call `obj.method()`, and the `method` is taken from the prototype, `this` still references `obj`. So methods always work with the current objects even if they are inherited.

View file

@ -1,6 +1,6 @@
# F.prototype # F.prototype
In modern Javascript we can set a prototype using `__proto__`. But it wasn't like that all the time. In modern JavaScript we can set a prototype using `__proto__`. But it wasn't like that all the time.
[cut] [cut]
@ -12,7 +12,7 @@ But in the old times, there was another (and the only) way to set it: to use a `
As we know already, `new F()` creates a new object. But what we didn't use yet `F.prototype` property. As we know already, `new F()` creates a new object. But what we didn't use yet `F.prototype` property.
That property is used by the Javascript itself to set `[[Prototype]]` for new objects. That property is used by the JavaScript itself to set `[[Prototype]]` for new objects.
**When a new object is created with `new F()`, the `[[Prototype]]` of it is set to `F.prototype`.** **When a new object is created with `new F()`, the `[[Prototype]]` of it is set to `F.prototype`.**

View file

@ -1,6 +1,6 @@
# Native prototypes # Native prototypes
The `"prototype"` property is widely used by the core of Javascript itself. All built-in constructor functions use it. The `"prototype"` property is widely used by the core of JavaScript itself. All built-in constructor functions use it.
We'll see how it is for plain objects first, and then for more complex ones. We'll see how it is for plain objects first, and then for more complex ones.
@ -123,7 +123,7 @@ During the process of development we may have ideas which new built-in methods w
Prototypes are global, so it's easy to get a conflict. If two libraries add a method `String.prototype.show`, then one of them overwrites the other one. Prototypes are global, so it's easy to get a conflict. If two libraries add a method `String.prototype.show`, then one of them overwrites the other one.
In modern programming, there is only one case when modifying native prototypes is approved. That's polyfills. In other words, if there's a method in Javascript specification that is not yet supported by our Javascript engine (or any of those that we want to support), then may implement it manually and populate the built-in prototype with it. In modern programming, there is only one case when modifying native prototypes is approved. That's polyfills. In other words, if there's a method in JavaScript specification that is not yet supported by our JavaScript engine (or any of those that we want to support), then may implement it manually and populate the built-in prototype with it.
For instance: For instance:
@ -177,4 +177,4 @@ That's more efficient, because evades creation of an extra array object `[]`. Fr
- The methods are stored in the prototype (`Array.prototype`, `Object.prototype`, `Date.prototype` etc). - The methods are stored in the prototype (`Array.prototype`, `Object.prototype`, `Date.prototype` etc).
- The object itself stores only the data (array items, object properties, the date). - The object itself stores only the data (array items, object properties, the date).
- Primitives also store methods in prototypes of wrapper objects: `Number.prototype`, `String.prototype`, `Boolean.prototype`. There are no wrapper objects only for `undefined` and `null`. - Primitives also store methods in prototypes of wrapper objects: `Number.prototype`, `String.prototype`, `Boolean.prototype`. There are no wrapper objects only for `undefined` and `null`.
- Built-in prototypes can be modified or populated with new methods. But it's not recommended to change them. Probably the only allowable cause is when we add-in a new standard, but not yet supported by the engine Javascript method. - Built-in prototypes can be modified or populated with new methods. But it's not recommended to change them. Probably the only allowable cause is when we add-in a new standard, but not yet supported by the engine JavaScript method.

View file

@ -51,7 +51,7 @@ That's for historical reasons.
And now we have all these ways at our disposal. And now we have all these ways at our disposal.
But please note: for most practical tasks, prototype chains are fixed: `rabbit` inherits from `animal`, and that is not going to change. And Javascript engines are highly optimized to that. Changing a prototype "on-the-fly" with `Object.setPrototypeOf` or `obj.__proto__=` is a very slow operation. But it is possible. But please note: for most practical tasks, prototype chains are fixed: `rabbit` inherits from `animal`, and that is not going to change. And JavaScript engines are highly optimized to that. Changing a prototype "on-the-fly" with `Object.setPrototypeOf` or `obj.__proto__=` is a very slow operation. But it is possible.
## "Very plain" objects ## "Very plain" objects
@ -74,7 +74,7 @@ Here if the user types in `__proto__`, the assignment is ignored! That's because
We did not intend to implement such behavior, right? So that's a bug. Here the consequences are not terrible. But in more complex cases the prototype may indeed be changed, so the execution may go wrong in totally unexpected ways. We did not intend to implement such behavior, right? So that's a bug. Here the consequences are not terrible. But in more complex cases the prototype may indeed be changed, so the execution may go wrong in totally unexpected ways.
What's worst -- usually developers do not think about such possibility at all. That makes such bugs hard to notice and even turn them into vulnerabilities, especially when Javascript is used on server-side. What's worst -- usually developers do not think about such possibility at all. That makes such bugs hard to notice and even turn them into vulnerabilities, especially when JavaScript is used on server-side.
Such thing happens only with `__proto__`. All other properties are "assignable" normally. Such thing happens only with `__proto__`. All other properties are "assignable" normally.

View file

@ -9,7 +9,7 @@ There's a special syntax construct and a keyword `class` in JavaScript. But befo
In JavaScript there are several well-known programming patterns to make classes even without using the `class` keyword. And here we'll talk about them first. In JavaScript there are several well-known programming patterns to make classes even without using the `class` keyword. And here we'll talk about them first.
The `class` construct will be described in the next chapter, but in Javascript it's a "syntax sugar" and an extension of one of the patterns that we'll study here. The `class` construct will be described in the next chapter, but in JavaScript it's a "syntax sugar" and an extension of one of the patterns that we'll study here.
[cut] [cut]
@ -108,7 +108,7 @@ We already can see benefits over the functional pattern:
So the prototypal pattern is more memory-efficient. So the prototypal pattern is more memory-efficient.
...But not only that. Prototypes allow us to setup the inheritance, precisely the same way as built-in Javascript constructors do. Functional pattern allows to wrap a function into another function, and kind-of emulate inheritance this way, but that's far less effective, so here we won't go into details to save our time. ...But not only that. Prototypes allow us to setup the inheritance, precisely the same way as built-in JavaScript constructors do. Functional pattern allows to wrap a function into another function, and kind-of emulate inheritance this way, but that's far less effective, so here we won't go into details to save our time.
## Prototype-based inheritance for classes ## Prototype-based inheritance for classes
@ -200,7 +200,7 @@ Here's what the code does:
## Summary ## Summary
The term "class" comes from the object-oriented programming. In Javascript it usually means the functional class pattern or the prototypal pattern. The prototypal pattern is more powerful and memory-efficient, so it's recommended to stick to it. The term "class" comes from the object-oriented programming. In JavaScript it usually means the functional class pattern or the prototypal pattern. The prototypal pattern is more powerful and memory-efficient, so it's recommended to stick to it.
According to the prototypal pattern: According to the prototypal pattern:
1. Methods are stored in `Class.prototype`. 1. Methods are stored in `Class.prototype`.

View file

@ -90,7 +90,7 @@ User(); // Error: Class constructor User cannot be invoked without 'new'
```smart header="Outputting a class" ```smart header="Outputting a class"
If we output it like `alert(User)`, some engines show `"class User..."`, while others show `"function User..."`. If we output it like `alert(User)`, some engines show `"class User..."`, while others show `"function User..."`.
Please don't be confused: the string representation may vary, but that's still a function, there is no separate "class" entity in Javascript language. Please don't be confused: the string representation may vary, but that's still a function, there is no separate "class" entity in JavaScript language.
``` ```
```smart header="Class methods are non-enumerable" ```smart header="Class methods are non-enumerable"

View file

@ -267,7 +267,7 @@ Let's get a little deeper under the hood of `super`. We'll see some interesting
First to say, from all that we've learned till now, it's impossible for `super` to work. First to say, from all that we've learned till now, it's impossible for `super` to work.
Yeah, indeed, let's ask ourselves, how it could technically work? When an object method runs, it gets the current object as `this`. If we call `super.method()` then, how to retrieve that method? In other words, we need to take the `method` from the parent prototype of the current object. How, technically, we (or a Javascript engine) can do it? Yeah, indeed, let's ask ourselves, how it could technically work? When an object method runs, it gets the current object as `this`. If we call `super.method()` then, how to retrieve that method? In other words, we need to take the `method` from the parent prototype of the current object. How, technically, we (or a JavaScript engine) can do it?
Maybe we can get it `[[Prototype]]` of `this`, as `this.__proto__.method`? Unfortunately, that won't work. Maybe we can get it `[[Prototype]]` of `this`, as `this.__proto__.method`? Unfortunately, that won't work.

View file

@ -12,7 +12,7 @@ In other words, a *mixin* is a class that implements a certain behavior. But we
## A mixin example ## A mixin example
The simplest way to make a mixin in Javascript -- is to make an object with useful methods, that we can just copy into the prototype. The simplest way to make a mixin in JavaScript -- is to make an object with useful methods, that we can just copy into the prototype.
For instance here the mixin `sayHiMixin` is used to add some "speech" for `User`: For instance here the mixin `sayHiMixin` is used to add some "speech" for `User`:
@ -192,7 +192,7 @@ And the `eventMixin` can add such behavior to as many classes as we'd like, with
*Mixin* -- is a generic object-oriented programming term: a class that contains methods for other classes. *Mixin* -- is a generic object-oriented programming term: a class that contains methods for other classes.
In Javascript that can be implemented as copying them into the prototype. In JavaScript that can be implemented as copying them into the prototype.
We can use mixins as a way to augment a class by multiple behaviors like event-handling that we overlooked above. We can use mixins as a way to augment a class by multiple behaviors like event-handling that we overlooked above.

View file

@ -79,7 +79,7 @@ Let's see more examples.
````warn header="`try..catch` only works for runtime errors" ````warn header="`try..catch` only works for runtime errors"
For `try..catch` to work, the code must be runnable. In other words, it should be valid Javascript. For `try..catch` to work, the code must be runnable. In other words, it should be valid JavaScript.
It won't work if the code is syntactically wrong, for instance it has unmatched figure brackets: It won't work if the code is syntactically wrong, for instance it has unmatched figure brackets:
@ -91,7 +91,7 @@ try {
} }
``` ```
The Javascript engine first reads the code, and then runs it. The errors that occur on the reading phrase are called "parse-time" errors and are unrecoverable (from inside that code). That's because the engine can't understand the code. The JavaScript engine first reads the code, and then runs it. The errors that occur on the reading phrase are called "parse-time" errors and are unrecoverable (from inside that code). That's because the engine can't understand the code.
So, `try..catch` can only handle errors that occur in the valid code. Such errors are called "runtime errors" or, sometimes, "exceptions". So, `try..catch` can only handle errors that occur in the valid code. Such errors are called "runtime errors" or, sometimes, "exceptions".
```` ````
@ -126,7 +126,7 @@ setTimeout(function() {
## Error object ## Error object
When an error occurs, Javascript generates an object containing the details about it. The object is then passed as an argument to `catch`: When an error occurs, JavaScript generates an object containing the details about it. The object is then passed as an argument to `catch`:
```js ```js
try { try {
@ -259,7 +259,7 @@ throw <error object>
Technically, we can use anything as an error object. That may be even a primitive, like a number or a string, but it's better to use objects, preferrably with `name` and `message` properties (to stay somewhat compatible with built-in errors). Technically, we can use anything as an error object. That may be even a primitive, like a number or a string, but it's better to use objects, preferrably with `name` and `message` properties (to stay somewhat compatible with built-in errors).
Javascript has many built-in constructors for standard errors: `Error`, `SyntaxError`, `ReferenceError`, `TypeError` and others. We can use them to create error objects as well. JavaScript has many built-in constructors for standard errors: `Error`, `SyntaxError`, `ReferenceError`, `TypeError` and others. We can use them to create error objects as well.
Their syntax is: Their syntax is:
@ -321,7 +321,7 @@ try {
} }
``` ```
In the line `(*)` the `throw` operator generates `SyntaxError` with the given `message`, the same way as Javascript would generate itself. The execution of `try` immediately stops and the control flow jumps into `catch`. In the line `(*)` the `throw` operator generates `SyntaxError` with the given `message`, the same way as JavaScript would generate itself. The execution of `try` immediately stops and the control flow jumps into `catch`.
Now `catch` became a single place for all error handling: both for `JSON.parse` and other cases. Now `catch` became a single place for all error handling: both for `JSON.parse` and other cases.
@ -572,7 +572,7 @@ In the code above, an error inside `try` always falls out, because there's no `c
## Global catch ## Global catch
```warn header="Environment-specific" ```warn header="Environment-specific"
The information from this section is not a part of the core Javascript. The information from this section is not a part of the core JavaScript.
``` ```
Let's imagine we've got a fatal error outside of `try..catch`, and the script died. Like a programming error or something else terrible. Let's imagine we've got a fatal error outside of `try..catch`, and the script died. Like a programming error or something else terrible.

View file

@ -4,7 +4,7 @@ When we develop something, we often need our own error classes to reflect specif
Our errors should inherit from basic `Error` class and support basic error properties like `message`, `name` and, preferably, `stack`. But they also may have other properties of their own, e.g. `HttpError` objects may have `statusCode` property with a value like `404` or `403` or `500`. Our errors should inherit from basic `Error` class and support basic error properties like `message`, `name` and, preferably, `stack`. But they also may have other properties of their own, e.g. `HttpError` objects may have `statusCode` property with a value like `404` or `403` or `500`.
Technically, we can use standalone classes for our errors, because Javascript allows to use `throw` with any argument. But if we inherit from `Error`, then it becomes possible to use `obj instanceof Error` check to identify error objects. So it's better to inherit from it. Technically, we can use standalone classes for our errors, because JavaScript allows to use `throw` with any argument. But if we inherit from `Error`, then it becomes possible to use `obj instanceof Error` check to identify error objects. So it's better to inherit from it.
As we build our application, our own errors naturally form a hierarchy, for instance `HttpTimeoutError` may inherit from `HttpError`. Examples will follow soon. As we build our application, our own errors naturally form a hierarchy, for instance `HttpTimeoutError` may inherit from `HttpError`. Examples will follow soon.
@ -24,7 +24,7 @@ That's called "data validation" -- we need to ensure that the data has all the n
Our `ValidationError` should inherit from the built-in `Error` class. To better understand what we're extending -- here's the approximate code for built-in [Error class](https://tc39.github.io/ecma262/#sec-error-message): Our `ValidationError` should inherit from the built-in `Error` class. To better understand what we're extending -- here's the approximate code for built-in [Error class](https://tc39.github.io/ecma262/#sec-error-message):
```js ```js
// "pseudocode" for the built-in Error class defined by Javascript itself // "pseudocode" for the built-in Error class defined by JavaScript itself
class Error { class Error {
constructor(message) { constructor(message) {
this.message = message; this.message = message;
@ -61,7 +61,7 @@ try {
Please note: Please note:
1. In the line `(1)` we call the parent constructor to set the message. Javascript requires us to call `super` in the child constructor. 1. In the line `(1)` we call the parent constructor to set the message. JavaScript requires us to call `super` in the child constructor.
2. The parent constructor sets the `name` property to `"Error"`, so here we reset it to the right value. 2. The parent constructor sets the `name` property to `"Error"`, so here we reset it to the right value.
Let's try to use it in `readUser(json)`: Let's try to use it in `readUser(json)`:

View file

@ -2,9 +2,9 @@
Regular expressions is a powerful way of searching and replacing inside a string. Regular expressions is a powerful way of searching and replacing inside a string.
In Javascript regular expressions are implemented using objects of a built-in `RegExp` class and integrated with strings. In JavaScript regular expressions are implemented using objects of a built-in `RegExp` class and integrated with strings.
Please note that regular expressions vary between programming languages. In this tutorial we concentrate on Javascript. Of course there's a lot in common, but they are a somewhat different in Perl, Ruby, PHP etc. Please note that regular expressions vary between programming languages. In this tutorial we concentrate on JavaScript. Of course there's a lot in common, but they are a somewhat different in Perl, Ruby, PHP etc.
[cut] [cut]
@ -27,7 +27,7 @@ regexp = /pattern/; // no flags флагов
regexp = /pattern/gmi; // with flags g,m and i (to be covered soon) regexp = /pattern/gmi; // with flags g,m and i (to be covered soon)
``` ```
Slashes `"/"` tell Javascript that we are creating a regular expression. They play the same role as quotes for strings. Slashes `"/"` tell JavaScript that we are creating a regular expression. They play the same role as quotes for strings.
## Usage ## Usage
@ -36,7 +36,7 @@ To search inside a string, we can use method [search](mdn:js/String/search).
Here's an example: Here's an example:
```js run ```js run
let str = "I love Javascript!"; // will search here let str = "I love JavaScript!"; // will search here
let regexp = /love/; let regexp = /love/;
alert( str.search(regexp) ); // 2 alert( str.search(regexp) ); // 2
@ -47,7 +47,7 @@ The `str.search` method looks for the pattern `pattern:/love/` and returns the p
The code above is the same as: The code above is the same as:
```js run ```js run
let str = "I love Javascript!"; // will search here let str = "I love JavaScript!"; // will search here
let substr = 'love'; let substr = 'love';
alert( str.search(substr) ); // 2 alert( str.search(substr) ); // 2
@ -78,7 +78,7 @@ let search = prompt("What you want to search?", "love");
let regexp = new RegExp(search); let regexp = new RegExp(search);
// find whatever the user wants // find whatever the user wants
alert( "I love Javascript".search(regexp)); alert( "I love JavaScript".search(regexp));
``` ```
```` ````
@ -87,7 +87,7 @@ alert( "I love Javascript".search(regexp));
Regular expressions may have flags that affect the search. Regular expressions may have flags that affect the search.
There are only 5 of them in Javascript: There are only 5 of them in JavaScript:
`i` `i`
: With this flag the search is case-insensitive: no difference between `А` and `а` (see the example below). : With this flag the search is case-insensitive: no difference between `А` and `а` (see the example below).
@ -113,7 +113,7 @@ The simplest flag is `i`.
An example with it: An example with it:
```js run ```js run
let str = "I love Javascript!"; let str = "I love JavaScript!";
alert( str.search(/LOVE/) ); // -1 (not found) alert( str.search(/LOVE/) ); // -1 (not found)
alert( str.search(/LOVE/i) ); // 2 alert( str.search(/LOVE/i) ); // 2

View file

@ -53,17 +53,17 @@ The array may have more than one element.
For instance: For instance:
```js run ```js run
lar str = "Javascript is a programming language"; lar str = "JavaScript is a programming language";
let result = str.match( *!*/JAVA(SCRIPT)/i*/!* ); let result = str.match( *!*/JAVA(SCRIPT)/i*/!* );
alert( result[0] ); // Javascript (the whole match) alert( result[0] ); // JavaScript (the whole match)
alert( result[1] ); // script (the part of the match that corresponds to the brackets) alert( result[1] ); // script (the part of the match that corresponds to the brackets)
alert( result.index ); // 0 alert( result.index ); // 0
alert( result.input ); // Javascript is a programming language alert( result.input ); // JavaScript is a programming language
``` ```
Due to the `i` flag the search is case-insensitive, so it finds `match:Javascript`. The part of the match that corresponds to `pattern:SCRIPT` becomes a separate array item. Due to the `i` flag the search is case-insensitive, so it finds `match:JavaScript`. The part of the match that corresponds to `pattern:SCRIPT` becomes a separate array item.
We'll be back to brackets later in the chapter [todo]. They are great for search-and-replace. We'll be back to brackets later in the chapter [todo]. They are great for search-and-replace.
@ -243,7 +243,7 @@ The `test` method looks for any match and returns `true/false` whether he found
So it's basically the same as `str.search(reg) != -1`, for instance: So it's basically the same as `str.search(reg) != -1`, for instance:
```js run ```js run
let str = "I love Javascript"; let str = "I love JavaScript";
// these two tests do the same // these two tests do the same
alert( *!*/love/i*/!*.test(str) ); // true alert( *!*/love/i*/!*.test(str) ); // true
@ -281,7 +281,7 @@ But the `g` flag allows to get all matches with their positions and bracket grou
Here's the example how subsequent `regexp.exec` calls return matches one by one: Here's the example how subsequent `regexp.exec` calls return matches one by one:
```js run ```js run
let str = "A lot about Javascript at https://javascript.info"; let str = "A lot about JavaScript at https://javascript.info";
let regexp = /JAVA(SCRIPT)/ig; let regexp = /JAVA(SCRIPT)/ig;
@ -289,7 +289,7 @@ let regexp = /JAVA(SCRIPT)/ig;
// Look for the first match // Look for the first match
*/!* */!*
let matchOne = regexp.exec(str); let matchOne = regexp.exec(str);
alert( matchOne[0] ); // Javascript alert( matchOne[0] ); // JavaScript
alert( matchOne[1] ); // script alert( matchOne[1] ); // script
alert( matchOne.index ); // 12 (the position of the match) alert( matchOne.index ); // 12 (the position of the match)
alert( matchOne.input ); // the same as str alert( matchOne.input ); // the same as str
@ -321,7 +321,7 @@ As we can see, each `regexp.exec` call returns the match in a "full format": as
The main use case for `regexp.exec` is to find all matches in a loop: The main use case for `regexp.exec` is to find all matches in a loop:
```js run ```js run
let str = 'A lot about Javascript at https://javascript.info'; let str = 'A lot about JavaScript at https://javascript.info';
let regexp = /javascript/ig; let regexp = /javascript/ig;
@ -338,7 +338,7 @@ The loop continues until `regexp.exec` returns `null` that means "no more matche
We can force `regexp.exec` to start searching from the given position by setting `lastIndex` manually: We can force `regexp.exec` to start searching from the given position by setting `lastIndex` manually:
```js run ```js run
let str = 'A lot about Javascript at https://javascript.info'; let str = 'A lot about JavaScript at https://javascript.info';
let regexp = /javascript/ig; let regexp = /javascript/ig;
regexp.lastIndex = 30; regexp.lastIndex = 30;

View file

@ -74,11 +74,11 @@ The word boundary `pattern:\b` -- is a special character class.
It does not denote a character, but rather a boundary between characters. It does not denote a character, but rather a boundary between characters.
For instance, `pattern:\bJava\b` matches `match:Java` in the string `subject:Hello, Java!`, but not in the script `subject:Hello, Javascript!`. For instance, `pattern:\bJava\b` matches `match:Java` in the string `subject:Hello, Java!`, but not in the script `subject:Hello, JavaScript!`.
```js run ```js run
alert( "Hello, Java!".match(/\bJava\b/) ); // Java alert( "Hello, Java!".match(/\bJava\b/) ); // Java
alert( "Hello, Javascript!".match(/\bJava\b/) ); // null alert( "Hello, JavaScript!".match(/\bJava\b/) ); // null
``` ```
The boundary has "zero width" in a sense that usually a character class means a character in the result (like a wordly or a digit), but not in this case. The boundary has "zero width" in a sense that usually a character class means a character in the result (like a wordly or a digit), but not in this case.
@ -108,7 +108,7 @@ alert( "Hello, Java!".match(/\Java!\b/) ); // null
Once again let's note that `pattern:\b` makes the searching engine to test for the boundary, so that `pattern:Java\b` finds `match:Java` only when followed by a word boundary, but it does not add a letter to the result. Once again let's note that `pattern:\b` makes the searching engine to test for the boundary, so that `pattern:Java\b` finds `match:Java` only when followed by a word boundary, but it does not add a letter to the result.
Usually we use `\b` to find standalone English words. So that if we want `"Java"` language then `pattern:\bJava\b` finds exactly a standalone word and ignores it when it's a part of `"Javascript"`. Usually we use `\b` to find standalone English words. So that if we want `"Java"` language then `pattern:\bJava\b` finds exactly a standalone word and ignores it when it's a part of `"JavaScript"`.
Another example: a regexp `pattern:\b\d\d\b` looks for standalone two-digit numbers. In other words, it requires that before and after `pattern:\d\d` must be a symbol different from `\w` (or beginning/end of the string). Another example: a regexp `pattern:\b\d\d\b` looks for standalone two-digit numbers. In other words, it requires that before and after `pattern:\d\d` must be a symbol different from `\w` (or beginning/end of the string).

View file

@ -35,7 +35,7 @@ alert( "1\2".match(/\\/) ); // '\'
## A slash ## A slash
The slash symbol `'/'` is not a special character, but in Javascript it is used to open and close the regexp: `pattern:/...pattern.../`, so we should escape it too. The slash symbol `'/'` is not a special character, but in JavaScript it is used to open and close the regexp: `pattern:/...pattern.../`, so we should escape it too.
Here's what a search for a slash `'/'` looks like: Here's what a search for a slash `'/'` looks like:

View file

@ -23,7 +23,7 @@ So characters like `a` and `≈` occupy 2 bytes, and those rare ones take 4.
The unicode is made in such a way that the 4-byte characters only have a meaning as a whole. The unicode is made in such a way that the 4-byte characters only have a meaning as a whole.
In the past Javascript did not know about that, and many string methods still have problems. For instance, `length` thinks that here are two characters: In the past JavaScript did not know about that, and many string methods still have problems. For instance, `length` thinks that here are two characters:
```js run ```js run
alert('😄'.length); // 2 alert('😄'.length); // 2

View file

@ -114,7 +114,7 @@ Regexp "open HTML-tag without attributes" (improved): `pattern:/<[a-z][a-z0-9]*>
``` ```
Regexp "opening or closing HTML-tag without attributes": `pattern:/<\/?[a-z][a-z0-9]*>/i` Regexp "opening or closing HTML-tag without attributes": `pattern:/<\/?[a-z][a-z0-9]*>/i`
: We added an optional slash `pattern:/?` before the tag. Had to escape it with a backslash, otherwise Javascript would think it is the pattern end. : We added an optional slash `pattern:/?` before the tag. Had to escape it with a backslash, otherwise JavaScript would think it is the pattern end.
```js run ```js run
alert( "<h1>Hi!</h1>".match(/<\/?[a-z][a-z0-9]*>/gi) ); // <h1>, </h1> alert( "<h1>Hi!</h1>".match(/<\/?[a-z][a-z0-9]*>/gi) ); // <h1>, </h1>

View file

@ -1,14 +1,14 @@
# Browser environment, specs # Browser environment, specs
The Javascript language was initially created for web browsers. But as of now, it evolved and became a language with many uses and platforms. The JavaScript language was initially created for web browsers. But as of now, it evolved and became a language with many uses and platforms.
A platform may be either a browser or a web-server or a washing machine or another *host*. Each of them provides platform-specific functionality. The Javascript standard called that a *host environment*. A platform may be either a browser or a web-server or a washing machine or another *host*. Each of them provides platform-specific functionality. The JavaScript standard called that a *host environment*.
That host environment provides additional objects and functions to the language core. Web browsers provide means to control web pages. Node.JS provides server-side features. There are other host environments too. That host environment provides additional objects and functions to the language core. Web browsers provide means to control web pages. Node.JS provides server-side features. There are other host environments too.
[cut] [cut]
Here's a bird-eye view of what we have when Javascript runs in a web-browser: Here's a bird-eye view of what we have when JavaScript runs in a web-browser:
![](windowObjects.png) ![](windowObjects.png)

View file

@ -8,7 +8,7 @@ libs:
The essential part of HTML is tags, right? The essential part of HTML is tags, right?
According to Document Object Model (DOM), every HTML-tag is an object. Nested tags are called "children". And the text inside it is an object as well. All these objects are accessible using Javascript, we'll see that now. According to Document Object Model (DOM), every HTML-tag is an object. Nested tags are called "children". And the text inside it is an object as well. All these objects are accessible using JavaScript, we'll see that now.
## An example of DOM ## An example of DOM
@ -48,7 +48,7 @@ For instance, the `<title>` tag has the text `"About elks"`.
Please note the special characters in text nodes: Please note the special characters in text nodes:
- a newline: `↵` (in Javascript known as `\n`) - a newline: `↵` (in JavaScript known as `\n`)
- a space: `␣` - a space: `␣`
Spaces and newlines -- are totally valid characters, they form text nodes and become a part of the DOM. So, for instance, in the example above the `<head>` tag contains come spaces before `<title>`, and that text becomes a `#text` node (it contains a newline and some spaces only). Spaces and newlines -- are totally valid characters, they form text nodes and become a part of the DOM. So, for instance, in the example above the `<head>` tag contains come spaces before `<title>`, and that text becomes a `#text` node (it contains a newline and some spaces only).
@ -221,7 +221,7 @@ The best way to study them is to click around. Most values are in-place editable
## Interaction with console ## Interaction with console
As we explore the DOM, we also may want to apply Javascript to it. Like: get a node and run some code to modify it, to see how it looks. Here are few tips to travel between the Elements tab and the console. As we explore the DOM, we also may want to apply JavaScript to it. Like: get a node and run some code to modify it, to see how it looks. Here are few tips to travel between the Elements tab and the console.
- Select the first `<li>` in the Elements tab. - Select the first `<li>` in the Elements tab.
- Press `key:Esc` -- it will open console right below the Elements tab. - Press `key:Esc` -- it will open console right below the Elements tab.
@ -238,7 +238,7 @@ Or we can just output it in the console and explore "at-place", like `document.b
![](domconsole1.png) ![](domconsole1.png)
That's for debugging purposes of course. From the next chapter on we'll access and modify DOM using Javascript. That's for debugging purposes of course. From the next chapter on we'll access and modify DOM using JavaScript.
The browser developer tools are a great help in development: we can explore DOM, try things and see what goes wrong. The browser developer tools are a great help in development: we can explore DOM, try things and see what goes wrong.

View file

@ -63,10 +63,10 @@ alert( document.body instanceof Node ); // true
alert( document.body instanceof EventTarget ); // true alert( document.body instanceof EventTarget ); // true
``` ```
As we can see, DOM nodes are regular Javascript objects. They use prototype-based classes for inheritance. That's easy to see by outputting an element with `console.dir(elem)`. There you can see `HTMLElement.prototype`, `Element.prototype` and so on. As we can see, DOM nodes are regular JavaScript objects. They use prototype-based classes for inheritance. That's easy to see by outputting an element with `console.dir(elem)`. There you can see `HTMLElement.prototype`, `Element.prototype` and so on.
```smart header="`console.dir(elem)` versus `console.log(elem)`" ```smart header="`console.dir(elem)` versus `console.log(elem)`"
Most browsers support two commands in their developer tools: `console.log` and `console.dir`. They output their arguments to the console. For Javascript objects these commands usually do the same. Most browsers support two commands in their developer tools: `console.log` and `console.dir`. They output their arguments to the console. For JavaScript objects these commands usually do the same.
But for DOM elements they are different: But for DOM elements they are different:
@ -77,7 +77,7 @@ Try it on `document.body`.
``` ```
````smart header="IDL in the spec" ````smart header="IDL in the spec"
In the specification classes are described using not Javascript, but a special [Interface description language](https://en.wikipedia.org/wiki/Interface_description_language) (IDL), that is usually easy to understand. In the specification classes are described using not JavaScript, but a special [Interface description language](https://en.wikipedia.org/wiki/Interface_description_language) (IDL), that is usually easy to understand.
The most important difference is that all properties are given with their types. For instance, `DOMString`, `boolean` and so on. The most important difference is that all properties are given with their types. For instance, `DOMString`, `boolean` and so on.
@ -353,7 +353,7 @@ For text nodes we can imagine a reason to read or modify them, but why comments?
<!-- /if --> <!-- /if -->
``` ```
...Then Javascript can read it and process embedded instructions. ...Then JavaScript can read it and process embedded instructions.
## textContent: pure text ## textContent: pure text
@ -407,14 +407,14 @@ In most cases, we expect the text from a user, and want to treat it as text. We
The "hidden" attribute and the DOM property specifies whether the element is visible or not. The "hidden" attribute and the DOM property specifies whether the element is visible or not.
We can use it in HTML or assign using Javascript, like this: We can use it in HTML or assign using JavaScript, like this:
```html run height="80" ```html run height="80"
<div>Both divs below are hidden</div> <div>Both divs below are hidden</div>
<div hidden>With the attribute "hidden"</div> <div hidden>With the attribute "hidden"</div>
<div id="elem">Javascript assigned the property "hidden"</div> <div id="elem">JavaScript assigned the property "hidden"</div>
<script> <script>
elem.hidden = true; elem.hidden = true;

View file

@ -12,7 +12,7 @@ But the mapping is not one-to-one! In this chapter we'll see that DOM properties
We've already seen built-in DOM properties. There's a lot. But technically no one limits us, and if it's not enough -- we can add own own. We've already seen built-in DOM properties. There's a lot. But technically no one limits us, and if it's not enough -- we can add own own.
DOM nodes are regular Javascript objects. We can alter them. DOM nodes are regular JavaScript objects. We can alter them.
For instance, let's create a new property in `document.body`: For instance, let's create a new property in `document.body`:
@ -46,7 +46,7 @@ document.documentElement.sayHi(); // Hello, I'm HTML
document.body.sayHi(); // Hello, I'm BODY document.body.sayHi(); // Hello, I'm BODY
``` ```
So, DOM properties and methods behave just like those of regular Javascript objects: So, DOM properties and methods behave just like those of regular JavaScript objects:
- They can have any value. - They can have any value.
- They are case-sensitive (write `elem.nodeType`, not `elem.NoDeTyPe`). - They are case-sensitive (write `elem.nodeType`, not `elem.NoDeTyPe`).
@ -242,7 +242,7 @@ If we need the value of `href` or anything else exactly as written in the HTML,
When writing HTML, we use a lot of standard attributes. But what about non-standard, custom ones? First, let's see whether they are useful or not? What for? When writing HTML, we use a lot of standard attributes. But what about non-standard, custom ones? First, let's see whether they are useful or not? What for?
Sometimes non-standard attributes are used to pass custom data from HTML to Javascript, or "mark" elements. Sometimes non-standard attributes are used to pass custom data from HTML to JavaScript, or "mark" elements.
Like this: Like this:

View file

@ -32,7 +32,7 @@ Here's how it will look:
*/!* */!*
``` ```
That was an HTML example. Now let's create the same `div` with Javascript (assuming that the styles are still in the HTML or an external CSS). That was an HTML example. Now let's create the same `div` with JavaScript (assuming that the styles are still in the HTML or an external CSS).
## Creating an element ## Creating an element
@ -410,7 +410,7 @@ The syntax:
<p>The end</p> <p>The end</p>
``` ```
The call to `document.write(html)` writes the `html` into page "right here and now". The `html` string can be dynamically generated, so it's kind of flexible. We can use Javascript to create a full-fledged webpage and write it. The call to `document.write(html)` writes the `html` into page "right here and now". The `html` string can be dynamically generated, so it's kind of flexible. We can use JavaScript to create a full-fledged webpage and write it.
The method comes from times when there were no DOM, no standards... Really old times. It still lives, because there are scripts using it. The method comes from times when there were no DOM, no standards... Really old times. It still lives, because there are scripts using it.

View file

@ -1,6 +1,6 @@
# Styles and classes # Styles and classes
Before we get to Javascript ways of dealing with styles and classes -- here's an important rule. Hopefully it's obvious enough, but we still have to mention it. Before we get to JavaScript ways of dealing with styles and classes -- here's an important rule. Hopefully it's obvious enough, but we still have to mention it.
There are generally two ways to style an element: There are generally two ways to style an element:
@ -9,11 +9,11 @@ There are generally two ways to style an element:
[cut] [cut]
CSS is always the preferred way -- not only for HTML, but in Javascript as well. CSS is always the preferred way -- not only for HTML, but in JavaScript as well.
We should only manipulate the `style` property if classes "can't handle it". We should only manipulate the `style` property if classes "can't handle it".
For instance, `style` is acceptable if we calculate coordinates of an element dynamically and want to set them from Javascript, like this: For instance, `style` is acceptable if we calculate coordinates of an element dynamically and want to set them from JavaScript, like this:
```js ```js
let top = /* complex calculations */; let top = /* complex calculations */;
@ -28,7 +28,7 @@ For other cases, like making the text red, adding a background icon -- describe
Changing a class is one of the most often actions in scripts. Changing a class is one of the most often actions in scripts.
In the ancient time, there was a limitation in Javascript: a reserved word like `"class"` could not be an object property. That limitation does not exist now, but at that time it was impossible to have a `"class"` property, like `elem.class`. In the ancient time, there was a limitation in JavaScript: a reserved word like `"class"` could not be an object property. That limitation does not exist now, but at that time it was impossible to have a `"class"` property, like `elem.class`.
So for classes the similar-looking property `"className"` was introduced: the `elem.className` corresponds to the `"class"` attribute. So for classes the similar-looking property `"className"` was introduced: the `elem.className` corresponds to the `"class"` attribute.
@ -283,7 +283,7 @@ Visited links may be colored using `:visited` CSS pseudoclass.
But `getComputedStyle` does not give access to that color, because otherwise an arbitrary page could find out whether the user visited a link by creating it on the page and checking the styles. But `getComputedStyle` does not give access to that color, because otherwise an arbitrary page could find out whether the user visited a link by creating it on the page and checking the styles.
Javascript we may not see the styles applied by `:visited`. And also, there's a limitation in CSS that forbids to apply geometry-changing styles in `:visited`. That's to guarantee that there's no side way for an evil page to test if a link was visited and hence to break the privacy. JavaScript we may not see the styles applied by `:visited`. And also, there's a limitation in CSS that forbids to apply geometry-changing styles in `:visited`. That's to guarantee that there's no side way for an evil page to test if a link was visited and hence to break the privacy.
``` ```
## Summary ## Summary

View file

@ -1,8 +1,8 @@
# Element size and scrolling # Element size and scrolling
There are many Javascript properties that allow to read information about element width, height and other geometry features. There are many JavaScript properties that allow to read information about element width, height and other geometry features.
We often need them when moving or positioning elements in Javascript, to correctly calculate coordinates. We often need them when moving or positioning elements in JavaScript, to correctly calculate coordinates.
[cut] [cut]

View file

@ -1,3 +1,3 @@
# Document # Document
Here we'll learn to manipulate a web-page using Javascript. Here we'll learn to manipulate a web-page using JavaScript.

View file

@ -234,7 +234,7 @@ The numbers in square brackets denote the approximate time of when it happens. T
Page lifecycle events: Page lifecycle events:
- `DOMContentLoaded` event triggers on `document` when DOM is ready. We can apply Javascript to elements at this stage. - `DOMContentLoaded` event triggers on `document` when DOM is ready. We can apply JavaScript to elements at this stage.
- All scripts are executed except those that are external with `async` or `defer` - All scripts are executed except those that are external with `async` or `defer`
- Images and other resources may still continue loading. - Images and other resources may still continue loading.
- `load` event on `window` triggers when the page and all resources are loaded. We rarely use it, because there's usually no need to wait for so long. - `load` event on `window` triggers when the page and all resources are loaded. We rarely use it, because there's usually no need to wait for so long.

View file

@ -13,7 +13,7 @@ There's a `<select>`:
</select> </select>
``` ```
Use Javascript to: Use JavaScript to:
1. Show the value and the text of the selected option. 1. Show the value and the text of the selected option.
2. Add an option: `<option value="classic">Classic</option>`. 2. Add an option: `<option value="classic">Classic</option>`.

View file

@ -1,5 +1,5 @@
1. On click -- replace `innerHTML` of the cell by `<textarea>` with same sizes and no border. Can use Javascript or CSS to set the right size. 1. On click -- replace `innerHTML` of the cell by `<textarea>` with same sizes and no border. Can use JavaScript or CSS to set the right size.
2. Set `textarea.value` to `td.innerHTML`. 2. Set `textarea.value` to `td.innerHTML`.
3. Focus on the textarea. 3. Focus on the textarea.
4. Show buttons OK/CANCEL under the cell, handle clicks on them. 4. Show buttons OK/CANCEL under the cell, handle clicks on them.

View file

@ -50,7 +50,7 @@ Your email please: <input type="email" id="input">
</script> </script>
``` ```
Modern HTML allows to do many validations using input attributes: `required`, `pattern` and so on. And sometimes they are just what we need. Javascript can be used when we want more flexibility. Also we could automatically send the changed value on the server if it's correct. Modern HTML allows to do many validations using input attributes: `required`, `pattern` and so on. And sometimes they are just what we need. JavaScript can be used when we want more flexibility. Also we could automatically send the changed value on the server if it's correct.
## Methods focus/blur ## Methods focus/blur

View file

@ -1,6 +1,6 @@
# Form submission: event and method submit # Form submission: event and method submit
The `submit` event triggers when the form is submitted, it is usually used to validate the form before sending it to the server or to abort the submission and process it in Javascript. The `submit` event triggers when the form is submitted, it is usually used to validate the form before sending it to the server or to abort the submission and process it in JavaScript.
The method `form.submit()` allows to initiate form sending from JavaScript. We can use it to dynamically create and send our own forms to server. The method `form.submit()` allows to initiate form sending from JavaScript. We can use it to dynamically create and send our own forms to server.

View file

@ -13,7 +13,7 @@ window.open('http://javascript.info/')
## Popup blocking ## Popup blocking
Popups exist from really ancient times. The initial idea was to show another content without closing the main window. As of now, there are other ways to do that: Javascript is able to send requests for server, so popups are rarely used. But sometimes they are still handy. Popups exist from really ancient times. The initial idea was to show another content without closing the main window. As of now, there are other ways to do that: JavaScript is able to send requests for server, so popups are rarely used. But sometimes they are still handy.
In the past evil sites abused popups a lot. A bad page could open tons of popup windows with ads. So now most browsers try to block popups and protect the user. In the past evil sites abused popups a lot. A bad page could open tons of popup windows with ads. So now most browsers try to block popups and protect the user.
@ -41,13 +41,13 @@ The difference is that Firefox treats a timeout of 2000ms or less are acceptable
## Modern usage ## Modern usage
As of now, we have many methods to load and show data on-page with Javascript. But there are still situations when a popup works best. As of now, we have many methods to load and show data on-page with JavaScript. But there are still situations when a popup works best.
For instance, many shops use online chats for consulting people. A visitor clicks on the button, it runs `window.open` and opens the popup with the chat. For instance, many shops use online chats for consulting people. A visitor clicks on the button, it runs `window.open` and opens the popup with the chat.
Why a popup is good here, why not in-page? Why a popup is good here, why not in-page?
1. A popup is a separate window with its own independent Javascript environment. So a chat service doesn't need to integrate with scripts of the main shop site. 1. A popup is a separate window with its own independent JavaScript environment. So a chat service doesn't need to integrate with scripts of the main shop site.
2. A popup is very simple to attach to a site, little to no overhead. It's only a small button, without additional scripts. 2. A popup is very simple to attach to a site, little to no overhead. It's only a small button, without additional scripts.
3. A popup may persist even if the user left the page. For example, a consult advices the user to visit the page of a new "Super-Cooler" goodie. The user goes there in the main window without leaving the chat. 3. A popup may persist even if the user left the page. For example, a consult advices the user to visit the page of a new "Super-Cooler" goodie. The user goes there in the main window without leaving the chat.
@ -135,7 +135,7 @@ For windows with URLs from another sites, we are able to change the location by
## Accessing the opener window ## Accessing the opener window
A popup may access the "opener" window as well. A Javascript in it may use `window.opener` to access the window that opened it. It is `null` for all windows except popups. A popup may access the "opener" window as well. A JavaScript in it may use `window.opener` to access the window that opened it. It is `null` for all windows except popups.
So both the main window and the popup have a reference to each other. Thay may modify each other freely assuming that they come from the same origin. If that's not so, then there are still means to communicate, to be covered later [todo when]. So both the main window and the popup have a reference to each other. Thay may modify each other freely assuming that they come from the same origin. If that's not so, then there are still means to communicate, to be covered later [todo when].

View file

@ -227,7 +227,7 @@ In other words, an empty `"sandbox"` attribute puts the strictest limitations po
See [the manual](mdn:/HTML/Element/iframe) for more. See [the manual](mdn:/HTML/Element/iframe) for more.
The example below demonstrates a sandboxed iframe with some Javascript and a form. Neither one works: The example below demonstrates a sandboxed iframe with some JavaScript and a form. Neither one works:
[codetabs src="sandbox" height=140] [codetabs src="sandbox" height=140]

View file

@ -73,7 +73,7 @@ So that would look really odd to the user, and he will stop.
## Old-school defences (weak) ## Old-school defences (weak)
The oldest defence method is the piece of Javascript that forbids to open the page in a frame (so-called "framebusting"). The oldest defence method is the piece of JavaScript that forbids to open the page in a frame (so-called "framebusting").
Like this: Like this: