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 object
obj
obj
The 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.- using
call
changethis
Point to show binding toobj
(call
The implementation of “is described below. - if
result
Is 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