Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”

This article has participated in the “Digitalstar Project” and won a creative gift package to challenge the creative incentive money.

preface

This passage mainly analyzes the cow guest pen part of the examination questions this refers to the question. First, let’s take a look at JavaScript’s this pointing problem at a macro level.

Cow guest latest front-end JS written test 100 questions

There are four different bindings for this in JavaScript (including implicit lost bindings) plus the new arrow function bindings in ES6. If you learn all of these bindings, you should have no problem pointing this. This points to a more detailed explanation, you can go to the previous blog post, there are 38 topics, detailed and complete explanation of this points to the problem.

Portal: “2W word chapter 38 interview questions” completely clear JS this pointing to the problem

  • Default binding: in non-strict modethisPoints to global objects, in strict modethisWill be bound toundefined
  • Implicit binding: meetsXXX.fn()Format,fnthisPoint to theXXX. If there is a chain call,thisAlways point to the object that called it last
  • Implicit binding loss: alias the function and run through the alias; Functions as arguments cause implicit binding loss.
  • Explicit binding: Passcall/apply/bindModify thethisPoint to the
  • New Binding: PassnewTo call the constructor, a new object is generated, and this new object is bound to the calling functionthis
  • Arrow function bindings: Arrow functions do not have anythis, it’sthisThe outer scope is traced by scope chainthis, and refers to the function definitionthisNot at execution time

Title 1. Implicit binding and implicit binding loss

var x = 1;
var obj = {
    x: 3.fun:function () {
        var x = 5;
        return this.x; }};var fun = obj.fun;
console.log(obj.fun(), fun());
Copy the code

parsing

JavaScript addresses for reference types are stored in stack memory, whereas real ontologies are stored in heap memory. Fun = obj.fun is equivalent to assigning the heap memory pointer to obJ. fun to fun, after which fun execution has no relationship with OBj, implicit binding loss occurs.

  • obj.fun(): Implicit binding,funThe inside of thethisPoint to theobjTo print3
  • fun()Implicit binding loss:funDefault binding, non-strict mode,thisPoint to thewindowTo print1

The answer

3 1
Copy the code

Title two: Implicit binding loss

var person = {
  age: 18.getAge: function() {
    return this.age; }};var getAge = person.getAge
console.log(getAge())
Copy the code

Simple implicit binding loss problem

The answer

undefined
Copy the code

Title 3: Implicit binding loss

var obj = {
    name:"zhangsan".sayName:function(){
        console.log(this.name); }}var wfunc = obj.sayName;
obj.sayName();
wfunc();
var name = "lisi";
obj.sayName();
wfunc();
Copy the code

Simple implicit binding problem, not to go into detail.

The answer

zhangsan
undefined
zhangsan
lisi
Copy the code

Topic 4: New binding

var a = 5;
function test() { 
    a = 0; 
    console.log(a); 
    console.log(this.a); 
    var a;
    console.log(a); 
}
new test();
Copy the code

parsing

Using new to build a function does the following four things:

  1. Create an empty simpleJavaScriptThe object (i.e.{});
  2. Add attributes to the object created in Step 1__proto__Link this property to the constructor’s prototype object;
  3. Take the object created in Step 1 as the objectthisContext;
  4. Returns if the function does not return an objectthis.

Calling the constructor with new generates a new object and binds the new object to the calling function’s this.

  • console.log(a): Print variablesaThe current value oftestAOinaVariable, print0
  • console.log(this.a): newThe bindingthisPoints to a new instance object that the current title does not add toaProperties, printundefined
  • console.log(a): Same as the first one, print0

The answer

0
undefined
0
Copy the code

Title 5: Arrow functions and explicit binding

function fun () {
    return () = > {
        return () = > {
            return () = > {
                console.log(this.name)
            }
        }
    }
}
var f = fun.call({name: 'foo'})
var t1 = f.call({name: 'bar'}) () ()var t2 = f().call({name: 'baz'}) ()var t3 = f()().call({name: 'qux'})
Copy the code
  1. The arrow function does not have this; its this is traced through the scope chain to the this of the outer scope and refers to this when the function is defined, not when it is executed.

  2. The arrow function cannot modify this by calling apply bind, but can modify this indirectly by modifying this in the outer scope.

  3. JavaScript is statically scoped, meaning that the function’s scope is determined at function definition, whereas the arrow function’s this is found through the scope chain, so the arrow function’s scope chain is defined.

  • f = fun.call({name: 'foo'})Will:funFunction of thethisPoint to the{name: 'foo'}And returns an arrow function, so the arrow functionthisPoint to{name: 'foo'}
  • t1 = f.call({name: 'bar'})()(): executes on the first-level arrow functioncallOperation, invalid, currentthisStill point to{name: 'foo'}The second layer, the third layer are arrow functions, the third layerthisPoint to{name: 'foo'}To printfoo
  • subsequentt2 t3Apply to the second – and third-layer arrow functions respectivelycall, invalid, and eventually printedfoo

The answer

foo
foo
foo
Copy the code

Topic 6: Arrow functions

let obj1 = {
    a: 1.foo: () = > {
        console.log(this.a)
    }
}
// log1
console.log(obj1.foo())
const obj2 = obj1.foo
// log2
console.log(obj2())
Copy the code

parsing

  1. obj1.fooIs the arrow function,obj1Object, cannot provide an outer scope, soobj.fooThe inside of thethisPoint to thewindow
  • obj1.foo(): arrow function,thisPoint to thewindowTo printundefined
  • obj2Implicit binding lost: Printundefined

The answer

undefined
undefined
Copy the code

Directions: For this part, you are allowed 30 minutes to write a composition.

var name = 'global';
var obj = {
    name: 'local'.foo: function(){
        this.name = 'foo';
        console.log(this.name);
    }.bind(window)};var bar = new obj.foo();
setTimeout(function() {
    console.log(window.name);
}, 0);
console.log(bar.name);
 
var bar3 = bar2 = bar;
bar2.name = 'foo2';
console.log(bar3.name);
Copy the code

parsing

The overall quality of this topic is still very high, first of all, let’s put the knowledge involved in a list:

  1. bindIt is explicitly bound and will changethisPoint, butbind()The function does not execute the function immediately, but returns a new function
  2. setTimeoutAn asynchronous task can be executed only after the synchronization task is complete
  3. Binding priority: New binding > Explicit binding > Implicit binding > Default binding

parsing

  • obj.fooWill itthisthroughbindThe explicit binding iswindow, butbindNot immediately
  • var bar = new obj.foo(): newThe binding priority is greater thanbind, sobindIt failed, and nowthisPoint to thenewInstance, thereforeobj.fooThe inside of theconsoleprintfoo
  • barnew obj.foo()An instance of theconsole.log(bar.name)printfoo
  • setTimeoutAsynchronous tasks that wait until synchronization is complete before calling its callback
  • bar3 = bar2 = barThat will beBar2, bar3, barThe address of thebarThe space that I’m pointing to.
  • bar2.name = 'foo2'To change the value of the address pointing to heap memory
  • console.log(bar3.name)Since all three variables point to the same block of address,bar3To modify thenamebar3Also change, printfoo2
  • setTimeoutThe callback is executed and printedglobal

The answer

foo
foo
foo2
global
Copy the code

Topic 7: Comprehensive topic modification

Although the sixth topic is of good quality, I feel that there are several places that people are not satisfied with. Let’s change the topic.

Change 1: Remove the new binding

var name = 'global';
var obj = {
    name: 'local'.foo: function(){
        this.name = 'foo';
        console.log(this.name);
    }.bind(window)}; obj.foo();setTimeout(function() {
    console.log(this.name);
}, 0);
console.log(name);
Copy the code
  • obj.fooNo modifications were made to itthisthroughbindThe explicit binding iswindow, butbindNot immediately
  • obj.foo()Execute, explicit binding takes precedence over implicit binding, so at this pointfoofunctionthis -> window
  • this.nameThe equivalent ofwindow.name, modified globalnameVariable value, printfoo
  • setTimeoutCallback and other synchronization code execution is complete
  • globalnameHas been modified tofooTo printfoo
  • performsetTimeoutThe callback, default binding, printsfoo

The answer

foo
foo
foo
Copy the code

Change 1: change bind to call

var name = 'global';
var obj = {
    name: 'local'.foo: function(){
        this.name = 'foo';
        console.log(this.name); }}; obj.foo.call(window);
var bar = new obj.foo();
setTimeout(function() {
    console.log(window.name);
}, 0);
console.log(bar.name);
 
var bar3 = bar2 = bar;
bar2.name = 'foo2';
console.log(bar3.name);
Copy the code

The difference between call and bind is that the call function executes immediately

So obj.foo.call(window) immediately executes the function and also modifies the global name value. The other parts are similar to those mentioned above, so I won’t repeat them.

The answer

foo
foo
foo
foo2
foo
Copy the code

Past wonderful articles

  • Cow guest latest front-end JS written test 100 questions
  • A thorough understanding of prototypes and prototype chains in JavaScript
  • JavaScript precompilation learning
  • Complete understanding of EventLoop in JavaScript
  • “2W word big chapter 38 interview questions” completely clear JS this pointing to the problem