diff --git a/1-js/04-object-basics/04-object-methods/2-check-syntax/solution.md b/1-js/04-object-basics/04-object-methods/2-check-syntax/solution.md index e2e87de7..5589b655 100644 --- a/1-js/04-object-basics/04-object-methods/2-check-syntax/solution.md +++ b/1-js/04-object-basics/04-object-methods/2-check-syntax/solution.md @@ -15,13 +15,13 @@ The error message in most browsers does not give understanding what went wrong. **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 auto-insert a semicolon before a bracket `(user.go)()`, so it reads the code like: ```js no-beautify let user = { go:... }(user.go)() ``` -Then we can also see that such a joint expression is syntactically a call of the object `{ go: ... }` as a function with the argument `(user.go)`. And that also happens on the same line with `let user`, so the `user` object has not yet even been defined, hence the error. +Then we can also see that such a joint expression is syntactically a call of the object `{ go: ... }` as a function with the argument `(user.go)`. And that also happens on the same line with `let user`, so the `user` object has not yet even been defined, hence the error. If we insert the semicolon, all is fine: @@ -35,9 +35,3 @@ let user = { ``` Please note that brackets around `(user.go)` do nothing here. Usually they setup the order of operations, but here the dot `.` works first anyway, so there's no effect. Only the semicolon thing matters. - - - - - - diff --git a/1-js/04-object-basics/04-object-methods/4-object-property-this/solution.md b/1-js/04-object-basics/04-object-methods/4-object-property-this/solution.md index f5773ec2..ea00c970 100644 --- a/1-js/04-object-basics/04-object-methods/4-object-property-this/solution.md +++ b/1-js/04-object-basics/04-object-methods/4-object-property-this/solution.md @@ -14,11 +14,11 @@ let user = makeUser(); alert( user.ref.name ); // Error: Cannot read property 'name' of undefined ``` -That's because rules that set `this` do not look at object literals. +That's because rules that set `this` do not look at object definition. Only the moment of call matters. -Here the value of `this` inside `makeUser()` is `undefined`, because it is called as a function, not as a method. +Here the value of `this` inside `makeUser()` is `undefined`, because it is called as a function, not as a method with "dot" syntax. -And the object literal itself has no effect on `this`. The value of `this` is one for the whole function, code blocks and object literals do not affect it. +The value of `this` is one for the whole function, code blocks and object literals do not affect it. So `ref: this` actually takes current `this` of the function. @@ -42,5 +42,3 @@ alert( user.ref().name ); // John ``` Now it works, because `user.ref()` is a method. And the value of `this` is set to the object before dot `.`. - - diff --git a/1-js/04-object-basics/04-object-methods/article.md b/1-js/04-object-basics/04-object-methods/article.md index a79832f7..f449c8c2 100644 --- a/1-js/04-object-basics/04-object-methods/article.md +++ b/1-js/04-object-basics/04-object-methods/article.md @@ -257,11 +257,11 @@ user.hi(); // John (the simple call works) */!* ``` -On the last line there is a ternary operator that chooses either `user.hi` or `user.bye`. In this case the result is `user.hi`. +On the last line there is a conditinal operator that chooses either `user.hi` or `user.bye`. In this case the result is `user.hi`. -The method is immediately called with parentheses `()`. But it doesn't work right! +Then the method is immediately called with parentheses `()`. But it doesn't work right! -You can see that the call results in an error, because the value of `"this"` inside the call becomes `undefined`. +As you can see, the call results in an error, because the value of `"this"` inside the call becomes `undefined`. This works (object dot method): ```js @@ -306,7 +306,7 @@ The Reference Type is a "specification type". We can't explicitly use it, but it The value of Reference Type is a three-value combination `(base, name, strict)`, where: - `base` is the object. -- `name` is the property. +- `name` is the property name. - `strict` is true if `use strict` is in effect. The result of a property access `user.hi` is not a function, but a value of Reference Type. For `user.hi` in strict mode it is: @@ -318,6 +318,8 @@ The result of a property access `user.hi` is not a function, but a value of Refe When parentheses `()` are called on the Reference Type, they receive the full information about the object and its method, and can set the right `this` (`=user` in this case). +Reference type is a special "intermediary" internal type, with the purpose to pass information from dot `.` to calling parentheses `()`. + Any other operation like assignment `hi = user.hi` discards the reference type as a whole, takes the value of `user.hi` (a function) and passes it on. So any further operation "loses" `this`. So, as the result, the value of `this` is only passed the right way if the function is called directly using a dot `obj.method()` or square brackets `obj['method']()` syntax (they do the same here). Later in this tutorial, we will learn various ways to solve this problem such as [func.bind()](/bind#solution-2-bind). diff --git a/5-network/06-url/article.md b/5-network/06-url/article.md index 4615a4e5..47ccb918 100644 --- a/5-network/06-url/article.md +++ b/5-network/06-url/article.md @@ -3,7 +3,7 @@ The built-in [URL](https://url.spec.whatwg.org/#api) class provides a convenient interface for creating and parsing URLs. -We don't have to use it at all. There are no networking methods that require exactly an `URL` object, strings are good enough. But sometimes it can be really helpful. +There are no networking methods that require exactly an `URL` object, strings are good enough. So technically we don't have to use `URL`. But sometimes it can be really helpful. ## Creating an URL @@ -13,8 +13,28 @@ The syntax to create a new URL object: new URL(url, [base]) ``` -- **`url`** -- the text url -- **`base`** -- an optional base for the `url` +- **`url`** -- the URL string or path (if base is set, see below). +- **`base`** -- an optional base, if set and `url` has only path, then the URL is generated relative to `base`. + +For example, these two URLs are same: + +```js run +let url1 = new URL('https://javascript.info/profile/admin'); +let url2 = new URL('/profile/admin', 'https://javascript.info'); + +alert(url1); // https://javascript.info/profile/admin +alert(url2); // https://javascript.info/profile/admin +``` + +Переход к пути относительно текущего URL: + +```js run +let url = new URL('https://javascript.info/profile/admin'); +let testerUrl = new URL('tester', url); + +alert(testerUrl); // https://javascript.info/profile/tester +``` + The `URL` object immediately allows us to access its components, so it's a nice way to parse the url, e.g.: @@ -32,21 +52,10 @@ Here's the cheatsheet: - `href` is the full url, same as `url.toString()` - `protocol` ends with the colon character `:` -- `search` starts with the question mark `?` +- `search` - a string of parameters, starts with the question mark `?` - `hash` starts with the hash character `#` - there are also `user` and `password` properties if HTTP authentication is present. -We can also use `URL` to create relative urls, using the second argument: - -```js run -let url = new URL('profile/admin', 'https://javascript.info'); - -alert(url); // https://javascript.info/profile/admin - -url = new URL('tester', url); // go to 'tester' relative to current url path - -alert(url); // https://javascript.info/profile/tester -``` ```smart header="We can use `URL` everywhere instead of a string" We can use an `URL` object in `fetch` or `XMLHttpRequest`, almost everywhere where a string url is expected. @@ -54,15 +63,15 @@ We can use an `URL` object in `fetch` or `XMLHttpRequest`, almost everywhere whe In the vast majority of methods it's automatically converted to a string. ``` -## SearchParams +## SearchParams "?..." -Let's say we want to create an url with given search params, for instance, `https://google.com/search?query=value`. +Let's say we want to create an url with given search params, for instance, `https://google.com/search?query=JavaScript`. -They must be correctly encoded. +They must be correctly encoded to include non-latin charcters, spaces etc. -In very old browsers, before `URL` appeared, we'd use built-in functions `encodeURIComponent/decodeURIComponent`. +Some time ago, before `URL` objects appeared, we'd use built-in functions `encodeURIComponent/decodeURIComponent`. They have some problems, but now that doesn't matter. -Now, there's no need: `url.searchParams` is an object of type [URLSearchParams](https://url.spec.whatwg.org/#urlsearchparams). +There's URL property for that: `url.searchParams` is an object of type [URLSearchParams](https://url.spec.whatwg.org/#urlsearchparams). It provides convenient methods for search parameters: @@ -81,7 +90,7 @@ For example: ```js run let url = new URL('https://google.com/search'); -url.searchParams.set('query', 'test me!'); +url.searchParams.set('query', 'test me!'); // added parameter with a space and ! alert(url); // https://google.com/search?query=test+me%21