It’s a cliche, nothing special. Keep the following notes for yourself and share them with those who haven’t made a summary yet
Several common scenarios
This in JavaScript represents the environment object in which the code is currently executing. The general distinction is what environment object this refers to when it appears in a function. The main scenarios are as follows:
- The function is called as a property of an object => whoever calls it
- Call the function directly => whoever the global is
- Function call scenarios for Call, apply, and bind => bind is whoever you bind
- The constructor call to the function => newly created object
Object property call
Everything can be a property of an object, and this refers to the object if the function is called as an object property.
var obj = {
name: 'six strange'.getName:function() {
console.log(this.name)
console.log(this === obj)
}
}
obj.getName() True / / 6
Copy the code
The getName function is called as a property of the obj object, where this inside the function refers to the object obj on which the function was called
Ordinary function calls
Execute a defined function directly, as if it were executed in the global environment, with this pointing to the window
var obj = {
name: 'six strange'.getName:function() {
console.log(this.name)
}
}
name = 'global'
var globalGetName = obj.getName
globalGetName() // global
Copy the code
The getName function is defined inside the obj object, but refers to obj. GetName with its new alias globalGetName, and then calls globalGetName like a normal function when this refers to the global object instead of the obJ object. Here involves some memory data structure management problems, details can go to see javascript this principle – Ruan Yifeng
Also consider the following code: inside the bound onClick event, the first this points to the object that is currently firing the event, and the event is fired as a property of the object. But the second this is executed inside an internally defined function, which is a normal call to the function, so this refers to a global object and has no id defined so it is undefined
// https://jsbin.com/bacixul/1/edit?html,console,output
<div id="app">click me !</div>
<script>
document.getElementById('app').onclick = function() {
console.log(this.id)// app
var myalert = function() {
console.log(this.id) // undefined
}
myalert()
}
</script>
Copy the code
The obvious solution to these scenarios is to save this in an intermediate variable.
//https://jsbin.com/tuvefus/edit?html,console,output
<div id="app">click me !</div>
<script>
document.getElementById('app').onclick = function() {
var that = this // Save this point
console.log(this.id)// app
var myalert = function() {
console.log(that.id) // Use that instead of this after the app
}
myalert()
}
</script>
Copy the code
You can also use the arrow function in ES6 to get around this problem
<div id="app">click me !</div>
<script>
document.getElementById('app').onclick = function() {
console.log(this.id)// app
var myalert = (a)= > { // Use the arrow function
console.log(this.id) // app
}
myalert()
}
</script>
Copy the code
call & apply & bind
All three of these apis are used to modify the this reference of function execution. Call and apply return the result of the function, and bind returns the function after this is pointed to.
Call and Apply simulate the implementation
The implementation of these two functions is almost the same, except that the way arguments are passed is different. Call is the sequence of incoming parameters, and apply is the list of incoming parameters.
// call
Function.prototype.myCall = function (context) {
// Get the object to bind
var context = context || window
// Add a property to the context to call the function
context.fn = this
// Take out the parameters after the context
var args = [...arguments].slice(1)
// Execute the function
varresult = context.fn(... args)/ / delete the fn
delete context.fn
return result
}
// apply
Function.prototype.myApply = function (context) {
var context = context || window
context.fn = this
var result
// Need to determine whether to store the second parameter
// If it exists, expand the second argument. The second argument is the argument array. The element is the argument list when the function is called
if (arguments[1]) { result = context.fn(... arguments[1])}else {
result = context.fn()
}
delete context.fn
return result
}
Copy the code
It can be seen that the implementation idea of Call and apply is to add the function to be executed as an attribute to the target object, and delete the attribute after execution, so that the execution of the function becomes the attribute call of the object, and this refers to the target object.
Bind simulation implementation
The implementation of bind can rely on either call or apply
Function.prototype.mybind = function(context) {
var self = this // save the original function
return function(){ // returns a new function that binds the context
return self.apply(context, arguments) // New functions can be treated as apply or call}}Copy the code
React binds this to method calls, such as onClick={this.handleclick.bind (this)}.
A constructor call to a function
The reference to this in a function construction call is really the process of understanding new. New is a constructor call that binds this to the new object generated by new. The new operator uses the following procedure:
- Create a brand new object
- This object will be executed
[[Prototype]]
The connection - This object is bound to the function call
this
- If the function returns no other object, then
new
The function call in the expression automatically returns the new object
var mynew = function() {
// 1 Creates a new object
var obj = Object.create(null)
// 2 Gets the function that needs to be constructed
var fn = [].shift.call(arguments)
// 3 prototype link
// obj.__proto__ = fn.prototype
obj = Object.setPrototypeOf(obj,fn.prototype)
// 4 Bind this to execute the constructor
var res = fn.apply(obj, arguments)
// 5 Returns the generated object
return typeof res === 'object' ? res : obj
}
Copy the code