This deep understanding
Series of the opening
Establish clear, precise, essential concepts and clear, precise, necessary connections between them as you enter the front end, so that you can stay calm in whatever interview you’re going to be doing. There is no catalog, but a web of knowledge formed through the association of concepts, as you can see below. When you encounter a relation concept, you can use the parentheses (strong/weak) to determine whether the relation is strongly related to the concept you are understanding (you need to understand before you can proceed) or weakly related (knowledge expansion) to improve your reading efficiency. I also update related concepts regularly.
The interview questions
- Tell me what you know about this direction
- Do you know this for the arrow function
- Call /apply/bind/new is associated with this
- Can you implement the above primitive functions and explain how they work
What’s this for? Why?
This is a keyword in javascript that provides a more elegant way to implicitly “pass” an object reference, so apis can be designed to be cleaner and easier to reuse.
Remember there are some ways you can’t read it and skip it, it’s not linear, you can write down what’s not clear, look at the next one, the unknown is always there, don’t be afraid.
For example, first we use this, which is probably code that we write on purpose or not.
// Define two objects: you and me
let me = {
name: "NeverMore"
};
let you = {
name: "Reader"
};
// Change the name to uppercase
function identify() {
return this.name.toUpperCase();
}
// Print a way to say hello
function speak() {
let greeting = "Hello, I'm " + identify.call(this);
console.log(greeting);
}
identify.call(me); // NEVERMORE
identify.call(you); // READER
speak.call(me); // Hello, I'm NEVERMORE
speak.call(you); // Hello, I'm READER
Copy the code
If you do not use this, you should write:
function identify(context) {
return context.name.toUpperCase();
}
function speak(context) {
var greeting = "Hello, I'm " + identify(context);
console.log(greeting);
}
identify(you); // READER
speak(me); / / hello, I'm NEVERMORE
Copy the code
If you do not use this, you explicitly pass in a context object context to identify() and speak().
As your usage patterns get more complex, passing context objects explicitly will clutter up your code. Using this will not. When we introduce objects and stereotypes, you’ll see how important it is for functions to automatically reference the appropriate context objects.
What is the mechanism of this and how to analyze its direction
this
Is in theBind at run timeandNot binding at authoring timeIts context depends on the conditions under which the function is called.this
The binding has nothing to do with where the function is declared, but only how the function is called.- When a function is called, an execution context is created. This record contains information about where the function was called (call stack, execution stack), how the function was called, the parameters passed in, and so on. This is one of the properties of the record that is used during the execution of the function. One part of the creation process for the execution context is this Binding.
- This is actually a binding that happens when the function is called, and what it points to depends entirely on where and how the function is called.
First, the calling location is where the function is called in the code (not where it is declared). The most important thing is to analyze the call stack (that is, all the functions called to get to the current execution location). The call location we care about is in the previous call to the currently executing function.
Alternatively, we can print a stack trace with console.trace().
function baz() {
// The current stack is: baz
// Therefore, the current call location is global scope
console.trace( "baz" );
bar(); // <-- bar call location
}
function bar() {
// The current stack is: baz --> bar
// Therefore, the current call location is in baz
console.trace( "bar" );
foo(); // <-- foo's call location
}
function foo() {
// The current stack is: baz --> bar --> foo
// Therefore, the current call location is in bar
console.trace( "foo" );
}
baz();
Copy the code
It’s convenient. It’s consistent with our human analysis.
Misunderstanding of this
Before introducing the this binding rule, let’s look at some common misconceptions about this.
Myth # 1: Pointing to the function itself
I do hear this a lot in interviews
Why do we need to reference the function itself from within the function?
Common reasons are recursion (calling the function from within the function) or you can write an event handler that unbinds itself after the first call. Now let’s examine the pattern to show that this does not refer to the function itself as we thought.
function foo(num) {
console.log("foo: " + num);
// Records the number of times foo is called
this.count++;
}
foo.count = 0;
var i;
for (i = 0; i < 10; i++) {
if (i > 5) { foo(i); }}// foo: 6
// foo: 7
// foo: 8
// foo: 9
console.log(foo.count); / / 0???
Copy the code
How many times is Foo called? The console.log statement produces four outputs, proving that foo(..) It does get called four times, but foo.count is still 0. It is clearly a mistake to understand this from the reference function itself.
So how do we get there
- Solution – lexical scope
// Create another object with the count attribute
function foo(num) {
console.log("foo: " + num);
// Records the number of times foo is called
data.count++;
}
var data = {
count: 0
};
var i;
for (i = 0; i < 10; i++) {
if (i > 5) { foo(i); }}// foo: 6
// foo: 7
// foo: 8
// foo: 9
// How many times is foo called?
console.log( data.count ); / / 4
Copy the code
However, this approach obviously begs the question of this.
- Solution two forces this to point to function object foo
function foo(num) {
console.log("foo: " + num);
// Records the number of times foo is called
// Notice that in the current invocation (see code below), this does refer to foo
this.count++;
}
foo.count = 0;
var i;
for (i = 0; i < 10; i++) {
if (i > 5) {
foo.call(foo, i); / / using the call (..) You can make sure that this refers to the function object foo itself}}// foo: 6
// foo: 7
// foo: 8
// foo: 9
// How many times is foo called?
console.log( foo.count ); / / 4
Copy the code
Myth 2: Pointing to the scope of the function itself
The second common misconception is that this refers to the scope of a function.
It’s a bit complicated, because in some cases it’s true, but in others it’s not.
To be clear, this does not refer to the lexical scope of a function in any case.
Inside JavaScript, a scope is really like an object in that the visible identifiers are its properties. But the scoped “object” is not accessible through JavaScript code; it exists inside the JavaScript engine.
Consider the following code that tries (but fails) to cross the border and use this to implicitly reference the lexical scope of a function:
function foo() {
var a = 2;
this.bar();
}
function bar() {
console.log(this.a);
}
foo(); // ReferenceError: a is not defined
Copy the code
First, the code attempts to reference the bar() function via this.bar(). It’s a non-starter, and we’ll explain why later. In the next article [binding rules for this].
The most natural way to call bar() is to omit the preceding this and refer directly to the identifier using a lexical reference. In addition, the developer who wrote this code is trying to use this to connect the lexical scopes of foo() and bar() so that bar() can access variable A in the scope of foo(). This is impossible. You can’t use this to refer to something inside a lexical scope.
Whenever you want to mix this with lexical lookup, remind yourself that it’s not possible.
The binding rule for this
So let’s just leave the first idea of this. How to analyze this binding, binding rules, priorities, etc. Binding rules for this in javascript
reference
- You don’t know Javascript
- developer.mozilla.org/zh