This commit is contained in:
Ilya Kantor 2016-07-22 20:47:41 +03:00
parent 057783d216
commit 3f5f2cac8b
324 changed files with 669 additions and 286 deletions

View file

@ -281,83 +281,6 @@ Any other operation like assignment `hi = user.hi` discards the reference type a
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).
## Explicit "this" with "call/apply" [#call-apply]
The value of `this` does not have to come from the aforementioned rules.
We can explicitly set it to any object using `func.call`.
The syntax is:
```js
func.call(context, arg1, arg2, ...)
```
For instance:
```js run
function sayHi() {
alert(this.name);
}
let user = { name: "John" };
let admin = { name: "Admin" };
// use call to pass different objects as "this"
sayHi.call( user ); // John
sayHi.call( admin ); // Admin
```
The first parameter of `call` is the intended value of `"this"`, the latter are arguments.
So `sayHi.call(admin)` runs the function `sayHi` with `this = admin`, hence `this.name` in it becomes `"Admin"`.
These calls are roughly equivalent:
```js
func(1, 2, 3);
func.call(obj, 1, 2, 3)
```
They both call `func` with arguments `1`, `2` and `3`. The only difference is that `call` also sets `"this"`.
The method `func.call` is used when we'd like to use a function in the context of different objects, but do not want to actually assign it to them. We'll see more examples of it soon.
### "func.apply"
There's also a similar method `func.apply`:
```js
func.apply(context, args)
```
It does the same as `call`: executes the function providing `context` as `this`, but where `call` awaits a list of arguments, `apply` awaits an array.
These two calls do the same:
```js
func.call(obj, 1, 2, 3);
func.apply(obj, [1, 2, 3]);
```
In old times `apply` was more powerful, because it allows to create the array of arguments dynamically. Their number is not hardcoded at code-write time.
But in the modern language, we have the spread operator `'...'` and can use it to convert an array into a list of for `call`, so these two are equal:
```js
let args = [1, 2, 3];
func.call(obj, ...args);
func.apply(obj, args);
```
Nowadays the use of `apply` or `call` is mainly a metter of personal preference. But `apply` is somewhat better optimized in engines than the call + spread combination, because it exists longer. So it would execute a little bit faster.
## Binding "this" with "bind"
There's still a way to bind "this" to a function.
[todo] migrate bind here????
## Summary