In other words, only by mastering the usage of this in JS can we truly cross the threshold of JS.

What is this?

This refers to the object

You all remember the phrase “this always refers to the object that called it last.” This is the implicit binding rule, when the function is called first look to the left of the sign.

var cat = {
    name: "kitty",
    getName: function() {
        console.log(this.name);
    }
}
cat.getName(); // "kitty"
Copy the code

In order to avoid unnecessary trouble, this is the most common way. But as the woods get bigger, there are all kinds of birds, and we have to learn more about them so that we can cope with all kinds of changes.

This points to the window

What does this look like to point to the window?

Let’s make a small change to the above example

var cat = {
    name: "kitty",
    getName: function() {
        console.log(this.name);
    }
}
var realName = cat.getName;
realName(); // undefined
Copy the code

When this function is called, we can’t find any object. When this function is called, we can’t find any object. So what does this point to at this point? That’s window, and there’s no name property defined in the global, so we get undefined. If we specified the “use strict” mode in ES5, we would get an error:

Uncaught TypeError: Cannot read property 'name' of undefined
Copy the code

This when using the ES6 arrow function

To avoid the this problem in ES5, ES6 introduced the arrow function, whose this points to the object at the time of definition, not the runtime. Here’s an example:

var name = "miao";
var cat = {
    name: "kitty",
    getName: function() {
        console.log(this.name);
    },
    getArrowName: () => {
        console.log(this.name);
    }
}
cat.getName(); // "kitty"
cat.getArrowName(); // "miao"
Copy the code

Rule for this in ES6: Arrow functions have no 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

This for new

function getName(name) {
    this.name = name;
}
var newName = new getName("kitty");
console.log(newName.name); // "kitty"

Copy the code

The implementation principle of new

  • Create a new objectobj
  • objThe object of the__proto__Attribute points to the stereotype of the constructor, thus forming a stereotype chain. Specific constructors and prototype chain content can be linked to another article of mineTypeof & Instanceof && 23– Prototype inheritance and prototype chains.
  • usingcallchangethisPoint to show binding toobj(callThe implementation of “is described below.
  • ifresultIs the object type and is notnull, the returnresult
new getName("kitty") did this: (function(){
    var obj = {};
    obj.__proto__ = getName.prototype;
    var result = getName.call(obj,"kitty");
    return (typeof result === 'object'&& result) ? result : obj; }) ()Copy the code

This for call

I mentioned call, which can change the direction of this. Usage and presentation are as follows:

var cat = {
    name: "kitty",
    getAge: function(age, voice) {
        console.log(this.name + " is " + age + " years old. " + voice);
    },
}
cat.getAge(5, "miao"); // "kitty is 5 years old. miao"
var dog = {
    name: "blank"
}
cat.getAge.call(dog, 2, "wangwang") / /"blank is 2 years old. wangwang"
Copy the code

Call implementation principle

Draw key points: interview questions often test type, small book this note:

Function.prototype.newCall = function(content) {// An error is reported when a call passes in a null object, or some other type.if(typeof content === 'object') {
    content = content || window;
  } else{ content = Object.create(null); } content.fn = this; var keys = Array.from(arguments); var arg = keys.slice(1); content.fn(... arg); delete content.fn; } var cat = { name:"Kitty",
  getAge: function(age, voice) {
      console.log(this.name + " is " + age + " years old. " + voice);
  },
}
var dog = {
  name: "Blank"
}
cat.getAge.newCall(dog, 2, "wangwang");
Copy the code

This with apply

Call is a call with a different type of parameter:

var cat = {
    name: "kitty",
    getAge: function(age, voice) {
        console.log(this.name + " is " + age + " years old. " + voice);
    },
}
var dog = {
    name: "blank"
}
cat.getAge.apply(dog, [2, "wangwang"/ /])"blank is 2 years old. wangwang"
Copy the code

The implementation principle of Apply

Function.prototype.newApply = function(Content, params) {// An error is reported when a call passes in a null object, or some other type.if(typeof content === 'object') {
    content = content || window;
  } else{ content = Object.create(null); } content.fn = this; content.fn(... params); delete content.fn; } var cat = { name:"Kitty",
  getAge: function(age, voice) {
      console.log(this.name + " is " + age + " years old. " + voice);
  },
}
var dog = {
  name: "Blank"
}
cat.getAge.newApply(dog, [5, "wangwangwang"]);
Copy the code

This when using bind

Bind can also change the direction of this, but it returns a function:

var cat = {
    name: "kitty",
    getAge: function(age, voice) {
        console.log(this.name + " is " + age + " years old. " + voice);
    },
}
var dog = {
    name: "blank"
}
cat.getAge.bind(dog, 2, "wangwang") (); //"blank is 2 years old. wangwang"
Copy the code

The implementation principle of BIND

/ / use the ES6 Function extension of the operators. The prototype. NewBind =function(content, ... params) { var obj = this;return function(... otherParams) { obj.call(content, ... params, ... otherParams); } } var cat = { name:"Kitty",
  getAge: function(age, voice) {
      console.log(this.name + " is " + age + " years old. " + voice);
  },
}
var dog = {
  name: "Blank"
}
var newGetAge = cat.getAge.newBind(dog, 10, "wuwuwu")
newGetAge("wuwuwu");
Copy the code