[JavaScript] advanced tutorial under construction~

Posted by sulen on Thu, 24 Feb 2022 03:43:46 +0100

1, Prototype and original chain

prototype

1. prototype attribute of function

Each function has a prototype attribute. By default, it points to an empty Object (that is, a prototype Object)

There is a property constructor in the prototype object, which points to the function object

2. Add attributes (usually methods) to prototype objects

Function: all instance objects of the function automatically own the properties (Methods) in the prototype

// Each function has a prototype attribute. By default, it points to an empty Object (that is, a prototype Object)
console.log(Date.prototype, typeof Date.prototype);
function fun(){
    
}

console.log(fun.prototype);// By default, it points to an object empty object (there is no attribute defined by us)

// There is a property constructor in the prototype object, which points to the function object
console.log(Date.prototype.constructor === Date); // true
console.log(fun.prototype.constructor === fun); // true

// Add attributes (usually methods) to prototype objects - > instance objects can be accessed
fun.prototype.test = function() {
    console.log('test Prototype object addition');
}
var f = new fun();
f.test(); // test prototype object addition

Explicit prototype and implicit prototype

Each function has a prototype, that is, an explicit prototype attribute, which points to an empty object by default

Each instance object has one_ proto_ , It can be called implicit prototype

The value of the implicit prototype of an object is the value of the explicit prototype of its corresponding constructor

function Fn(){ // Inner statement: this prototype = {}
    
}
// Each function has a prototype, that is, an explicit prototype attribute, which points to an empty object by default
console.log(Fn.prototype);
// Each instance object has one__ proto__.  It can be called implicit prototype
var fn = new Fn(); // Inner statement: this__ proto__ =  Fn. prototype
console.log(fn.__proto__);
// The value of the implicit prototype of the object is the value of the display prototype of its corresponding constructor
console.log(Fn.prototype === fn.__proto__);// true
// Adding methods to prototype objects
Fn.prototype.test = function(){
    console.log('Adding methods to prototype objects')
}
fn.test()

Function prototype attribute: automatically added when defining a function. The default value is an empty Object object

Object__ proto__ Property: automatically added when creating an object. The default value is the prototype property value of the constructor

Programmers can directly manipulate explicit prototypes, but not implicit prototypes (before ES6)

Prototype chain

function Fn(){
    this.test1 = function(){
        console.log('test()');
    }
}
Fn.prototype.test2 = function(){
    console.log('test2()')
}

var fn = new Fn();
fn.test1();
fn.test2();

When accessing an object property,

​ First search in its own attributes, and return if found

​ If not, follow__ proto__ This line looks up and returns when it is found

​ If it is not found, return undefined

Prototype chain alias: implicit prototype chain

Purpose: find object attributes

Constructor / prototype / instance object relationship

1. The Object pointed to by the display prototype of the function: the default is an empty Object instance Object (but the Object is not satisfied)

2. All functions are instances of Function (including the Function itself)

3. Object is the end of the prototype chain

function Fn(){
    this.test1 = function() {
      console.log('test1()');
    }
  }

var fn = new Fn();

console.log(Fn.prototype instanceof Object); // true
console.log(Object.prototype instanceof Object); // false
console.log(Function.prototype instanceof Object); // true

// All functions are instances of Function (including the Function itself)
console.log(Function.__proto__ === Function.prototype); // true

// Object is the end of the prototype chain
console.log(Object.prototype.__proto__); // null

Prototype chain properties

1. When reading the object attribute value: it will be automatically found in the prototype chain

2. When setting the attribute value of an object: the prototype chain will not be found. If there is no such attribute in the current object, add the attribute and set the value directly

3. Methods are generally defined in the prototype, and attributes are generally defined on the object itself through the constructor

instanceof

How does instanceof judge

Expression: A instanceof B

If the display prototype object of B function object is on the prototype chain of A object, return true; otherwise, return false

Function is an instance generated by new itself

2, Execution context and execution context stack

Variable promotion and function promotion

// Output undefined
var a = 3;
function fn() {
    console.log(a);
    var a = 4;
}
fn();
// Within fn function, var a = 4; Actually equal to the following code
function fn() {
    var a; // var a here; Is variable promotion
    console.log(a); // Output defined here
    a = 4;
}

// fn2 the function can be called directly before it is declared through function. Function declaration promotion
fn2();
function fn2() {
    console.log('fn2()');
}

fn3(); // It cannot be called here, because the following belongs to variable promotion, not function promotion. Function promotion needs to be declared through function
var fn3 = function() {
    console.log('fn3()');
}

1. Variable declaration promotion

  • Variables defined (declared) by var can be accessed before defining statements
  • Value: undefined

2. Function declaration promotion

  • Functions declared through function can be called directly before
  • Value: function definition (object)

Execution context

Code classification (location)

Global code

Function (local) code

Global execution context

Determine the window as the global execution context before executing the global code

Preprocess global data

​ The global variable defined by var = = = "undefined" is added as the attribute of window

​ The global function declared by function = = = "is assigned (fun) and added as the method of window

Start executing global code

Function execution context

Before calling the function and preparing to execute the function body, create the corresponding function execution context object (virtual, existing in the stack)

Preprocess local data

​ Formal parameter variable = = = "assignment (argument) = = =" added as the attribute of execution context

​ arguments = = "assignment (argument list), added as execution context attribute

​ var defined local variable = = = "undefined", added as the attribute of the execution context

​ The function declared by function = = = "is assigned (fun) and added as the method of execution context

​ this = = = "assignment (object calling the function)

Start executing function body code

// Function execution context
function fn(a1) {
    console.log(a1); // 2
    console.log(a2); // undefined
    a3(); // a3()
    console.log(this); // Window, this is window, because the following call method is fn(2, 3)
    console.log(arguments); // Pseudo array (2,3)
    
    var a2 = 3;
    function a3() {
        console.log('a3()');
    }
}
fn(2, 3);

Execution Context Stack

Before global code execution, JS engine will create a stack to store and manage all execution context objects

After the global execution context (window) is determined, it is added to the stack (stack pressing)

After the function execution context is created, it is added to the stack (stack pressing)

After the current function is executed, the object at the top of the stack is removed (out of the stack)

When all the code is executed, only window is left in the stack

var a = 10;
var bar = function(x) {
    var b = ;
    foo(x + b);
}
var foo = function(y) {
    var c = 5;
    console.log(a + c + y); // The following figure does not consider the context of changing the print function
}
bar(10)

Examples

1,

/**
 * 1,What is output in turn?
 * 2,How many execution contexts are generated in the whole process?
 */
console.log('global begin:' + i);
var i = 1;
foo(1);
function foo(i) {
    if (i == 4) {
        return;
    }
    console.log('foo() begin:' + i);
    foo(i + 1); // Calling itself in function is called recursion.
    console.log('foo() end:' + i);
}
console.log('global end:' + i);

/**
1:
undefined
foo() begin:1
foo() begin:2
foo() begin:3
foo() end:3
foo() end:2
foo() end:1
global end:1

Each time you call yourself, you do not execute foo() end. After return ing in i == 4, the function will execute the remaining code one by one and get out of the stack, so execute foo() end at this time
*/

/**
2: Do not consider console log()
4 + 1 Times (4 times foo, 1 time global)
*/

2,

/**
 * 1
 */
function a() {}
var a;
console.log(typeof a); // Output: function. Because the variable is promoted first and then the function is promoted. The promoted function a() takes effect

/**
 * 2
 */
if (!(b in window)) { // b in window is true because var b is written, that is, variable promotion has been carried out
    var b = 1;
}
console.log(b); // undefined the following is the test code
if (false) {
	var b = 1;
}
console.log(b in window); // true

/**
 * 3
 */
var c = 1;
function c(c) {
    console.log(c);
}
c(2); // Error, c is not a function reason: first promote the variable, then the function, and finally execute the code.
// Equivalent to the following code, declare c first, assign a value to c before executing c(2) to make it a variable, not a function
var c;// Antecedent lifting
function c(c) { // After function promotion, it is executed when the function is promoted (execution does not mean call)
    console.log(c);
}
c = 1; // Perform assignment after variable promotion and function promotion
c(2);

3, Scope and scope chain

Scope

understand

Scope is a "territory", an area where code is short

It is static (relative to the context object) and is determined when writing code

classification

global scope

Function scope

No block scope (ES6 has)

effect

Isolate variables. Variables with the same name under different scopes will not conflict

if (true) {
  var a = 4; // a can also be accessed outside the braces, and the block scope without braces
}

// global scope
var a = 10,
  b = 20;
function fn(x) { // Function scope fn
  var a =100, // Variable isolation
    c = 300;
  console.log('fn()', a, b, c, x);
  function bar(x) { // Function scope bar
    var a = 1000, // Variable isolation
      d = 400;
    console.log('bar()', a, b, c, d, x);
  }

  bar(100);
  bar(200);
}
fn(10);

Scope and global context

difference

1,

Outside the global scope, each function will create its own scope, which has been determined when the function is defined. Not when a function is called

In the global execution context, after the global scope is determined, js code is created immediately before execution

When the function execution context environment is called, it is created before the function body code is executed

2,

The scope is static. As long as the function is defined, it will always exist and will not change

The execution context is dynamic. It is created when the function is called. When the function is called, the context will be released automatically

3,

The execution context (object) is subordinate to the scope in which it is located

Global context = = > global scope

Function context = = > corresponding function scope

Scope chain

understand

A chain formed by the scope of multiple parent-child relationships. Its direction is from bottom to top (from inside to outside)

Variables are found along the scope chain

Find rules for finding a variable

Find the corresponding attribute in the execution context under the current scope. If there is a direct return, otherwise enter 2

Find the corresponding attribute in the execution context of the upper level scope. If there is a direct return, otherwise enter 3

Perform the same operation of 2 again until the global scope. If it is not found, throw an exception that cannot be found (xxx is not defined)

var a = 1;
function fn1() {
  var b = 2;
  function fn2() {
    var c = 3;
    console.log(c); // 3
    console.log(b); // 2
    console.log(a); // 1
    console.log(d); // Error d is not defined
  }
  fn2();
}
fn1();

4, Closure

Example: realize the button cycle to listen for events. Click the corresponding button to pop up the first one

<body>
<button>Test 1</button>
<button>Test 2</button>
<button>Test 3</button>
<script type="text/javascript">
  var btns = document.getElementsByTagName('button');
  // Traversal plus listening
  /*
  This method cannot correctly pop up the value corresponding to the button, because i is a variable in the global scope. After the for loop binds the event, click the execute event function. In the function, i accesses the external global variable, and at this time, the value of i is the value after the loop
  for (var i = 0,lengths = btns.length; i < lengths; i++) {
    var btn = btns[i];
    btn.onclick = function() {
      alert('The '+ (i + 1) +' th ');
    }
  }*/
/*
  Save subscript to button
  for (var i = 0,lengths = btns.length; i < lengths; i++) {
    var btn = btns[i];
    btn.index = i; // Save the subscript corresponding to btn to btn
    btn.onclick = function() {
      alert('The '+ (this.index + 1) +' number ');
    }
  }*/

  // Using closures
  for (var i = 0,lengths = btns.length; i < lengths; i++) {
    (function(i) {
      var btn = btns[i];
      btn.onclick = function() {
        alert('The first' + (this.index + 1) + 'individual');
      }
    })(i);
  }
</script>
</body>

understand

How to generate closures?

Closure occurs when a nested inner (child) function references a variable (function) of a nested outer (parent) function

What is a closure?

Closures are nested internal functions that contain objects that are referenced by external variables (functions)

Conditions for generating closures?

The function is nested, and the internal function references the data of the external function (variable / function)

As shown in the above figure, you can view closures through the chrome debugging mode. Closure s are generated when the internal function definition is executed (not the calling function). To execute the internal function definition, you need to call the external function first, and you don't need to call the internal function.

Common closures

1. Take a function as the return value of another function

function fn1() {
    var a= 2;
    function fn2() {
        a++;
        console.log(a);
    }
    return fn2;
}
var f = fn1(); // A closure is generated by calling an external function here
f(); // Output 3
f(); // Output 4

2. Pass a function as an argument to another function call

function fn(msg, time) {
    setTimeout(function() {
        alert(msg);
    }, time);
}
fn('msg', 2000);

Function of closure

The variables inside the function still exist in memory after the function is executed (prolonging the declaration cycle of local variables)

Data (variable / function) that can be manipulated (read and write) outside the function to the inside of the function

// The following code extends the life cycle of variable A. when fn1 is executed, fn2 and fn3 generate closures. By returning fn2 or fn3 and receiving the call, the operation of adding or subtracting 1 to variable a can be realized, and no other operation can be performed on variable a except addition and subtraction.
function fn1() {
    var a = 2;
    function fn2() {
      a++;
      console.log(a);
    }
    function fn3() {
      a--;
      console.log(a);
    }
    return fn3;
  }
  var f = fn1();
f();

problem

1. After the function is executed, does the local variable declared inside the function still exist?

​ Generally, it does not exist. Only variables that exist in closures can exist

function fn1() {
    var a = 2;
    function fn2() {
      a++;
      console.log(a);
    }
    function fn3() {
      a--;
      console.log(a);
    }
    return fn3;
  }
  var f = fn1(); // fn1 will be released after the function is executed. Here, fn3 is returned, which is referenced by variable f. So the inner function fn3 is not released.
// fn1();  If there is no reference here, it will become a garbage object and be released after execution.
f();

2. Can local variables inside a function be accessed directly outside the function?

​ No, but we can let the outside operate it indirectly through closures. For example, as shown in the code above.

Closure lifecycle

1. Generate: generated when the nested internal function definition is executed (not called)

2. Death: when a nested inner function becomes a garbage object

function fn1() {
    // At this point, the closure has been generated (function promotion, internal function object has been created)
    var a = 2;
    function fn2() {
        a++;
        console.log(a);
    }
    return fn2;
}
var f = fn1();
f();
f();
f = null; // Closure death (function objects containing closures become garbage objects)

Application of closures: defining JS modules

JS module:

​ js files with specific functions

​ Encapsulate all data and functions inside a function (private)

​ Expose only one object or function containing n methods

​ The user of the module only needs to call the method through the exposed object of the module to realize the corresponding function

// myModule.js
function myModule() {
  // Private data
  var msg = 'My Module';
  // Functions that manipulate data
  function doSomethiing() {
    console.log('doSomething()', msg.toUpperCase());
  }
  function doOtherthing() {
    console.log('doOtherthing()', msg.toLowerCase());
  }

  // Expose objects outward (Methods for external use)
  return {
    doSomethiing: doSomethiing,
    doOtherthing: doOtherthing
  }
}
<!-- index.html -->
<!doctype html>
<html class="no-js" lang="">
<head>
  <meta charset="utf-8">
  <title></title>
</head>
<body>
</body>
<script type="text/javascript" src="js/myModule.js"></script>
<script type="text/javascript">
  var module = myModule();
  module.doSomethiing();
  module.doOtherthing();
</script>
</html>

On the other hand, assign the content to be exposed to the window. As follows:

(function myModule2() {
  // Private data
  var msg = 'My Module';
  // Functions that manipulate data
  function doSomethiing() {
    console.log('doSomething()', msg.toUpperCase());
  }
  function doOtherthing() {
    console.log('doOtherthing()', msg.toLowerCase());
  }

  // Expose objects to the outside (Methods for external use) objects to be exposed to the window
  window.myModule2 = {
    doSomethiing: doSomethiing,
    doOtherthing: doOtherthing
  }
})();
<!-- index.html -->
<!doctype html>
<html class="no-js" lang="">
<head>
  <meta charset="utf-8">
  <title></title>
</head>
<body>
</body>
<script type="text/javascript" src="js/myModule2.js"></script>
<script type="text/javascript">
  myModule2.doSomethiing();
  myModule2.doOtherthing();
</script>
</html>

Disadvantages of closures

1. Shortcomings

​ After the function is executed, the local variables in the function are not released, and the memory consumption time will become longer

​ Easy to cause memory leakage

2. Settle

​ You don't have to close it

​ Timely release

<script type="text/javascript">
function fn1() {
    var arr = new Array[10000000];
    function fn2() {
      console.log(arr.length);
    }
    return fn2;
  }
  var f = fn1();
  f();
  f = null; // Make internal functions garbage objects -- > recycle closures
</script>

supplement

out of memory

An error in the operation of a program

When the program needs more memory than the remaining memory, it will throw a memory overflow error

Memory leak

The occupied memory is not released in time

Memory leaks accumulate too much, which can easily lead to memory overflow

Common memory leaks:

​ Unexpected global variable

​ Timer or callback function not cleaned in time

​ closure

// Unexpected global variable
function fn() {
    a = new Array(100000000); // var is not used to define local variables, resulting in a becoming an unexpected global variable.
}
fn();

// Timer or callback function not cleaned in time
var intervalId = setInterval(function() {
    console.log('------------');
}, 1000); // The timer is not cleaned after use
// clearInteval(intervalId);

// closure
function fn1() {
    var a = 4;
    function fn2() {
        console.log('---', a);
    }
    return fn2;
}
var f = fn1();
f(); // Closure not cleaned after use
// f = null;

5, Object oriented advanced

Object creation mode

Mode 1: Object constructor mode

Routine: first create an empty Object object, and then dynamically add attributes / methods

Applicable scenario: uncertain object internal data at the beginning

Problem: too many statements

var p = new Object();
p.name = 'Tom';
p.age = 12;
p.setName = function(name) {
    this.name = name;
}

p.setName('JACK');
console.log(p.name, p.age);

Method 2: object literal mode

Routine: create objects with {} and specify properties / methods

Applicable scenario: at the beginning, the internal data of the object is determined

Problem: if you create multiple objects, there is duplicate code

var p = {
    name: 'Tom',
    age: 12,
    setName: function(name) {
        this.name = name;
    }
}

// test
console.log(p.name, p.age);
p.setName('JACK');
console.log(p.name, p.age);

var p2 = { // If you create multiple objects, the code is repetitive
    name: 'Bob',
    age: 13,
    setName: function(name) {
        this.name = name;
    }
}

Mode 3: factory mode

Routine: dynamically create objects through factory functions and return

Applicable scenario: multiple objects need to be created

Problem: objects don't have a specific type, they are all objects

function createPerson(name, age) {
    var obj = {
        name: name,
        age: age,
        setName: function(name) {
            this.name = name;
        }
    }
    return obj;
}

// Create two objects
var p1 = createPerson('Tom', 12);
var p2 = createPerson('Bob', 13);

function createStudent(name, price) {
    var obj = {
        name: name,
        price: price
    }
    return obj;
}
var s = createStudent('Zhang San', 12000);
// Here p1, p2 and s are also Object types. So the Object does not have a specific type.

Method 4: Custom constructor mode

Routine: Custom constructor, create object through new

Applicable scenario: you need to create multiple objects with certain types

Problem: each object has the same data, which wastes memory

// Define type
function Person(name, age) {
    this.name = name;
    this.age = age;
    this.setName = function(name) {
        this.name = name;
    }
}
var p1 = new Person('Tom', 13);
p1.setName('Jack');
console.log(p1.name, p1.age);
console.log(p1 instanceof Person);// true

function Studen(name, price) {
    this.name = name;
    this.price = price;
    this.setName = function(name) {
        this.name = name;
    }
}
var s1 = new Studen('KC', 1200);
s1.setName('KAKA');
console.log(s1.name, s1.price);
console.log(s2 instanceof Studen);// true here and quilted p1 have their own types

Mode 5: combination mode of constructor + prototype

Routine: Custom constructor, property initialized in function, method added to prototype

Applicable scenario: you need to create multiple objects with certain types

function Person(name, age) {
    this.name = name;
    this.age = age;
}
Person.prototype.setName = function(name) { // Put the method into the prototype
    this.name = name;
}

var p1 = new Person('Tom', 12);
var p2 = new Person('Bob', 13);
p1.setName('JACK'); // p1 and p2 have their own attributes, and the method is on the prototype. Their prototype is the same, so they share a method

Prototype chain inheritance

tricks:

​ Define a parent type constructor

​ Add a method to the prototype of the parent type

​ Defines the constructor for the subtype

​ Create an object of the parent type and assign it to the prototype of the child type

​ Set the constructor property of the subtype prototype to the bit subtype

​ Adding methods to subtype prototypes

​ Create sub type objects: you can call methods of the parent type

Key:

​ The prototype of the subtype is an instance object of the parent type

// Parent type
function Supper() {
    this.supProp = 'Supper property';
}
Supper.prototype.showSupperProp = function() {
    console.log(this.supProp);
}

// Subtype
function Sub() {
    this.subProp = 'Sub property';
}

// The prototype of the subtype is an instance object of the parent type
Sub.prototype = new Supper();
Sub.prototype.showSubProp = function() {
    console.log(this.subProp);
}
var sub - new Sub();
sub.showSupperProp();
sub.showSubProp();

Borrowing constructor inheritance (false)

tricks:

​ Define a parent type constructor

​ Define subtype constructor

​ Calling parent type constructor in subtype constructor

Key:

​ In the subtype constructor, call call() to call the parent type constructor.

function Person(name, age) {
    this.name = name;
    this.age = age;
}
function Student(name, age, price) {
    Person.call(this, name, age); // Equivalent to: this Person(name, age);
    this.price = price;
}

var s = new Student('Tom', 20, 10000);
console.log(s.name, s.age, s.price);

*Combinatorial inheritance

Combined inheritance of prototype chain + borrowing constructor

Using prototype chain to realize method inheritance of parent type object

Use super() to borrow the parent type to build the function to initialize the same attribute

function Person(name, age) {
    this.name = name;
    this.age = age;
}
Person.prototype.setName = function(name) {
    this.name = name;
}

function Student(name, age, price) {
    Person.call(this, name, age); // To get the parent type attribute
    this.price = price;
}
Student.prototype = new Person(); // In order to see the methods of the parent type
Student.prototype.constructor = Student; // Fix the contractor property
Student.prototype.setPrice = function(price) {
    this.price = price;
}

// test
var s = new Student('Tom', 24, 15000);
s.setName('Bob');
s.setPrice(11100);
console.log(s.name, s.age, s.price);

6, Thread mechanism and event mechanism

Process and thread

process

An execution of a program, which occupies a unique memory space

You can view the process through the window task manager

thread

A thread is an independent execution unit within a process

It is a complete process of program execution

It is the smallest scheduling unit of CPU

Relevant knowledge

The application cannot run on a thread of a process

There is at least one running thread in a process: the main thread, which is automatically created after the process is started

A process can run multiple threads at the same time. We will say that the program runs in multiple threads

The data in a process can be directly shared by multiple threads

Data between multiple processes cannot be shared directly

thread pool: a container for storing multiple thread objects to realize the repeated utilization of Thread objects

Related issues

What is multiprocessing and multithreading?

​ Multi process running: an application can start multiple instances at the same time

​ Multithreading: multiple threads run simultaneously in a process

Single thread and multi thread

​ Multithreading:

​ advantage:

​ It can effectively improve the utilization of CPU

​ Disadvantages:

​ Create multithreading overhead

​ Inter thread switching overhead

​ Deadlock and state synchronization

​ Single thread:

​ Advantages: sequential programming is simple and easy to understand

​ Disadvantages: low operation efficiency

Is JS single threaded or multi-threaded?

​ JS is single threaded

​ However, wokers can run in multiple threads through the web in H5

Is browser runtime multithreaded or single threaded?

​ Multithreading

Browser runtime single process or multi process?

​ Sometimes single process:

​ firefox, old IE

​ Sometimes multiple processes:

​ chrome, new IE

​ You can check the task manager of window when the program is running to determine whether it is a multi process or a single process

Browser kernel

The browser kernel is the core program that supports the operation of the browser

Different browsers may be different. For example, chrome and Safrai use webkit, firefox uses Gecko, IE uses Trident, and 360, Sogou and other domestic browsers use Trident+webkit

The kernel consists of many modules:

​ Main thread:

​ js engine module: responsible for compiling and running js programs

​ html and css document parsing module: responsible for parsing the page text

​ DOM / CSS module: responsible for the processing of DOM / CSS in memory

​ Layout and rendering module: responsible for the layout of the page and the rendering of the effect (objects in memory)

​ Split thread:

​ Timer module: responsible for timer management

​ DOM event response module: responsible for event management

​ Network request module: responsible for ajax request

​ Other modules:

Thinking caused by timer

Is the timer really timed?

​ Timers do not guarantee real timing

​ Generally, there will be a slight delay (acceptable range), but it may also be a long delay (unacceptable range)

Is the timer callback function executed in threads?

​ js is single threaded when executed by the main thread

How is the timer implemented?

​ Event cycle model

<button id='btn'>
    Start timer
</button>
<script type="text/javascript">
	document.getElementById('btn').onclick = function() {
        var start = Date.now();
        console.log('Before starting the timer...')
        setTimeout(function() {
            console.log('The timer is running', Date.now() - start);
        }, 200);
        console.log('After starting the timer...')
        
        // Following a long time will delay the timer for a long time (unacceptable range)
        for(var i = 0; i < 1000000; i++) { // Extended timer execution by long cycle
            
        }
    }
</script>

Single thread JS

1. How to prove that js execution is single threaded?

The callback function of setTimeout() is executed in the main thread

The timer returns to the function, which can be executed only after all the code in the run stack is executed

2. Why should js use single thread mode instead of multi thread mode?

The single thread of JavaScript is related to its purpose

As a browser scripting language, JavaScript is mainly used to interact with users to operate DOM

This determines that it can only be a single thread, otherwise it will bring complex synchronization problems

3. Classification of codes

setup code

callback code

4. The basic process of executing code by js engine

Execute initialization code first: contains some special code callback functions (asynchronous execution)

​ set timer

​ Binding event listening

​ Send ajax request

The callback code will be executed at a later time

setTimeout(function() {
    console.log('timeout 2000')
}, 2000);
setTimeout(function() {
    console.log('timeout 1000');
    alert('1000');
}, 1000);
setTimeout(function() {
    console.log('timeout 0');
}, 0);
function fn() {
    console.log('fn()');
}
fn();

console.log('alert()before');
alert('--------'); // Pause the execution of the current main thread and pause the timing at the same time. Click OK to resume the program execution and timer
console.log('alert()after');
/*
Execution sequence:
fn()
alert()before
 Pop up alert and click OK
alert()after
timeout 0
 One second later: timeout 1000
 alert 1000 pops up and click OK
 One second later: timeout 2000
*/

Event cycle model

1. All code categories

Initialization execution code (synchronization code): including the code for binding dom event listening, setting timer and sending ajax request

Callback execution code (asynchronous code): handles callback logic

2. Basic process code of js engine:

Initialization code = = > callback code

3. Two important components of the model:

Event (timer / DOM event / Ajax) management module

Callback queue

4. Operation process of model

Execute the initialization code and hand over the event callback function to the corresponding module for management

When the event is sent, the management module will add the function and its data to the callback queue

Only after the initialization code is executed (it may take some time), the callback function in the read callback queue will be traversed and executed

<button id='btn'>
    test
</button>
<script type="text/javascript">
	function fn1() {
        console.log('fn1()');
    }
    fn1();
    document.getElementById('btn').onclick = function() {
        console.log('Click btn');
    }
    setTimeout(function() {
        console.log('The timer is running');
    }, 2000);
    function fn2() {
        console.log('fn2()');
    }
    fn2();
</script>
<!--
Execution sequence:
fn1()
fn2()
The sequence of timer and button is uncertain
-->

Web Workers

H5 specification provides the implementation of js sub threading, which is called Web Workers

Related API:

​ Worker: constructor, which loads the js file executed by threads

​ Worker.prototype.onmessage: callback function used to receive another thread

​ Worker.prototype.postMessage: Send a message to another thread

Insufficient:

​ Code in Worker cannot operate DOM (update UI)

​ JS cannot be loaded across domains

​ Not every browser supports this new feature

Practical application of Web Workers:

<!-- Use recursion to calculate the value of the Fibonacci sequence where the input number is located -->
<!-- In this calculation method, when the number of calculation bits is large, the whole interface will be inoperable and wait for the calculation result. The main thread has been calculating -->
<input type="text" placeholder="numerical value" id="number" />
<button id='btn'>
    calculation
</button>
<script type="text/javascript">
	function fibonacci(n) {
        return n <= 2 ? 1 :fibonacci(n-1) + fibonacci(n-2); // Recursive call
    }
    var input = document.getElementById('number');
    document.getElementById('btn').onclick = function() {
        var number = input.value;
        var result = fibonacci(number);
        alert(result);
    }
</script>

The solution using Web Workers is as follows: (you need to start in the container to pass the test)

<input type="text" placeholder="numerical value" id="number" />
<button id='btn'>
    calculation
</button>
<script type="text/javascript">
  var input = document.getElementById('number');
  document.getElementById('btn').onclick = function () {
    var number = input.value;

    // Create a Worker object
    var worker = new Worker('myWorker.js');
    // Send messages to threads
    worker.postMessage(number);
    // Bind listening for receiving messages
    worker.onmessage = function (event) {
      console.log('The main thread receives the data returned by the sealing thread', event.data);
      alert(event.data);
    }
  }
</script>
// myWorker.js
function fibonacci(n) {
  return n <= 2 ? 1 : fibonacci(n-1) + fibonacci(n-2); // Recursive call
}

var onmessage = function(event) {
  var number = event.data;
  console.log('The sub thread receives the data sent by the main thread:', number);
  // calculation
  var result = fibonacci(number);
  postMessage(result);
  // alert(result); alert is a method of window, which cannot be called in sub thread
  // console is implemented by browser, so it can be used
  // Each thread has its own global object
  // The global object in the sub thread is no longer window, so it is impossible to follow the new interface in the sub thread
}

Insufficient workers:

1. Slow speed 2. js cannot be loaded across domains 3. Not every browser supports this new feature 4. Code in worker cannot access DOM (update)