A directory

What’s the difference between a free front end and a salted fish

directory
A directory
The preface
This in the global execution context
The function executes this in the context
 4.1 Change this by call/bind/apply
 4.2 Call method Settings through objects
 4.3 Using the constructor
This design defect and solution
 This in 5.1 nested functions does not inherit from outer functions
 5.2 In ordinary functions, this refers to the global object Window
React this points to
 6.1 Solution 1: Bind this in advance
 6.2 Solution 2: Bind this when called
 6.3 Solution 3: Return an arrow function
 6.4 Solution 4: Turn the calling method into an arrow function (failed)
 6.5 React This points to the actual content
 6.6 React This points to a solution
Seven summary
Eight topics
 8.1 This topic analyzes 5 steps
 8.2 let/const this
 8.3 Arrow function this
 8.4 Obtaining the output result
 8.5 Implicit binding loss
  8.5.1 Obtaining the output result
  8.5.2 Obtaining the output result
 8.6 Displaying binding Problems
  8.6.1 Obtaining the output result
  8.6.2 Obtaining the output result
 8.7 Obtaining the Output Result
 8.8 in this paper, the problem
Ix References

The preface

Returns the directory

Remember one sentence:

  • thisAlways point to the object that called it last

Two more things to remember:

  • In ordinary functionsthisTheta points to theta, yesthis Execution timeThe context in which the
  • In the arrow functionthisTheta points to theta, yesthis To define theThe context in which the

The scope chain and this are two different systems, and there is not much connection between them.

This is bound to the execution context, meaning that there is a this in each execution context.

There are three execution contexts:

  • Global execution context
  • Function execution context
  • evalExecution context

Note that this is in the browser, which is not the same as this in Node.

This in the global execution context

Returns the directory

Type: this into the Chrome console and you’ll see the answer:

Window {postMessage: ƒ.blur: ƒ.focus: ƒ.close: ƒ.parent: Windows,... }Copy the code

This in the global execution context refers to the Window.

function foo() {
  console.log(this);
}
foo();
Copy the code

This code also outputs Window, why?

Remember that this refers to whoever calls it.

We call foo in the global object, which is essentially a call to window.foo(), which points to window.

After executing the code above, you can type Window on the Chrome console and see foo().

Notice that this is non-strict mode. Uncaught TypeError: Cannot read property ‘name’ of undefined

The function executes this in the context

Returns the directory

As we’ve seen above, the usual way to call a method is to call a method on the window.

So how do I get this of the current function?

4.1 Change this by call/bind/apply

Returns the directory

this.myName = 'jsliang';
let foo = function() {
  this.myName = 'zhazhaliang';
}
foo();
console.log(window.myName); // Output what?
console.log(foo.myName); // Output what?
Copy the code

This refers to the window, so the output is;

  • zhazhaliang
  • undefined

After call binding:

this.myName = 'jsliang';
let foo = function() {
  this.myName = 'zhazhaliang';
}
foo.call(foo);
console.log(window.myName); // Output what?
console.log(foo.myName); // Output what?
Copy the code

The output is:

  • jsliang
  • zhazhaliang

Of course, you can also switch to apply and bind, so we don’t have to elaborate here.

4.2 Call method Settings through objects

Returns the directory

Use an object to call a method within it whose this refers to the object itself.

  • Case 1
let myObj = {
  name: 'jsliang'.showThis: function() {
    console.log(this.name); }}; myObj.showThis();// Output what?
Copy the code

Answer: Output jsliang.

We should always remember: who calls to whom. This is a call to myObj, so this points to myObj at the moment. MyObj contains name: jsliang, so jsliang is printed.

Of course, we need to be self-aware:

  • Case 2
let myObj = {
  myName: 'jsliang'.showThis: function() {
    console.log(this.myName); }};let foo = myObj.showThis;
foo(); // Output what?
Copy the code

At this point, let foo = myobj.showthis is just a definition that is actually implemented in foo(). So what’s going on with foo() now? Window. The foo ()! No doubt output undefined.

  • Case 3
let myObj = {
  name: 'jsliang'.showThis: function() {
    console.log(this.name); }};let foo = myObj.showThis;
foo(); // Output what?
Copy the code

Normally, the output of this code should be undefined.

Note here, however, that window.name is the name of the current window, which is the value of the second argument to the window.open() method that opens a new page.

So window.name is a null value, or the name of the window that currently exists.

Jsliang uses an example to show how this comes about:

index.html

<! DOCTYPEhtml>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="Width = device - width, initial - scale = 1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>jsliang</title>
</head>
<body>
  <button class="btn">Open a new page</button>

  <script>
    (function() {
      const btn = document.querySelector('.btn');
      btn.onclick = function() {
        window.open('index.html'.'Jsliang webpage');
      }
    })()
  </script>
</body>
</html>
Copy the code

In the console of the newly opened page, type window.name to get the jsliang page.

Conclusion:

  • Call a function in the global environmentthisIt points to a global variablewindow.
  • To call a method within an object in the execution context of that methodthisPoint to the object itself.

4.3 Using the constructor

Returns the directory

this.name = 'jsliang';
let Foo = function() {
  this.name = 'zhazhaliang';
}
let foo = new Foo();
console.log(foo.name); // Output what?
console.log(window.name); // Output what?
Copy the code

The answer is:

  • zhazhaliang
  • jsliang

Before giving the answer, let’s take a look at what the JavaScript engine does in new Foo() :

  • Start by creating an empty objecttempObj = {}.
  • Then callFoo.applyMethods,tempObjAs aapplyMethod, so whenFooThe execution context is created when it isthisJust point totempObjObject.
  • Then performFooDelta function, at this pointFooIn the context of function executionthisPoints to thetempObjObject.
  • The last returntempObjObject.
function myNew(func, ... args) {
  const tempObj = {};
  func.apply(tempObj, args);
  return tempObj;
}

this.name = 'jsliang';
let Foo = function(name, age) {
  this.name = name;
  this.age = age;
}
let foo = myNew(Foo, 'zhazhaliang'.25);
console.log(foo.name); // Output what?
console.log(foo.age); // Output what?
console.log(window.name); // Output what?
Copy the code

As shown above, we can see that this belongs to the tempObj and is bound to foo to get:

  • zhazhaliang
  • 25
  • jsliang

Of course, we should improve the new handwriting method, so as not to mislead the friends that new does that kind of thing:

function myNew(func, ... args) {
  // 1
  if (typeoffunc ! = ='function') {
    throw 'The first argument must be the method body';
  }

  // 2. Create new objects
  const obj = {};

  // 3. The __proto__ of this object points to the protoobject of the func class
  // That is, the instance can access properties on the constructor. Prototype chain
  obj.__proto__ = Object.create(func.prototype);

  // Step 2 and Step 3 can be merged for compatibility with IE
  // const obj = Object.create(func.prototype);

  // 4. Bind this to apply and get the result
  let result = func.apply(obj, args);
  
  // 5. If the constructor returns a reference data type, return the result of the run
  // Otherwise return the newly created obj
  const isObject = typeof result === 'object'&& result ! = =null;
  const isFunction = typeof result === 'function';
  return isObject || isFunction ? result : obj;
}

/ / test
function Person(name) {
  this.name = name;
  return function() { // Test point 5
    console.log('Return reference data type');
  };
}
// Test points 2 and 3
Person.prototype.sayName = function() {
  console.log(`My name is The ${this.name}`);
}
const me = myNew(Person, 'jsliang'); // Test point 4
me.sayName(); // My name is jsliang
console.log(me); // Person {name: 'jsliang'}

// Test point 1
// const you = myNew({ name: 'jsliang' }, 'jsliang'); // Error: the first argument must be the method body
Copy the code

So we know what new is in the constructor.

This design defect and solution

Returns the directory

This in 5.1 nested functions does not inherit from outer functions

Returns the directory

var myObj = {
  myName: "jsliang".showThis: function(){
    console.log(this.myName); // Output what?
    function bar(){
      console.log(this.myName); // Output what?} bar(); }}; myObj.showThis();Copy the code

The answer is:

  1. jsliang
  2. undefined

Solution 1: PassthatcontrolthisPoint to the

var myObj = {
  myName: "jsliang".showThis: function(){
    console.log(this.myName); // Output what?
    let that = this;
    function bar(){
      console.log(that.myName); // Output what?} bar(); }}; myObj.showThis();Copy the code

So that’s jsliang output.

Solution 2: Use ES6’s arrow function to solve the problem

var myObj = {
  myName: "jsliang".showThis: function(){
    console.log(this.myName); // Output what?
    const bar = () = > {
      console.log(this.myName); // Output what?} bar(); }}; myObj.showThis();Copy the code

This is because the arrow function in ES6 does not create its own execution context, so the this in the arrow function depends on its external function, which is inherited from whoever calls it.

5.2 In ordinary functions, this refers to the global object Window

Returns the directory

In practice, we don’t want this in the execution context of a function to point to a global object by default, because that would break the boundaries of the data and cause some misoperations.

If you want this in the execution context of a function to point to an object, the best way to display the call is through the call method.

This problem can be solved by setting strict mode for JavaScript. In strict mode, the default execution of a function whose execution context this is undefined solves the above problem.

React this points to

Returns the directory

HandleClik = this.handleclick. bind(this);

Why do you do that?

Let’s start with a code comparison:

Code 1: The object calls this in the field

const test = {
  myName: 'jsliang'.getName: function() {
    console.log(this.myName); / / output jsliang}}; test.getName();Copy the code

Code 2: Put it in a global variable

const test = {
  myName: 'jsliang'.getName: function() {
    console.log(this.myName); / / output is undefined}};const func = test.getName;
func();
Copy the code

So the React method, if not bound, will refer to the global object Window.

So how to fix this problem?

Note: netizens pointed out: the following four methods of comparison is actually wrong, ordinary objects can not be compared with class

Of course, jsliang is still listed here

Concrete conclusion, I believe that when we review again in 202X, we will have the opportunity to gradually solve the inner doubts.

So, to avoid conflict, you can skip this chapter

6.1 Solution 1: Bind this in advance

Returns the directory

const test = {
  myName: 'jsliang'.getName: function() {
    console.log(this.myName); / / output jsliang}}; test.getName = test.getName.bind(test);const func = test.getName;
func();
Copy the code

Corresponding to React:

constructor (props) {
  this.handleClick = this.handleClick.bind(this);
}
<button onClick={this.handleClick}>btn 1</button>
Copy the code

6.2 Solution 2: Bind this when called

Returns the directory

const test = {
  myName: 'jsliang'.getName: function() {
    console.log(this.myName); / / output jsliang}};const func = test.getName.bind(test);
func();
Copy the code

Corresponding to React:

<button onClick={this.handleClick.bind(this)}>btn 2</button>
Copy the code

6.3 Solution 3: Return an arrow function

Returns the directory

const test = {
  myName: 'jsliang'.getName: function() {
    console.log(this.myName); / / output jsliang}};const func = () = > test.getName();
func();
Copy the code

Corresponding to React:

<button onClick={() = > this.handleClick()}>btn 3</button>
Copy the code

6.4 Solution 4: Turn the calling method into an arrow function (failed)

Returns the directory

const test = {
  myName: 'jsliang'.getName: () = > {
    console.log(this.myName); }};const func = test.getName;
func();
Copy the code

Corresponding to React:

handleClick2 = () = > {
  console.log('jsliang 2021');
}
<button onClick={this.handleClick2}>btn 4</button>
Copy the code

However, this method fails and returnsundefinedWhat’s the reason?

Netizens pointed out:

  • The comparison of these four methods is actually wrong. Ordinary objects cannot be compared to classes

Of course, Jsliang still wants to list out the specific conclusions, I believe that there will be an opportunity to gradually solve the inner doubts.

6.5 React This points to the actual content

Returns the directory

class Toggle extends React.Component {
  constructor(props) {
    super(props);
    this.state = {isToggleOn: true};

    // This binding is necessary in order to use 'this' in callbacks
    // this.handleClick = this.handleClick.bind(this);
  }
  handleClick() {
    console.log(this);
  }
  render() {
    return (
      <button onClick={this.handleClick}>
        {this.state.isToggleOn ? 'ON' : 'OFF'}
      </button>
    );
  }
}

ReactDOM.render(
  <Toggle />.document.getElementById('root'));Copy the code

Given the above method, compile it into:

"use strict";

/ /... The code is omitted

var Toggle = /*#__PURE__*/function (_React$Component) {
  _inherits(Toggle, _React$Component);

  var _super = _createSuper(Toggle);

  function Toggle(props) {
    var _this;

    _classCallCheck(this, Toggle);

    _this = _super.call(this, props);
    _this.state = {
      isToggleOn: true
    }; // This binding is necessary in order to use 'this' in callbacks
    // this.handleClick = this.handleClick.bind(this);

    return _this;
  }

  _createClass(Toggle, [{
    key: "handleClick".value: function handleClick() {
      console.log(this); // The output is undefined}}, {key: "render".value: function render() {
      return /*#__PURE__*/React.createElement("button", {
        onClick: this.handleClick
      }, this.state.isToggleOn ? 'ON' : 'OFF'); }}]);return Toggle;
}(React.Component);
Copy the code

The _createClass method takes the created class as its first argument and an array of methods in the created class as its second argument.

Obviously, handleClick’s output of this must be undefined.

The Render method returns the React. CreateElement, in which this is referred to the first argument to the _createClass method, which is Toggle.

In this case, if the method becomes the arrow function:

handleClick = () = > {
  console.log(this);
}
Copy the code

The arrow function is the context in which this is defined.

When a button is clicked, the handleClick method is called to handle the event, and the handleClick method is defined in the Toggle method, so this refers to the Toggle class.

6.6 React This points to a solution

Returns the directory

import React, { Component } from 'react'

class App extends Component {
  constructor (props) {
    super(props);
    this.handleClick = this.handleClick.bind(this);
  }
  handleClick () {
    console.log('jsliang 2020');
  }
  handleClick2 = () = > {
    console.log('jsliang 2021');
  }
  render () {
    // There are four binding methods
    return (
      <div className='App'>{/* Bind from constructor */}<button onClick={this.handleClick}>btn 1</button>{/* bind this */}<button onClick={this.handleClick.bind(this)}>btn 2</button>{/* Method 3: return event via arrow function */}<button onClick={()= > this.handleClick()}>btn 3</button>{/* method 4: turn method into arrow function */}<button onClick={this.handleClick2}>btn 4</button>} {this.handleclick ()} {this.handleclick ()}</div>)}}export default App;
Copy the code

Seven summary

Returns the directory

Remember one sentence:

  • thisAlways point to the object that called it last

Two more things to remember:

  • In ordinary functionsthisTheta points to theta, yesthis Execution timeThe context in which the
  • In the arrow functionthisTheta points to theta, yesthis To define theThe context in which the

Eight topics

Returns the directory

8.1 This topic analyzes 5 steps

Returns the directory

  • The first question
var name = 'window name';
function a() {
  var name = 'jsliang';
  console.log(this.name); // Output what?
  console.log('inner:' + this); // Output what?
}
a();
console.log('outer:' + this); // Output what?
Copy the code

What does this code output?


The answer:

Window name Inner: window name Outer: window nameCopy the code

A () a() b () C () D ()

  • The second question
var name = 'window name';
var a = {
  name: 'jsliang'.fn: function () {
    console.log(this.name); // Output what?
  }
}
a.fn();
Copy the code

What does this code output?


Answer: jsliang

Now it’s a.fin (), so this points to a, so jsliang is printed

  • The third question
var name = 'window name';
var a = {
  // name: 'jsliang',
  fn: function () {
    console.log(this.name); // Output what?
  }
}
a.fn();
Copy the code

What does this code output?


Answer: undefined

A. a () = ‘a’; a.f () = ‘a’

  • The fourth question
var name = 'window name';
var a = {
  name: 'jsliang'.fn: function () {
    console.log(this.name); // Output what?}}var f = a.fn;
f();
Copy the code

What does this code output?


Answer: Window name

Var f = a.fein does not call a.fein. This is called at f(), where fn() is window.fn(), so it refers to window, so it prints window name

  • The fifth problem
var name = 'window name';
function fn() {
  var name = 'jsliang';
  function innerFn() {
    console.log(this.name);
  };
  innerFn();
}
fn();
Copy the code

Answer: Window name

Let’s see

8.2 let/const this

Returns the directory

let a = 10;
const b = 20;

function foo() {
  console.log(this.a);
  console.log(this.b);
}
foo();

console.log(window.a);
Copy the code

What does this code output?


Answer: undefined, undefined, undefined

If we change var to let or const, the variable will not be bound to the window, so we print three undefined variables.

8.3 Arrow function this

Returns the directory

var name = 'window name';

var a = {
  name: 'jsliang'.func1: function () {
    console.log(this.name);
  },
  func2: function () {
    setTimeout(() = > {
      this.func1();
    }, 100); }}; a.func1();// Output what?
a.func2(); // Output what?
Copy the code

What does this code output?


The answer:

jsliang
jsliang
Copy the code

This of the arrow function refers to this when the function is defined, not when it is executed. Arrow functions do not have the this binding, and its value must be determined by searching the scope chain. If the arrow function is contained by a non-arrow function, this is bound to the nearest non-arrow function’s this; otherwise, this is undefined.

8.4 Obtaining the output result

Returns the directory

function foo () {
  console.log(this.a)
};
var obj = { a: 1, foo };
var a = 2;
var foo2 = obj.foo;
var obj2 = { a: 3.foo2: obj.foo }

obj.foo(); // Output what?
foo2(); // Output what?
obj2.foo2(); // Output what?
Copy the code

What does this code output?


A:

1
2
3
Copy the code

Resolution:

  • obj.foo():objcallfoo(), so point toobjAnd the output1
  • foo2(): Actuallywindow.foo2()To point towindowAnd the output2
  • obj2.foo2():obj2callfoo2()To point toobj2And the output3

8.5 Implicit binding loss

Returns the directory

8.5.1 Obtaining the output result

Returns the directory

function foo() {
  console.log(this.a);
}
function doFoo(fn) {
  console.log(this);
  fn();
}
var obj = { a: 1, foo };
var a = 2;
doFoo(obj.foo); // Output what?
Copy the code

What does this code output?


Window {… 2},

Implicit binding loss problem. When obj.foo is passed, foo is not executed yet, so fn() equals window.fn() in doFoo, so it points to window.

Note that when called, it looks for fn in the window, not in doFoo, because doFoo does not set fn.

8.5.2 Obtaining the output result

Returns the directory

function foo() {
  console.log(this.a);
}
function doFoo(fn) {
  console.log(this);
  fn();
}
var obj = { a: 1, foo };
var a = 2;
var obj2 = { a: 3, doFoo };

obj2.doFoo(obj.foo); // Output what?
Copy the code

What does this code output?


Answer: {a: 3, doFoo: f}, 2

Resolution:

  1. At the moment offn()Call, find the location orwindow.foo()So the call will point towindow.
  2. Here,fn()It came in by passing in, not bydoFooIt’s there, so when you do itthisIs found in thefooThe defined position, in fact, is stillwindow.fn()
  3. How to correct this problem?
function foo() {
  console.log(this.a);
}
function doFoo(fn) {
  console.log(this);
  fn.call(this);
}
var obj = { a: 1, foo };
var a = 2;
var obj2 = { a: 3, doFoo };

obj2.doFoo(obj.foo);
Copy the code

8.6 Displaying binding Problems

Returns the directory

8.6.1 Obtaining the output result

Returns the directory

function foo() {
  console.log(this.a);
}
var obj = { a: 1 };
var a = 2;

foo(); // Output what?
foo.call(obj); // Output what?
foo().call(obj); // Output what?
Copy the code

What does this code output?


The answer:

2
1
2
Uncaught TypeError: Cannot read property 'call' of undefined
Copy the code

Resolution:

  • foo(): point towindow
  • foo.call(obj)Will:foothisPoints to theobj
  • foo().call(obj): first performfoo()And the output2And then it does not return, which is equivalent toundefined.call(obj), directly report an error

8.6.2 Obtaining the output result

Returns the directory

function foo() {
  console.log(this.a);
  return function () {
    console.log(this.a);
  };
}
var obj = { a: 1 };
var a = 2;

foo(); // Output what?
foo.call(obj); // Output what?
foo().call(obj); // Output what?
Copy the code

What does this code output?


The answer:

2
1
2
1
Copy the code

3. The first three are the same as the above.

Return function {this.a}, so this method calls (obj), so output the a in obj, that is, 1.

8.7 Obtaining the Output Result

Returns the directory

function Foo() {
  'use strict'
  console.log(this.location);
}

Foo();
Copy the code

Please select:

  • A: Of the current windowLocationobject
  • B:undefined
  • C:null
  • D:TypeError

Answer: D

A. strict B. strict C. strict D. strict In strict mode, it is D, where the this keyword is prohibited from pointing to global objects.

8.8 in this paper, the problem

Returns the directory

let userInfo = {
  name: 'jsliang'.age: 25.sex: 'male'.updateInfo: function(){
    // Emulates the XMLHttpRequest request delay
    setTimeout(function(){
      this.name = "zhazhaliang"
      this.age = 30;
      this.sex = 'female';
    }, 1000); }}; userInfo.updateInfo();Copy the code

Solve the this pointing problem here and get the final result:

{
  name: "zhazhaliang".age: 30.sex: "female".updateInfo: function(),}Copy the code

SetTimeout (() => {})

Ix References

Returns the directory

  • 40 more of these interview questions continue[Reading Suggestions: 1H]
  • This,this, again,this in javascript, super comprehensive【 Reading Suggestions: 10min】
  • JavaScript in this【 Reading Suggestions: 10min】
  • JavaScript digs into this from the ECMAScript specification【 Reading Suggestions: 20min】
  • Front end foundation advanced (seven) : all-round interpretation of this【 Reading Suggestions: 20min】
  • JavaScript base method — this【 Reading Suggestions: 20min】
  • 11 | this: from the Angle of JavaScript execution context clear this【 reading Advice: 2hour】
  • Talk about this in React【 Reading Suggestions: 10min】
  • React performance optimization【 Reading Suggestions: 5min】
  • The React event handler must use bind(this) for reasons【 Reading Suggestions: 10min】
  • This caused by bind in the React constructor points to understanding why the React method binds this【 Reading Suggestions: 20min】
  • React this.handleclick = this.handleclick.bind (this) this points to the problem【 Reading Suggestions: 10min】

Jsliang’s document library is licensed by Junrong Liang under the Creative Commons Attribution – Non-commercial – Share alike 4.0 International License. Based on the github.com/LiangJunron… On the creation of works. Outside of this license agreement authorized access can be from creativecommons.org/licenses/by… Obtained.