Objects and constructors in JS, This pointing and binding methods, closures, synchronous and asynchronous, micro-tasks and macro-tasks

Table of contents

1. Objects and Constructors

1. What is the object

2. Constructor

Two, This pointing and binding method

1.This orientation

1.1. The meaning of this

1.2. Usage scenarios

2. Binding This method

Function.prototype.call()

Function.prototype.apply()

Function.prototype.bind()

3. Closure

1. Concept

2. Points to note when using closures

 4. Synchronous and asynchronous

1. Synchronization

2. Asynchronous

5. Macro tasks and micro tasks

1. Why should we distinguish between macro tasks and micro tasks?

2. Macro task

3. Microtasks


1. Objects and Constructors

1. What is the object

Object-oriented programming (Object Oriented Programming, abbreviated as OOP) is currently the mainstream programming paradigm. It abstracts various complex relationships in the real world into individual objects, and then completes the simulation of the real world through the division of labor and cooperation between objects.

Each object is a functional center with a clear division of labor and can complete tasks such as receiving information, processing data, and sending information. Objects can be reused and customized through the inheritance mechanism. Therefore, object-oriented programming has the characteristics of flexibility, code reusability, and high modularity, and is easy to maintain and develop. Compared with traditional procedural programming (procedural programming) consisting of a series of functions or instructions, it is more suitable for multi-person cooperation. Large software projects.

So, what exactly is an "object"? We understand it on two levels.

(1) An object is an abstraction of a single object.

A book, a car, and a person can all be objects, as can a database, a web page, and a remote server connection. When objects are abstracted into objects, the relationship between objects becomes the relationship between objects, so that the real situation can be simulated and programming for objects can be performed.

(2) An object is a container that encapsulates properties and methods.

Properties are the state of the object, and methods are the behavior of the object (accomplishing some kind of task). For example, we can abstract an animal into animalan object, use "attributes" to record which animal it is, and use "methods" to represent certain behaviors of animals (running, hunting, resting, etc.).

2. Constructor

The first step in object-oriented programming is to generate objects. As mentioned earlier, an object is an abstraction of a single entity. Usually a template is needed to represent the common characteristics of a certain type of object, and then the object is generated according to this template.

Typical object-oriented programming languages ​​(such as C++ and Java) have the concept of "class". The so-called "class" is the template of the object, and the object is the instance of the "class". However, the object system of the JavaScript language is not based on "classes", but on constructors and prototype chains.

The JavaScript language uses constructors as templates for objects. The so-called "constructor" is a function specially used to generate instance objects. It is the template of the object, describing the basic structure of the instance object. A constructor can generate multiple instance objects, all of which have the same structure.

A constructor is just an ordinary function, but with its own characteristics and usage.

There are two characteristics of the constructor.

  • The keyword is used inside the function body this, which represents the object instance to be generated.

  • When generating objects, newcommands must be used.

Example 1:

var Vehicle = function () {
  this.price = 1000;
};

var v = new Vehicle();       //使用new命令新生成一个实例v
v.price // 1000

Two, This pointing and binding method

1.This orientation

1.1. The meaning of this

thisKeywords are a very important grammatical point. It is no exaggeration to say that most development tasks cannot be accomplished without understanding its implications.

As mentioned in the previous chapter, thisit can be used in constructors to represent instance objects. In addition, thisit can also be used in other occasions. But no matter what the occasion, thisthere is one thing in common: it always returns an object.

Simply put, thisit is the object where the property or method "currently" resides.

Example 2:

var A = {
    name: '张三',
    describe: function () {
      return '姓名:'+ this.name;
    }
  };
  
  var name = '李四';
  var f = A.describe;
  console.info(f()) // "姓名:李四"
  console.info(A.describe())// "姓名:张三"

In the above code, name='Li Si' is defined under the window, and the describe method of A is assigned to the f variable, and then f() is called directly under the window. At this time, this will point to the top-level window, that is, window. name, that is, 'Li Si'.

When calling the describe method in class A, this will point to A, that is, A.name, that is, 'Zhang San'.

Since the properties of an object can be assigned to another object, the current object where the property is located is mutable, that is, the thispointer to is mutable.

1.2. Usage scenarios

(1) Global environment

Used by the global environment this, it refers to the top-level object window . That is, the f() function in Example 2 above

(2) Constructor

In the constructor this, it refers to the instance object. That is, this.price in example 1 above

(3) Object method

If the method of the object contains this, thisthe pointer to is the object where the method is running. Assigning this method to another object will change thisthe pointer.

Example 3:

var obj ={
  foo: function () {
    console.log(this);
  }
};

obj.foo() // obj

// 情况一
(obj.foo = obj.foo)() // window
// 情况二
(false || obj.foo)() // window
// 情况三
(1, obj.foo)() // window

In the above code, when the first obj.foomethod is executed, its internal thispointer obj. But in the above three cases, this points to window.

In the above code, obj.fooit is a value. When this value is actually called, the operating environment is no longer obj, but the global environment, so thisit no longer points to it obj.

It can be understood that inside the JavaScript engine, objand obj.foostored in two memory addresses, called address one and address two. obj.foo()When calling in this way, address 2 is called from address 1, so the operating environment of address 2 is address 1, thispointing to obj. However, in the above three cases, the address 2 is directly taken out and called. In this case, the operating environment is the global environment, so it thispoints to the global environment.

(4) Arrow function

The this in the arrow function is bound when the function is defined, not when the function is executed . If the arrow function is in a simple object , since the simple object has no execution context, this points to the upper-level execution context; if the arrow function is in an environment with an execution context such as a function or class , then this points to the current function or class.

var code = 404;
let obj = {
    code: 200,
    getCode: () => {
    	console.log(this.code);
    }
}
obj.getCode(); // 404

In arrow functions, the value of this is determined when the function is defined, not at runtime. In this example, the arrow function getCode is created when the object obj is defined, not when obj.getCode() is called.

The this in the arrow function points to the this value of the outer lexical scope, not to the object that called it. In the global scope, this refers to the global object (usually the window object in a browser environment). So, when this.code is used in an arrow function, it is actually referring to the code variable in the global scope, which has a value of 404.

 Since the obj common object is defined globally, this points to window

2. Binding This method

thisThe dynamic switching of , of course, creates great flexibility for JavaScript, but it also makes programming difficult and ambiguous. Sometimes, it is necessary to thisfix it to avoid unexpected situations. JavaScript provides call, apply, bindthese three methods to switch/fix thisthe pointing.

Function.prototype.call()

func.call(thisValue, [arg1], [arg2], [...])

The method of a function instance call, you can specify the internal thispointer of the function (that is, the scope where the function is executed), and then call the function in the specified scope

Example 4:

var obj = {};

var f = function () {
  return this;
};

f() === window // true
f.call(obj) === obj // true

In the above code, fwhen the function is run in the global environment, thisit points to the global environment (the browser is windowan object); callthe method can change thisthe pointing, specify thisthe pointing object obj, and then objrun the function in the scope of the object f.

callThe method parameter, which should be an object. If the parameter is empty, nulland undefined, the global object is passed in by default.

If callthe parameter of the method is an original value, the original value will be automatically converted into the corresponding wrapper object, and then passed into callthe method.  

Function.prototype.apply()

func.apply(thisValue, [arg1, arg2, ...])

applyThe function of the method callis similar to the method, which is to change thisthe pointer and then call the function. The only difference is that it receives an array as a parameter when the function is executed  

Function.prototype.bind()

func.call(thisValue, [arg1], [arg2], [...])

bind()Methods are used to bind a function body thisto an object and then return a new function.

Example 5:

var A = {
    name: '张三',
    describe: function () {
      return '姓名:'+ this.name;
    }
  };
  
  var name = '李四';
  var f = A.describe;
  console.info(f()) // "姓名:李四"
  console.info(A.describe())// "姓名:张三"
  var pname=A.describe.bind(A)
  console.info(pname()) // "姓名:张三"

We follow the above example, we assign the A.describe method to the pname variable in the same way as the f variable, and then call pname() directly, but this time we add the bind method and point this to Fixed in A, call the pname() function at this time, the return is still 'Zhang San'.

bind()It can also accept more parameters, and bind these parameters to the parameters of the original function.

Example 6:

var add = function (x, y) {
  return x * this.m + y * this.n;
}

var obj = {
  m: 2,
  n: 2
};

var newAdd = add.bind(obj, 5);
newAdd(5) // 20

In the above code, bind()in addition to binding the object, the method thisalso binds add()the first parameter of the function to , and then returns a new function , which can run as long as it accepts one more parameter.  x5newAdd()y

3. Closure

1. Concept

A function is bundled with references to its surrounding state (lexical environment, lexical environment) (or the function is surrounded by references), such a combination is a closure (closure). That is, closures allow you to access the scope of an outer function from within an inner function. In JavaScript, whenever a function is created, a closure is created at the same time the function is created.

In JS, generally speaking, a closure is a function that can read the internal variables of the outer function .

Global variables can be read inside the function, and local variables inside the function cannot be read outside the function

Example 7:

a=400
function f1() {
    let code = 200;

    function f2() {
        console.log(code);
    }

    return f2;
}
function f3(){
    console.log(a)
}

console.info(f3()) //400,函数内部可以读取全局变量
console.info(code) //undefined,函数外部无法读取函数内部的局部变量
console.info(f1()())  // 200,函数f1内部的函数f2可以读取f1中所有的局部变量。因此,若想在外部访问                    
                      //函数f1中的局部变量`code`,可通过函数f2间接访问。

The function f2 in 1.2 is a closure, and its function is to connect the inside of the function with the outside of the function.  

2. Points to note when using closures

1) Because the closure will make the variables in the function be stored in the memory, the memory consumption is very large, so the closure cannot be abused, otherwise it will cause performance problems of the web page, and may cause memory leaks in IE. The solution is to delete all unused local variables before exiting the function.

2) The closure will change the value of the variable inside the parent function outside the parent function. So, if you use the parent function as an object (object), the closure as its public method (Public Method), and the internal variable as its private property (private value), then you must be careful not to Feel free to change the value of the variable inside the parent function.

 4. Synchronous and asynchronous

1. Synchronization

Synchronous (Synchronous): In synchronous code execution, the code will be executed sequentially from top to bottom, and the next line of code will not be executed until each line of code is executed. In synchronous execution, if an operation takes a long time (such as a network request or a file read), the entire code execution will be blocked until the operation is completed, and the next line of code will not be executed. This execution method makes the code simple and easy to read, but it may also cause the program to stall when waiting for I/O operations for a long time, degrading the user experience.

Example 8:

console.log("Start");
console.log("Step 1");
console.log("Step 2");
console.log("End");

The four statements in the above code console.logwill be executed sequentially, and the next statement will not be executed until the previous statement is executed.

2. Asynchronous

Asynchronous: In asynchronous code execution, certain tasks are deferred until later rather than executed immediately. Asynchronous code usually involves operations that need to wait, such as network requests, file reading, timers, etc. When encountering these asynchronous operations, JavaScript continues to execute subsequent code instead of waiting for the asynchronous operation to complete. When the asynchronous operation is completed, the corresponding callback function is triggered or the bound event handler is executed.

Example 9:

console.log("Start");
setTimeout(function() {
  console.log("Async Task Done");
}, 2000);
console.log("End");

In the above code, setTimeoutthe function sets a 2-second timer, which will execute the callback function after 2 seconds and output "Async Task Done". While the timer is waiting for 2 seconds, the code will continue to execute subsequent console.log("End")statements.

5. Macro tasks and micro tasks

1. Why should we distinguish between macro tasks and micro tasks?

(1) js is single-threaded, but it is divided into synchronous and asynchronous

(2) Both microtasks and macrotasks are asynchronous tasks, and they all belong to a queue

(3) Macro tasks are generally: script, setTimeout, setInterval, postMessage

(4) Micro-tasks: Promise.then ES6

(5) Execute synchronously and then asynchronously. When asynchronously encounters microtasks, execute the microtasks first. After execution, if there are no microtasks, execute the next macrotask. If there are microtasks, execute the microtasks one by one in order

Sync > Microtasks > Macrotasks

2. Macro task

A macro task represents a group of asynchronous tasks, which usually include user interaction, timer events, network requests, etc. The execution of the macro task is carried out after all the tasks in the current execution stack are executed. During execution, if a new macro task is added, it will be queued at the end of the queue for execution.

Macro tasks are generally: script, setTimeout, setInterval, postMessage

3. Microtasks

A microtask represents a group of asynchronous tasks that execute after the execution of the current macrotask and before the start of the next macrotask. In other words, the execution priority of microtasks is higher than that of macrotasks. If microtasks are generated in a macrotask, then these microtasks will be executed immediately after the execution of the current macrotask.

Microtasks: Promise.then

Example 10:

//宏任务 放进队列
setTimeout(function(){
    console.log(1);
});
//微任务
new Promise(function(resolve){		    
    console.log(2);
    resolve();
}).then(function(){		    
    console.log(3);
}).then(function(){
    console.log(4)
}); 	
//同步代码
console.log(5);
// 2 5 3 4 1

This question may be misunderstood, thinking that 5 will be output first, but the order in which promise and promise.then execute code is different

Encounter setTimout, asynchronous macro task, put it into the macro task queue
Encounter new Promise, the code executed by new Promise in the process of instantiation is synchronous, so output 2
Promise.then, asynchronous micro task, put it Put it into the microtask queue
Encounter a synchronization task console.log(5); output 5; the synchronization task in the main thread is executed
Take out the task from the microtask queue to the main thread, output 3, 4, the microtask queue is
empty Take out tasks from the macro task queue and send them to the main thread, output 1, and the macro task queue is empty

Guess you like

Origin blog.csdn.net/CQ17743254852/article/details/131946281