Skip to content

Commit 0279335

Browse files
committed
fixes, eventSource
1 parent 70cf2b2 commit 0279335

File tree

5 files changed

+428
-47
lines changed

5 files changed

+428
-47
lines changed

1-js/04-object-basics/03-symbol/article.md

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ A value of this type can be created using `Symbol()`:
1616
let id = Symbol();
1717
```
1818

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

2121
```js run
2222
// id is a symbol with the description "id"
@@ -74,7 +74,7 @@ alert(id.description); // id
7474

7575
Symbols allow us to create "hidden" properties of an object, that no other part of code can occasionally access or overwrite.
7676

77-
For instance, if we want to store an "identifier" for the object `user`, we can use a symbol as a key for it:
77+
For instance, if we'd like to add an "identifier" to the object `user`, we can use a symbol as a key for it:
7878

7979
```js run
8080
let user = { name: "John" };
@@ -88,7 +88,7 @@ What's the benefit of using `Symbol("id")` over a string `"id"`?
8888

8989
Let's make the example a bit deeper to see that.
9090

91-
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.
91+
Imagine that another script wants to have its own identifier inside `user`, for its own purposes. That may be another JavaScript library, so thes scripts are completely unaware of each other.
9292

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

@@ -99,9 +99,9 @@ let id = Symbol("id");
9999
user[id] = "Their id value";
100100
```
101101

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

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

106106
```js run
107107
let user = { name: "John" };
@@ -117,7 +117,7 @@ user.id = "Their id value"
117117

118118
### Symbols in a literal
119119

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

122122
Like this:
123123

@@ -155,7 +155,7 @@ for (let key in user) alert(key); // name, age (no symbols)
155155
alert( "Direct: " + user[id] );
156156
```
157157

158-
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.
158+
`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.
159159

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

@@ -190,13 +190,13 @@ alert( obj[0] ); // test (same property)
190190

191191
## Global symbols
192192

193-
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.
193+
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.
194194

195195
For instance, different parts of our application want to access symbol `"id"` meaning exactly the same property.
196196

197197
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.
198198

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

201201
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`.
202202

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

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

212212
// the same symbol
@@ -266,14 +266,14 @@ Other symbols will also become familiar when we study the corresponding language
266266

267267
`Symbol` is a primitive type for unique identifiers.
268268

269-
Symbols are created with `Symbol()` call with an optional description.
269+
Symbols are created with `Symbol()` call with an optional description (name).
270270

271-
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.
271+
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.
272272

273273
Symbols have two main use cases:
274274

275275
1. "Hidden" object properties.
276-
If we want to add a property into an object that "belongs" to another script or a library, we can create a symbol and use it as a property key. A symbolic property does not appear in `for..in`, so it won't be occasionally listed. Also it won't be accessed directly, because another script does not have our symbol, so it will not occasionally intervene into its actions.
276+
If we want to add a property into an object that "belongs" to another script or a library, we can create a symbol and use it as a property key. A symbolic property does not appear in `for..in`, so it won't be occasionally processed together with other properties. Also it won't be accessed directly, because another script does not have our symbol. So the property will be protected from occasional use or overwrite.
277277

278278
So we can "covertly" hide something into objects that we need, but others should not see, using symbolic properties.
279279

5-network/04-fetch-crossorigin/article.md

Lines changed: 48 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -18,82 +18,96 @@ try {
1818

1919
Fetch fails, as expected.
2020

21-
## Why?
21+
## Why? A brief history
2222

2323
Because cross-origin restrictions protect the internet from evil hackers.
2424

2525
Seriously. Let's make a very brief historical digression.
2626

27-
For many years JavaScript did not have any special methods to perform network requests.
28-
29-
**A script from one site could not access the content of another site.**
27+
**For many years a script from one site could not access the content of another site.**
3028

3129
That simple, yet powerful rule was a foundation of the internet security. E.g. a script from the page `hacker.com` could not access user's mailbox at `gmail.com`. People felt safe.
3230

33-
But web developers demanded more power. A variety of tricks were invented to work around it.
31+
JavaScript also did not have any special methods to perform network requests at that time. It was a toy language to decorate a web page.
32+
33+
But web developers demanded more power. A variety of tricks were invented to work around the limitation.
34+
35+
### Using forms
3436

3537
One way to communicate with another server was to submit a `<form>` there. People submitted it into `<iframe>`, just to stay on the current page, like this:
3638

3739
```html
3840
<!-- form target -->
41+
*!*
3942
<iframe name="iframe"></iframe>
43+
*/!*
4044

4145
<!-- a form could be dynamically generated and submited by JavaScript -->
46+
*!*
4247
<form target="iframe" method="POST" action="http://another.com/…">
48+
*/!*
4349
...
4450
</form>
4551

4652
```
4753

48-
- So, it was possible to make a GET/POST request to another site, even without networking methods.
49-
- But as it's forbidden to access the content of an `<iframe>` from another site, it wasn't possible to read the response.
54+
So, it was possible to make a GET/POST request to another site, even without networking methods. But as it's forbidden to access the content of an `<iframe>` from another site, it wasn't possible to read the response.
5055

51-
So, `<form>` allowed to submit the data anywhere, but the response content was unaccessible.
56+
...Okay, in fact there actually were tricks for that (required special scripts at both remote and our page), but let's not delve deeper. Nothing good in those for us now.
57+
58+
### Using scripts
5259

5360
Another trick was to use a `<script src="http://another.com/…">` tag. A script could have any `src`, from any domain. But again -- it was impossible to access the raw content of such script.
5461

5562
If `another.com` intended to expose data for this kind of access, then a so-called "JSONP (JSON with padding)" protocol was used.
5663

57-
Here's the flow:
64+
Let's say we need to get the data from `http://another.com` this way:
5865

5966
1. First, in advance, we declare a global function to accept the data, e.g. `gotWeather`.
60-
2. Then we make a `<script>` and pass its name as the `callback` query parameter, e.g. `src="http://another.com/weather.json?callback=gotWeather"`.
61-
3. The remote server dynamically generates a response that wraps the data into `gotWeather(...)` call.
67+
68+
```js
69+
// 1. Declare the function to process the data
70+
function gotWeather({ temperature, humidity }) {
71+
alert(`temperature: ${temperature}, humidity: ${humidity}`);
72+
}
73+
```
74+
2. Then we make a `<script>` tag with `src="http://another.com/weather.json?callback=gotWeather"`, please note that the name of our function is its `callback` parameter.
75+
76+
```js
77+
let script = document.createElement('script');
78+
script.src = `http://another.com/weather.json?callback=gotWeather`;
79+
document.body.append(script);
80+
```
81+
3. The remote server dynamically generates a script that calls `gotWeather(...)` with the data it wants us to receive.
82+
```js
83+
// The expected answer from the server looks like this:
84+
gotWeather({
85+
temperature: 25,
86+
humidity: 78
87+
});
88+
```
6289
4. As the script executes, `gotWeather` runs, and, as it's our function, we have the data.
6390
64-
Here's an example of the code to receive the data in JSONP:
6591
66-
```js run
67-
// 1. Declare the function to process the data
68-
function gotWeather({ temperature, humidity }) {
69-
alert(`temperature: ${temperature}, humidity: ${humidity}`);
70-
}
7192
72-
// 2. Pass its name as the ?callback parameter for the script
73-
let script = document.createElement('script');
74-
script.src = `https://cors.javascript.info/article/fetch-crossorigin/demo/script?callback=gotWeather`;
75-
document.body.append(script);
93+
That works, and doesn't violate security, because both sides agreed to pass the data this way. And, when both sides agree, it's definitely not a hack. There are still services that provide such access, as it works even for very old browsers.
7694
77-
// 3. The expected answer from the server looks like this:
78-
/*
79-
gotWeather({
80-
temperature: 25,
81-
humidity: 78
82-
});
83-
*/
84-
```
95+
After a while, networking methods appeared, such as `XMLHttpRequest`.
8596
97+
At first, cross-origin requests were forbidden. But as a result of long discussions, cross-domain requests were allowed, in a way that does not add any capabilities unless explicitly allowed by the server.
8698
87-
That works, and doesn't violate security, because both sides agreed to pass the data this way. And, when both sides agree, it's definitely not a hack. There are still services that provide such access, as it works even for very old browsers.
99+
## Simple requests
88100
89-
After a while, modern network methods appeared. At first, cross-origin requests were forbidden. But as a result of long discussions, cross-domain requests were allowed, in a way that does not add any capabilities unless explicitly allowed by the server.
101+
There are two types of cross-domain requests:
102+
1. Simple requests.
103+
2. All the others.
90104
91-
## Simple requests
105+
Simple Requests are, well, simpler to make, so let's start with them.
92106

93-
[Simple requests](http://www.w3.org/TR/cors/#terminology) must satisfy the following conditions:
107+
A [simple request](http://www.w3.org/TR/cors/#terminology) is a request that satisfies two conditions:
94108

95109
1. [Simple method](http://www.w3.org/TR/cors/#simple-method): GET, POST or HEAD
96-
2. [Simple headers](http://www.w3.org/TR/cors/#simple-header) -- only allowed:
110+
2. [Simple headers](http://www.w3.org/TR/cors/#simple-header) -- the only allowed custom headers are:
97111
- `Accept`,
98112
- `Accept-Language`,
99113
- `Content-Language`,

0 commit comments

Comments
 (0)