In most common programming languages, this is the keyword (self is used in Objective-C)
In common object-oriented programming languages, such as Java, C++, Swift, Dart, and a host of others, this usually only appears in class methods.
That is, you need to have a class in which methods (especially instance methods) in which this represents the object being called
However, the value of this in JS is much more diverse and flexible
The effect of this
// Every method on this object wants to get obj.name when called
// However, if we change obj to foo, it means that we need to change the function internally, which is very inconvenient
var obj = {
name: "klaus".running: function() {
console.log(obj.name + " running");
},
eating: function() {
console.log(obj.name + " eating");
},
studying: function() {
console.log(obj.name + " studying"); }}Copy the code
// At this point we can use this instead
// this represents the caller of the current method
var obj = {
name: "klaus".running: function() {
console.log(this.name + " running");
},
eating: function() {
console.log(this.name + " eating");
},
studying: function() {
console.log(this.name + " studying"); }}Copy the code
Binding rules
By default, this refers to the current caller, so the value of this is only known at runtime
At compile time, there is no way to get the value of this
The basic rule
The default rules
Independent function calls can be understood as functions that are not bound to an object to be called
This is the default
// Independent function calls can be divided into the following three cases
// 1. Plain function calls
function foo() {
console.log(this); // => window
}
foo();
// --------------------------------------------------
// 2. Function call chain
// 2.
function test1() {
console.log(this); // => window
test2();
}
function test2() {
console.log(this); // => window
test3()
}
function test3() {
console.log(this); // => window
}
test1();
// --------------------------------------------------
// 3. Functions are passed as arguments
function foo(func) {
func()
}
function bar() {
console.log(this); // => window
}
foo(bar);
Copy the code
Implicit binding
The function is called by an object,
This is the name of the current function
// 1. Call a function from an object
function foo() {
console.log(this); // => object obj
}
var obj = {
name: "klaus".foo: foo
}
obj.foo();
// --------------------------------------------------
// 2. Chain calls to objects
function foo() {
console.log(this); // => object obj
}
var obj1 = {
name: "obj1".foo: foo
}
var obj2 = {
name: "obj2".obj1: obj1
}
obj2.obj1.foo(); // <=> const tmp = obj2.obj1; tmp.foo();
Copy the code
According to the binding
Call and apply methods
function foo() {
console.log(this);
}
foo.call(window); // window
foo.call({name: "klaus"}); // => {name: "klaus"}
// The first argument to call and apply is an object. If it is not an object, it is implicitly converted to an object before this is modified
// The difference between call and apply:
Call (this, param1, param2,...); // Call (this, param1, param2,...);
// Apply (this, [param1, param2,....); // Apply (this, param1, param2,....)
foo.call(123); // Number{ [[PrimitiveValue]] }
// --------------------------------------------------
/ / the bind method
function foo() {
console.log(this);
}
var obj = {
name: "klaus"
}
// The bind method returns a new method in which this is modified
// This is the biggest difference from call and apply, which modify this directly and call the function immediately
// bind modifies this and returns a new function, not called immediately
var bar = foo.bind(obj);
bar(); // => object obj
Copy the code
Built-in function
setTimeout(function() { // => setTimeout, serInterval this is the window
console.log(this); // => window
}, 1000);
// --------------------------------------------------
var names = ["abc"."cba"."nba"];
names.forEach(function(item) { // => array callback functions (forEach,filter,map...) This in is window
console.log(this); // => window x 3
});
var names = ["abc"."cba"."nba"];
var obj = {name: "klaus"};
names.forEach(function(item) {
console.log(this); // => obj object x 3
}, obj); // => The array callback usually has a second argument that specifies the this value of the current callback
// --------------------------------------------------
var box = document.querySelector(".box");
box.onclick = function() { // This in the browser event is the DOM element object that triggers the event
console.log(this); // => box object
}
Copy the code
The new keyword
/ / create a Person
function Person(name) {
console.log(this); // => Person {}
this.name = name; // Person {name: "klaus"}
}
1. Create a brand new object; 2. Refer this to this object 3. Execute the corresponding code in constructor 4. Return this object */
var p = new Person("klaus");
console.log(p); Person {name: "Klaus "} => Person {name:" Klaus "} =
Copy the code
Rule priority
New Binding > Show Binding > Implicit Binding > Default binding
function foo() {
console.log(this);
}
var obj1 = {
name: "obj1".foo: foo
}
var obj2 = {
name: "obj2".foo: foo
}
Implicit binding and display binding exist at the same time, and display binding has higher priority
obj1.foo.call(obj2); // => obj2 objects
// <=> const tmp = obj1.foo; tmp.call(obj2);
Copy the code
function foo() {
console.log(this);
}
var obj = {
name: "klaus".foo: foo
}
new obj.foo(); // => foo object
// <=> const tmp = obj.foo; new tmp();
Copy the code
function foo() { console.log(this); }var obj = { name: "obj"}// The new keyword takes precedence over the bind function var bar = foo.bind(obj); var foo = new bar(); / / / / = > foo object -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- the function foo () {the console. The log (this); Var foo = new foo.call(obj); var foo = new foo.call(obj); // error
Copy the code
Exception to the rule
Ignoring to show bindings
If we pass null or undefined in the display binding, the display binding is ignored, using the default rule
function foo() { console.log(this); }var obj = { name: "klaus"}foo.call(obj); // => obj object foo.call(null); // => windowfoo.call(undefined); // => windowvar bar = foo.bind(null); bar(); // => window
Copy the code
Indirect function reference
function foo() { console.log(this); }var obj1 = { name: "obj1".foo: foo}; var obj2 = { name: "obj2"}obj1.foo(); Num1 = num2 = 2*/(obj2.foo = obj1.foo)(); // => window (obj2.foo = obj1.foo)() <=> foo()// obj2.foo = obj1.foo => The result is the reference address of the function foo
Copy the code
Arrow function
The arrow function in ES6 does not have this inside; it determines this based on the outer scope.
// ES5var obj = { data: [], getData: function() { var _this = this; SetTimeout (function() {var res = [" ABC ", "CBA "," NBA "]; _this.data.push(... res); }, 1000); }}obj.getData(); // ------------------------------------------------// ES6var obj = { data: [], getData: Function () {setTimeout(() => {function() {setTimeout() => {function() {setTimeout() => {function() {setTimeout() => { Var res = [" ABC ", "CBA "," NBA "]; this.data.push(... res); }, 1000); }}obj.getData();
Copy the code
The interview questions
var name = "window";var person = { name: "person".sayName: function () { console.log(this.name); }};function sayName() { var sss = person.sayName; sss(); // => window person.sayName(); // => person (person.sayName)(); // => person (b = person.sayName)(); // => window}sayName();
Copy the code
var name = 'window'var person1 = { name: 'person1'.foo1: function () { console.log(this.name) }, foo2: () = > console.log(this.name), foo3: function () { return function () { console.log(this.name) } }, foo4: function () { return () = > { console.log(this.name) } }}var person2 = { name: 'person2' }person1.foo1(); // => person1person1.foo1.call(person2); // => person2person1.foo2(); // => windowperson1.foo2.call(person2); // => windowperson1.foo3()(); // => windowperson1.foo3.call(person2)(); // => windowperson1.foo3().call(person2); // => person2/* var person1 = { name: 'person1', foo4: function () { // 2. Go one level above the arrow function, in person1.foo4(), Return () => {// 1.person1.foo4 ()() => There is no this console.log(this.name)}}}*/person1.foo4()(); // => person1person1.foo4.call(person2)(); // => person2person1.foo4().call(person2); // => person1
Copy the code
var name = 'window'function Person (name) { this.name = name this.obj = { name: 'obj'.foo1: function () { return function () { console.log(this.name) } }, foo2: function () { return () = > { console.log(this.name) } } }}var person1 = new Person('person1')person1.obj.foo2()() Obj object // person1.obj.foo2() returns the arrow function, so the upper level is the person1.obj.foo2 method, in which case this is person1.obj
Copy the code