This is the 24th day of my participation in the August More Text Challenge.
preface
Function.prototype.call I think you all think you are familiar with it and can write it by hand!! Before you confirm this question, first have a look at three thousand words.
After reading, you feel OK, then look at a problem: please ask the following output result
function a(){
console.log(this.'a')};function b(){
console.log(this.'b')
}
a.call.call(b,'b')
Copy the code
If, you also clearly know, the result, sorry, big guy, disturb, I was wrong!
The origin of this article: a digger added me to wechat and asked me this question in private chat. After researching it, he asked Po Ge. Feel very interesting, then share with everyone!
The results of
The result: Surprise or surprise, or calm?
String {"b"} "b"
Copy the code
For two, three, four, or more calls, the output will be String {“b”} “b”.
function a(){
console.log(this.'a')};function b(){
console.log(this.'b')
}
a.call.call(b,'b') // String {"b"} "b"
a.call.call.call(b,'b') // String {"b"} "b"
a.call.call.call.call(b,'b') // String {"b"} "b"
Copy the code
After reading the above, there should be three questions, right?
- Why is it called
b
function - why
this
isString {"b"}
- Why two, three, four
call
With the same results.
Call (b, ‘b’); call(b, ‘b’);
Analysis of the
Why two, three, fourcall
With the same results.
A.call (b) is finally called by a, a.call.call(b), which is finally called by a.call.call.call(b), which is finally executed by A.call.call
Look at the reference relationship
a.call === Function.protype.call // true
a.call === a.call.call // true
a.call === a.call.call.call // true
Copy the code
A. call.call (function.prototype. call); function.prototype. call
Why are the results of 2, 3 and 4 calls the same and the truth is already there
Why is it calledb
function
Look at the essence will be back to nature, ES standard for Funtion. Prototye. Call description
Function.prototype.call (thisArg , … args)
When the
call
method is called on an objectfunc
with argument,thisArg
and zero or moreargs
, the following steps are taken:
- If IsCallable(func) is false, throw a TypeError exception.
- Let argList be an empty List.
- If this method was called with more than one argument then in left to right order, starting with the second argument, append each argument as the last element of argList.
- Perform PrepareForTailCall().
- Return Call(func.thisArg.argList).
Translate it into Chinese
- If not, throw an exception
- Prepare an argList empty array variable
- Variables after the first are added to argList in order
- returnCall(func.thisArg.argListThe result of)
Instead of an abstract definition, Call is actually a Call to the [[Call]] method inside the function, and it doesn’t reveal much useful information.
In fact, I’ve stopped thinking here:
a is a function, then what a.call.call really do? Bind (MDN, function.prototype.bind) : “I have Bound Function Exotic Objects.
The
bind()
function creates a new bound function, which is an exotic function object (a term from ECMAScript 2015) that wraps the original function object. Calling the bound function generally results in the execution of its wrapped function.
Function.prototype.call is not mentioned!! But do not check that there is a build during the call.
Difference between Function.call, Function.prototype.call, Function. The prototype. The call. The call and the Function. The prototype. The call. The call. The call is to explain, I think it is more reasonable
function my(p) { console.log(p) }
Function.prototype.call.call(my, this."Hello"); // output 'Hello'
Copy the code
Function.prototype.call.call(my, this, "Hello");
means:Use
my
asthis
argument (the function context) for the function that wascall
ed. In this caseFunction.prototype.call
was called.So,
Function.prototype.call
would be called withmy
as its context. Which basically means – it would be the function to be invoked.It would be called with the following arguments:
(this, "Hello")
, wherethis
is the context to be set inside the function to be called (in this case it’smy
), and the only argument to be passed is"Hello"
string.
Highlight: So, Function.prototype.call would be called with my as its context. Which basically means – it would be the function to be invoked.
It would be called with the following arguments: (this, "Hello")
, where this
is the context to be set inside the function to be called (in this case it’s my
), and the only argument to be passed is "Hello"
string
Translation: the Function prototype. Call. The call (my, this, “Hello”), said: in my as the context to invoke the Function. The prototype. The call, that is to say my is ultimately the called Function.
My is called with these (this, “Hello”), this as the context of the called function, here as the context of my function, and the only argument passed is the “Hello” string.
With this understanding, let’s just verify that this is indeed the case
// case 1:
function my(p) { console.log(p) }
Function.prototype.call.call(my, this."Hello"); // output 'Hello'
// case 2:
function a(){
console.log(this.'a')};function b(){
console.log(this.'b')
}
a.call.call(b,'b') // String {"b"} "b"
Copy the code
Why is it calledb
Delta function, that’s the truth.
In fact, I still can not be too relieved, but this explanation is acceptable, the appearance is correct, expect digg friends to have a more reasonable, more detailed answer.
whythis
isString {"b"}
I intentionally left out two notes for function.prototype. call in the previous section
NOTE 1: The thisArg value is passed without modification as the this value. This is a change from Edition 3, where an undefined or null thisArg is replaced with the global object and ToObject is applied to all other values and that result is passed as the this value. Even though the thisArg is passed without modification, non-strict functions still perform these transformations upon entry to the function.
NOTE 2: If
func
is an arrow function or a bound function then thethisArg
will be ignored by the function [[Call]] in step 5.
Notice this sentence:
This is a change from Edition 3, where an undefined or null thisArg is replaced with the global object and ToObject is applied to all other values and that result is passed as the this value
Two points:
- if
thisArg
isundefined
ornull
, will be replaced with global Object
The premise here is non-strict mode
"use strict"
function a(m){
console.log(this, m); // undefined, 1
}
a.call(undefined.1)
Copy the code
- For all other types, ToObject is called for conversion
So in non-strict mode, this must be an object, look at the following code:
Object('b') // String {"b"}
Copy the code
ToObject of Note2 is the answer
That’s it. Whythis
isSting(b)
That’s true, too
Universal function call method
. Based on the Function prototype. Call. The characteristics of the call, we can encapsulate a universal method of Function calls
var call = Function.prototype.call.call.bind(Function.prototype.call);
Copy the code
The sample
var person = {
hello() {
console.log('hello'.this.name)
}
}
call(person.hello, {"name": "tom"}) // hello tom
Copy the code
Write in the last
If you think it is good, your likes and comments are the biggest motivation for me to move forward.
Technical group please come here. Or add my wechat Dirge-Cloud and learn together.
reference
sec-function.prototype.call
Bound Function Exotic Objects
Function.prototype.bind a is a function, then whata.call.call
really do?
Difference between Function.call, Function.prototype.call, Function.prototype.call.call and Function.prototype.call.call.call
Javascript Function.prototype.call()
Can’t use Function.prototype.call directly