You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: 1-js/04-object-basics/03-symbol/article.md
+13-13Lines changed: 13 additions & 13 deletions
Original file line number
Diff line number
Diff line change
@@ -16,7 +16,7 @@ A value of this type can be created using `Symbol()`:
16
16
let id =Symbol();
17
17
```
18
18
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:
20
20
21
21
```js run
22
22
// id is a symbol with the description "id"
@@ -74,7 +74,7 @@ alert(id.description); // id
74
74
75
75
Symbols allow us to create "hidden" properties of an object, that no other part of code can occasionally access or overwrite.
76
76
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:
78
78
79
79
```js run
80
80
let user = { name:"John" };
@@ -88,7 +88,7 @@ What's the benefit of using `Symbol("id")` over a string `"id"`?
88
88
89
89
Let's make the example a bit deeper to see that.
90
90
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.
92
92
93
93
Then that script can create its own `Symbol("id")`, like this:
94
94
@@ -99,9 +99,9 @@ let id = Symbol("id");
99
99
user[id] ="Their id value";
100
100
```
101
101
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.
103
103
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:
105
105
106
106
```js run
107
107
let user = { name:"John" };
@@ -117,7 +117,7 @@ user.id = "Their id value"
117
117
118
118
### Symbols in a literal
119
119
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.
121
121
122
122
Like this:
123
123
@@ -155,7 +155,7 @@ for (let key in user) alert(key); // name, age (no symbols)
155
155
alert( "Direct: "+ user[id] );
156
156
```
157
157
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.
159
159
160
160
In contrast, [Object.assign](mdn:js/Object/assign) copies both string and symbol properties:
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.
194
194
195
195
For instance, different parts of our application want to access symbol `"id"` meaning exactly the same property.
196
196
197
197
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.
198
198
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)`.
200
200
201
201
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`.
202
202
@@ -206,7 +206,7 @@ For instance:
206
206
// read from the global registry
207
207
let id =Symbol.for("id"); // if the symbol did not exist, it is created
208
208
209
-
// read it again
209
+
// read it again (maybe from another part of the code)
210
210
let idAgain =Symbol.for("id");
211
211
212
212
// the same symbol
@@ -266,14 +266,14 @@ Other symbols will also become familiar when we study the corresponding language
266
266
267
267
`Symbol` is a primitive type for unique identifiers.
268
268
269
-
Symbols are created with `Symbol()` call with an optional description.
269
+
Symbols are created with `Symbol()` call with an optional description (name).
270
270
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.
272
272
273
273
Symbols have two main use cases:
274
274
275
275
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.
277
277
278
278
So we can "covertly" hide something into objects that we need, but others should not see, using symbolic properties.
Copy file name to clipboardExpand all lines: 5-network/04-fetch-crossorigin/article.md
+48-34Lines changed: 48 additions & 34 deletions
Original file line number
Diff line number
Diff line change
@@ -18,82 +18,96 @@ try {
18
18
19
19
Fetch fails, as expected.
20
20
21
-
## Why?
21
+
## Why? A brief history
22
22
23
23
Because cross-origin restrictions protect the internet from evil hackers.
24
24
25
25
Seriously. Let's make a very brief historical digression.
26
26
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.**
30
28
31
29
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.
32
30
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
34
36
35
37
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:
36
38
37
39
```html
38
40
<!-- form target -->
41
+
*!*
39
42
<iframename="iframe"></iframe>
43
+
*/!*
40
44
41
45
<!-- a form could be dynamically generated and submited by JavaScript -->
- 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.
50
55
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
52
59
53
60
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.
54
61
55
62
If `another.com` intended to expose data for this kind of access, then a so-called "JSONP (JSON with padding)" protocol was used.
56
63
57
-
Here's the flow:
64
+
Let's say we need to get the data from `http://another.com` this way:
58
65
59
66
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.
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.
That works, and doesn't violate security, because both sides agreed to pass the data thisway. 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.
76
94
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`.
85
96
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.
86
98
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
88
100
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.
90
104
91
-
## Simple requests
105
+
Simple Requests are, well, simpler to make, so let's start with them.
92
106
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:
94
108
95
109
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:
0 commit comments