Skip to content

Sync with upstream @ 3a0b3f4e #205

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 26 commits into from
Jan 19, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
6b296c1
new.target is undefined not empty
sarscoder Jan 11, 2021
b9d5335
Merge pull request #2425 from sarscode/sarscode-constructor-new-target
iliakan Jan 11, 2021
afd41ea
each unit parts must be tested
lumosmind Jan 12, 2021
eb3b360
minor fixes
iliakan Jan 12, 2021
a27b7e2
"exception" vs "new feature" ?
joaquinelio Jan 12, 2021
73fd173
Update article.md
bilalbutt044 Jan 12, 2021
09f8ca8
individual test case for methods
lumosmind Jan 12, 2021
85fe7b8
no need to "js run"
lumosmind Jan 13, 2021
09ec05c
minor fixes
iliakan Jan 13, 2021
3c673ac
Merge pull request #2434 from lumosmind/patch-65
iliakan Jan 13, 2021
c7d3072
closes #2433
iliakan Jan 13, 2021
58e6456
minor fixes
iliakan Jan 13, 2021
003d602
Merge pull request #2432 from lumosmind/patch-62
iliakan Jan 13, 2021
9c1a0fd
Merge pull request #2431 from bilalbutt044/patch-1
iliakan Jan 13, 2021
f6d3e30
Merge pull request #2429 from lumosmind/patch-61
iliakan Jan 13, 2021
bc8b37b
minor fixes
iliakan Jan 13, 2021
4307531
Merge branch 'master' of github.com:javascript-tutorial/en.javascript…
iliakan Jan 13, 2021
15e6f2d
minor fixes
iliakan Jan 13, 2021
e95ca4b
typo
lumosmind Jan 13, 2021
9c082c8
minor fixes
iliakan Jan 13, 2021
99b2a09
Merge pull request #2437 from lumosmind/patch-68
iliakan Jan 13, 2021
8eb6f97
minor fixes
iliakan Jan 13, 2021
f797858
closes #2398
iliakan Jan 14, 2021
3a0b3f4
Merge pull request #2430 from joaquinelio/patch-1
iliakan Jan 16, 2021
2d2f340
merging all conflicts
iliakan Jan 18, 2021
82a94da
Resolve conflicts
odsantos Jan 18, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 1 addition & 5 deletions 1-js/01-getting-started/2-manuals-specifications/article.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,12 @@ E mais, se você está desenvolvendo para browsers, há outras especificações

## Manuais

- **MDN (Mozilla) JavaScript Reference** é um manual com exemplos e outras informações. É ótimo para um entendimento sobre funções, métodos da linguagem, etc.
- **MDN (Mozilla) JavaScript Reference** é um manual com exemplos e outras informações. É ótimo para um entendimento sobre funções da linguagem, métodos , etc.

Pode ser encontrado em <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference>.

Porém, às vezes é melhor fazer uma busca na internet. Apenas use "MDN [termo]" na busca, por exemplo: <https://google.com/search?q=MDN+parseInt> para procurar pela função `parseInt`.

- **MSDN** - Manual da Microsoft com muitas informações, incluindo JavaScript (frequentemente referido como JScript). Se precisar de algo específico para o Internet Explorer, é melhor ir por aqui: <http://msdn.microsoft.com/>.

Assim como para o manual da Mozilla, também podemos fazer uma busca na internet com frases do tipo "RegExp MSDN" ou "RegExp MSDN jscript".

## Tabelas de compatibilidade

JavaScript é uma linguagem em desenvolvimento, novas funcionalidades são adicionadas regularmente.
Expand Down
2 changes: 1 addition & 1 deletion 1-js/03-code-quality/02-coding-style/code-style.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 3 additions & 3 deletions 1-js/04-object-basics/03-garbage-collection/article.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ Simply put, "reachable" values are those that are accessible or usable somehow.

For instance:

- Local variables and parameters of the current function.
- Variables and parameters for other functions on the current chain of nested calls.
- The currently executing function, its local variables and parameters.
- Other functions on the current chain of nested calls, their local variables and parameters.
- Global variables.
- (there are some other, internal ones as well)

Expand Down Expand Up @@ -207,6 +207,6 @@ A general book "The Garbage Collection Handbook: The Art of Automatic Memory Man

If you are familiar with low-level programming, the more detailed information about V8 garbage collector is in the article [A tour of V8: Garbage Collection](http://jayconrod.com/posts/55/a-tour-of-v8-garbage-collection).

[V8 blog](http://v8project.blogspot.com/) also publishes articles about changes in memory management from time to time. Naturally, to learn the garbage collection, you'd better prepare by learning about V8 internals in general and read the blog of [Vyacheslav Egorov](http://mrale.ph) who worked as one of V8 engineers. I'm saying: "V8", because it is best covered with articles in the internet. For other engines, many approaches are similar, but garbage collection differs in many aspects.
[V8 blog](https://v8.dev/) also publishes articles about changes in memory management from time to time. Naturally, to learn the garbage collection, you'd better prepare by learning about V8 internals in general and read the blog of [Vyacheslav Egorov](http://mrale.ph) who worked as one of V8 engineers. I'm saying: "V8", because it is best covered with articles in the internet. For other engines, many approaches are similar, but garbage collection differs in many aspects.

In-depth knowledge of engines is good when you need low-level optimizations. It would be wise to plan that as the next step after you're familiar with the language.
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ describe("calculator", function() {
afterEach(function() {
prompt.restore();
});

it('the read get two values and saves them as object properties', function () {
assert.equal(calculator.a, 2);
assert.equal(calculator.b, 3);
});

it("the sum is 5", function() {
assert.equal(calculator.sum(), 5);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,31 @@

describe("calculator", function() {
let calculator;
before(function() {
sinon.stub(window, "prompt")

prompt.onCall(0).returns("2");
prompt.onCall(1).returns("3");

calculator = new Calculator();
calculator.read();
});

it("when 2 and 3 are entered, the sum is 5", function() {
assert.equal(calculator.sum(), 5);
});

it("when 2 and 3 are entered, the product is 6", function() {
assert.equal(calculator.mul(), 6);
});

after(function() {
prompt.restore();
let calculator;
before(function() {
sinon.stub(window, "prompt")

prompt.onCall(0).returns("2");
prompt.onCall(1).returns("3");

calculator = new Calculator();
calculator.read();
});

it("the read method asks for two values using prompt and remembers them in object properties", function() {
assert.equal(calculator.a, 2);
assert.equal(calculator.b, 3);
});

it("when 2 and 3 are entered, the sum is 5", function() {
assert.equal(calculator.sum(), 5);
});

it("when 2 and 3 are entered, the product is 6", function() {
assert.equal(calculator.mul(), 6);
});

after(function() {
prompt.restore();
});
});
});
10 changes: 7 additions & 3 deletions 1-js/04-object-basics/06-constructor-new/article.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,15 +83,15 @@ let user = new function() {
The constructor can't be called again, because it is not saved anywhere, just created and called. So this trick aims to encapsulate the code that constructs the single object, without future reuse.
````

## Dual-syntax constructors: new.target
## Constructor mode test: new.target

```smart header="Advanced stuff"
The syntax from this section is rarely used, skip it unless you want to know everything.
```

Inside a function, we can check whether it was called with `new` or without it, using a special `new.target` property.

It is empty for regular calls and equals the function if called with `new`:
It is undefined for regular calls and equals the function if called with `new`:

```js run
function User() {
Expand All @@ -109,7 +109,9 @@ new User(); // function User { ... }
*/!*
```

That can be used to allow both `new` and regular calls to work the same. That is, create the same object:
That can be used inside the function to know whether it was called with `new`, "in constructor mode", or without it, "in regular mode".

We can also make both `new` and regular calls to do the same, like this:

```js run
function User(name) {
Expand Down Expand Up @@ -210,6 +212,8 @@ john = {
*/
```

To create complex objects, there's a more advanced syntax, [classes](info:classes), that we'll cover later.

## Summary

- Constructor functions or, briefly, constructors, are regular functions, but there's a common agreement to name them with capital letter first.
Expand Down
14 changes: 6 additions & 8 deletions 1-js/04-object-basics/07-optional-chaining/article.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,12 +74,12 @@ That's why the optional chaining `?.` was added to the language. To solve this p

## Optional chaining

The optional chaining `?.` stops the evaluation if the part before `?.` is `undefined` or `null` and returns that part.
The optional chaining `?.` stops the evaluation if the value before `?.` is `undefined` or `null` and returns `undefined`.

**Further in this article, for brevity, we'll be saying that something "exists" if it's not `null` and not `undefined`.**

In other words, `value?.prop`:
- is the same as `value.prop` if `value` exists,
- works as `value.prop`, if `value` exists,
- otherwise (when `value` is `undefined/null`) it returns `undefined`.

Here's the safe way to access `user.address.street` using `?.`:
Expand All @@ -103,7 +103,7 @@ alert( user?.address.street ); // undefined

Please note: the `?.` syntax makes optional the value before it, but not any further.

E.g. in `user?.address.street.name` the `?.` allows `user` to be `null/undefined`, but it's all it does. Further properties are accessed in a regular way. If we want some of them to be optional, then we'll need to replace more `.` with `?.`.
E.g. in `user?.address.street.name` the `?.` allows `user` to safely be `null/undefined` (and returns `undefined` in that case), but that's only for `user`. Further properties are accessed in a regular way. If we want some of them to be optional, then we'll need to replace more `.` with `?.`.

```warn header="Don't overuse the optional chaining"
We should use `?.` only where it's ok that something doesn't exist.
Expand Down Expand Up @@ -173,18 +173,16 @@ Then `?.()` checks the left part: if the admin function exists, then it runs (th
The `?.[]` syntax also works, if we'd like to use brackets `[]` to access properties instead of dot `.`. Similar to previous cases, it allows to safely read a property from an object that may not exist.

```js run
let key = "firstName";

let user1 = {
firstName: "John"
};

let user2 = null; // Imagine, we couldn't authorize the user

let key = "firstName";
let user2 = null;

alert( user1?.[key] ); // John
alert( user2?.[key] ); // undefined

alert( user1?.[key]?.something?.not?.existing); // undefined
```

Also we can use `?.` with `delete`:
Expand Down
41 changes: 23 additions & 18 deletions 1-js/04-object-basics/08-symbol/article.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ A value of this type can be created using `Symbol()`:
let id = Symbol();
```

We can also give symbol a description (also called a symbol name), mostly useful for debugging purposes:
Upon creation, we can give symbol a description (also called a symbol name), mostly useful for debugging purposes:

```js
// id is a symbol with the description "id"
Expand Down Expand Up @@ -94,7 +94,7 @@ What's the benefit of using `Symbol("id")` over a string `"id"`?

As `user` objects belongs to another code, and that code also works with them, we shouldn't just add any fields to it. That's unsafe. But a symbol cannot be accessed accidentally, the third-party code probably won't even see it, so it's probably all right to do.

Imagine that another script wants to have its own "id" property inside `user`, for its own purposes. That may be another JavaScript library, so the scripts are completely unaware of each other.
Also, imagine that another script wants to have its own identifier inside `user`, for its own purposes. That may be another JavaScript library, so that the scripts are completely unaware of each other.

Then that script can create its own `Symbol("id")`, like this:

Expand All @@ -105,11 +105,11 @@ let id = Symbol("id");
user[id] = "Their id value";
```

There will be no conflict, because symbols are always different, even if they have the same name.
There will be no conflict between our and their identifiers, because symbols are always different, even if they have the same name.

Now note that if we used a string `"id"` instead of a symbol for the same purpose, then there *would* be a conflict:
...But if we used a string `"id"` instead of a symbol for the same purpose, then there *would* be a conflict:

```js run
```js
let user = { name: "John" };

// Our script uses "id" property
Expand All @@ -123,7 +123,7 @@ user.id = "Their id value"

### Symbols in an object literal

If we want to use a symbol in an object literal, we need square brackets.
If we want to use a symbol in an object literal `{...}`, we need square brackets around it.

Like this:

Expand Down Expand Up @@ -161,7 +161,7 @@ for (let key in user) alert(key); // name, age (no symbols)
alert( "Direct: " + user[id] );
```

That's a part of the general "hiding" concept. If another script or a library loops over our object, it won't unexpectedly access a symbolic property.
`Object.keys(user)` also ignores them. That's a part of the general "hiding symbolic properties" principle. If another script or a library loops over our object, it won't unexpectedly access a symbolic property.

In contrast, [Object.assign](mdn:js/Object/assign) copies both string and symbol properties:

Expand All @@ -180,13 +180,11 @@ There's no paradox here. That's by design. The idea is that when we clone an obj

## Global symbols

As we've seen, usually all symbols are different, even if they have the same names. But sometimes we want same-named symbols to be same entities.

For instance, different parts of our application want to access symbol `"id"` meaning exactly the same property.
As we've seen, usually all symbols are different, even if they have the same name. But sometimes we want same-named symbols to be same entities. For instance, different parts of our application want to access symbol `"id"` meaning exactly the same property.

To achieve that, there exists a *global symbol registry*. We can create symbols in it and access them later, and it guarantees that repeated accesses by the same name return exactly the same symbol.

In order to create or read a symbol in the registry, use `Symbol.for(key)`.
In order to read (create if absent) a symbol from the registry, use `Symbol.for(key)`.

That call checks the global registry, and if there's a symbol described as `key`, then returns it, otherwise creates a new symbol `Symbol(key)` and stores it in the registry by the given `key`.

Expand All @@ -196,7 +194,7 @@ For instance:
// read from the global registry
let id = Symbol.for("id"); // if the symbol did not exist, it is created

// read it again
// read it again (maybe from another part of the code)
let idAgain = Symbol.for("id");

// the same symbol
Expand All @@ -218,22 +216,29 @@ For global symbols, not only `Symbol.for(key)` returns a symbol by name, but the
For instance:

```js run
// get symbol by name
let sym = Symbol.for("name");
let sym2 = Symbol.for("id");

// get name from symbol
// get name by symbol
alert( Symbol.keyFor(sym) ); // name
alert( Symbol.keyFor(sym2) ); // id
```

The `Symbol.keyFor` internally uses the global symbol registry to look up the key for the symbol. So it doesn't work for non-global symbols. If the symbol is not global, it won't be able to find it and returns `undefined`.

That said, any symbols have `description` property.

For instance:

```js run
alert( Symbol.keyFor(Symbol.for("name")) ); // name, global symbol
let globalSymbol = Symbol.for("name");
let localSymbol = Symbol("name");

alert( Symbol.keyFor(globalSymbol) ); // name, global symbol
alert( Symbol.keyFor(localSymbol) ); // undefined, not global

alert( Symbol.keyFor(Symbol("name2")) ); // undefined, the argument isn't a global symbol
alert( localSymbol.description ); // name
```

## System symbols
Expand All @@ -256,9 +261,9 @@ Other symbols will also become familiar when we study the corresponding language

`Symbol` is a primitive type for unique identifiers.

Symbols are created with `Symbol()` call with an optional description.
Symbols are created with `Symbol()` call with an optional description (name).

Symbols are always different values, 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(key)` returns (creates if needed) a global symbol with `key` as the name. Multiple calls of `Symbol.for` return exactly the same symbol.
Symbols are always different values, 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(key)` returns (creates if needed) a global symbol with `key` as the name. Multiple calls of `Symbol.for` with the same `key` return exactly the same symbol.

Symbols have two main use cases:

Expand All @@ -269,4 +274,4 @@ Symbols have two main use cases:

2. There are many system symbols used by JavaScript which are accessible as `Symbol.*`. We can use them to alter some built-in behaviors. For instance, later in the tutorial we'll use `Symbol.iterator` for [iterables](info:iterable), `Symbol.toPrimitive` to setup [object-to-primitive conversion](info:object-toprimitive) and so on.

Technically, symbols are not 100% hidden. There is a built-in method [Object.getOwnPropertySymbols(obj)](mdn:js/Object/getOwnPropertySymbols) that allows us 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. But most libraries, built-in methods and syntax constructs adhere to a common agreement that they are. And the one who explicitly calls the aforementioned methods probably understands well what he's doing.
Technically, symbols are not 100% hidden. There is a built-in method [Object.getOwnPropertySymbols(obj)](mdn:js/Object/getOwnPropertySymbols) that allows us 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. But most libraries, built-in functions and syntax constructs don't use these methods.
22 changes: 15 additions & 7 deletions 1-js/05-data-types/02-number/article.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,29 @@ Imagine we need to write 1 billion. The obvious way is:
let billion = 1000000000;
```

But in real life, we usually avoid writing a long string of zeroes as it's easy to mistype. Also, we are lazy. We will usually write something like `"1bn"` for a billion or `"7.3bn"` for 7 billion 300 million. The same is true for most large numbers.
We also can use underscore `_` as the separator:

In JavaScript, we shorten a number by appending the letter `"e"` to the number and specifying the zeroes count:
```js
let billion = 1_000_000_000;
```

Here the underscore `_` plays the role of the "syntactic sugar", it makes the number more readable. The JavaScript engine simply ignores `_` between digits, so it's exactly the same one billion as above.

In real life though, we try to avoid writing long sequences of zeroes. We're too lazy for that. We'll try to write something like `"1bn"` for a billion or `"7.3bn"` for 7 billion 300 million. The same is true for most large numbers.

In JavaScript, we can shorten a number by appending the letter `"e"` to it and specifying the zeroes count:

```js run
let billion = 1e9; // 1 billion, literally: 1 and 9 zeroes

alert( 7.3e9 ); // 7.3 billions (7,300,000,000)
alert( 7.3e9 ); // 7.3 billions (same as 7300000000 or 7_300_000_000)
```

In other words, `"e"` multiplies the number by `1` with the given zeroes count.
In other words, `e` multiplies the number by `1` with the given zeroes count.

```js
1e3 = 1 * 1000
1.23e6 = 1.23 * 1000000
1e3 = 1 * 1000 // e3 means *1000
1.23e6 = 1.23 * 1000000 // e6 means *1000000
```

Now let's write something very small. Say, 1 microsecond (one millionth of a second):
Expand Down Expand Up @@ -125,7 +133,7 @@ There are several built-in functions for rounding:
: Rounds up: `3.1` becomes `4`, and `-1.1` becomes `-1`.

`Math.round`
: Rounds to the nearest integer: `3.1` becomes `3`, `3.6` becomes `4` and `-1.1` becomes `-1`.
: Rounds to the nearest integer: `3.1` becomes `3`, `3.6` becomes `4`, the middle case: `3.5` rounds up to `4` too.

`Math.trunc` (not supported by Internet Explorer)
: Removes anything after the decimal point without rounding: `3.1` becomes `3`, `-1.1` becomes `-1`.
Expand Down
2 changes: 1 addition & 1 deletion 1-js/05-data-types/10-destructuring-assignment/article.md
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ let [name1, name2] = ["Julius", "Caesar", "Consul", "of the Roman Republic"];

alert(name1); // Julius
alert(name2); // Caesar
// Furher items aren't assigned anywhere
// Further items aren't assigned anywhere
```

If we'd like also to gather all that follows -- we can add one more parameter that gets "the rest" using three dots `"..."`:
Expand Down
Loading