1. Basic Concepts
- Neither to itself nor to lexical scope
- This is actually bound when the function is called, what does it refer to depending on where the function is called
Such as:
// call directly from the global scope
var name = 'hello world'
function foo() {
consoel.log(this.name)
}
foo() // 'hello world' this refers to window because function foo() is called in the global scope equivalent to window.foo().
// as a method call
function foo() {
console.log(this.name)
}
var obj = {
name: 'Ming'.foo: foo
}
obj.foo() // 'xiao Ming ', this refers to object obj, because foo() is called as a method of object obj
Copy the code
2. Call location
Before we understand the binding process for this, we need to understand the call location: the call location is where the function is called in code (not declared). Look at the following code:
function baz() {
// Current call stack: baz
// Function call location: global scope
console.log('baz')
bar() // where bar() is called
}
function bar() {
// Current call stack: baz > bar
// Function call location: scope of baz
console.log('bar')
foo() // where foo() is called
}
function foo() {
// Current call stack: baz > bar > foo
// Function call location: scope of bar
console.log('foo')
}
baz() // Call location of baz
Copy the code
3. Binding rules
3.1 Default Binding
function foo() {
console.log(this.a)
}
var a = 2
foo() / / 2
Copy the code
Foo () is called directly in the global scope, this refers to the global scope, and there is a declared variable a in the global scope, so this.a accesses variable A in the global scope
3.2 Implicit binding
function foo() {
console.log(this.a)
}
var obj = {
a: 2.foo: foo
}
obj.foo() / / 2
Copy the code
When a function references a context object, the implicit binding rule binds this in the function call to another context object. In the code above, when foo() is called, this is bound to obj, so this.a and obj.a are the same
Only the top or last level in the object attribute reference chain affects the call location, for example:Copy the code
function foo() {
console.log(this.a)
}
var obj2 = {
a: 42.foo: foo
}
var obj1 = {
a: 2.obj2: obj2
}
obj1.obj2.foo() / / 42
Copy the code
3.2.1 Implicit Loss
One of the most common problems with this binding is that implicitly bound functions lose the binding object, meaning that it applies the default binding, binding this to global or undefined, depending on whether it is in strict mode
function foo() {
console.log(this.a)
}
var obj = {
a: 2.foo: foo
}
var bar = obj.foo // Function alias
var a = 'hello world'
bar() // 'hello world'
Copy the code
Although bar is a reference to obj.foo, it actually refers to the foo function itself, so bar() at this point is really an undecorated function call, so it applies the default binding.
When a callback function is passed in
function foo() {
console.log( this.a );
}
function doFoo(fn) {
// fn actually refers to foo
fn(); // <-- call location!
}
var obj = {
a: 2.foo: foo
};
var a = "oops, global"; // a is an attribute of the global object
doFoo( obj.foo ); // "oops, global"
Copy the code
Argument passing is also an implicit assignment, so when we pass in a function we get an implicit assignment, so the result is the same as in the previous example
3.3 Displaying Binding
Bind this using call(), apply(), and bind().
function foo() {
console.log(this.a)
}
var obj = { a:2 }
foo.call( obj ) / / 2
Copy the code
- through
foo.call(...)
We can force this to point to Obj when calling foo - If a raw value is passed in (
String, number, bolean
) as the binding object for this, and the raw value is converted to object form. Often referred to as “boxing”
3.3.1 hard binding
Use call and apply
function foo() {
console.log(this.a)
}
var obj = {
a: 2
}
var bar = function() {
foo.call(obj)
}
bar() / / 2
setTimeout(bar, 100) / / 2
bar.call(window) / / 2
Copy the code
Bind this using the bind() function
function foo(something) {
console.log(this.a, something)
return this.a + something
}
var obj = {
a: 2
}
var bar = foo.bind(obj)
bar(3)
Copy the code
3.3.2 rainfall distribution on 10-12 new binding
Calling a constructor with the new operator goes through the following four steps:
- Create a new object
- Assigns the constructor’s scope to the new object (this refers to the new object)
- Execute the code in the constructor (add properties and methods for the new object)
- Return this new object
function foo(a) {
this.a = a
}
var bar = new foo(2)
console.log(bar.a) / / 2
Copy the code
When foo() is called with new, the this in foo() is bound to the bar object, so bar.a is actually this.a in foo()
4. Binding priority
Which has higher priority, implicit binding or explicit binding?
function foo() {
console.log(this.a)
}
let obj1 = {
a: 2.foo: foo
}
let obj2 = {
a: 3.foo: foo
}
obj1.foo.call(obj2) / / 3
obj2.foo.call(obj1) / / 2
Copy the code
As you can see from the code above, showing bindings takes precedence
Five, the summary
If you want to determine a running this binding with eucalyptus, you need to find where the function is called directly. Once found, we can apply the following four rules in sequence to determine the object bound to this
- by
new
Call? Bind to the newly created object - Called by call or apply(or bind)? Binds to the specified object
- Called by a context object? Bind that context object
- Default: in strict mode bound to
undefined
Otherwise, bind to the global object