JavaScript advanced self study notes

Posted by batfastad on Fri, 31 Dec 2021 02:00:01 +0100

preface:

This note is an advanced self-study note of javascript based on JavaScript. The full text is about 11000 words
Main contents:

  • Depth of data types;
  • Prototype chain;
  • Succession;

Parts to be improved:

  • Combinatorial inheritance, combinatorial + parasitic inheritance;
  • Browser thread;

Last updated on: August 3, 2021

data type

Basic type

string
number
boolean
undefined
null

Reference type (object type)

object
Function (special object, executable)
Array (special object, internal data in order)

Judge data type

typeof

Returns a string of data type
Unable to judge null and object, both return object
Neither array nor object can be judged. Both return object

Instanceof (instance)

Determine the specific type of reference type
The output is Boolean

a instanceof Object/Function/Array
Functions and arrays are also objects

===

Can be used to determine undefined and null

What is the difference between undefined and null?

undefined means that an unassigned value is defined

Null means defined and assigned, and the value is null

When is a variable assigned null?

The initial assignment is null, indicating that it will be assigned as an object

var a = null // Indicates the object to be assigned
a = []
a = null // Free memory occupied by array

Finally, assign null to change the pointing object into a garbage object, so that it can be recycled and free memory

Strictly distinguish between data types and variable types

Type of variable (type of variable memory value)
Basic type: the saved value is a basic type
Reference type: the saved value is the address of the object

Variable parameter passing is value passing. The value may be the basic type or the address value of the object

Note the following distinction: the saved address value and the object pointed to

        var a = {
            // Give the address value of the object to a
            // The object itself is in the heap, and the address value identifying the object is saved on the stack
            age: 12
        }
        function changeAge(a) {
            a.age = 17;
        }
        changeAge(a);
        // A and parameter a in the function have different addresses and point to the same object
        // The same object is modified
        console.log(a.age);// 17
        var a = {
            // Give the address value of the object to a
            // The object itself is in the heap, and the address value identifying the object is saved on the stack
            age: 12
        }
        function changeAge(a) {
            // The formal parameter of the function originally points to the same object as the uppermost a, that is, age=12
            a = {age: 17};
            // At this time, the formal parameter of the function points to the new object age=17

            // The real a is another object and has not changed
        }
        changeAge(a);// Assign a to a formal parameter
        console.log(a.age);// 12

Note: if you use const to declare an object, you cannot change it to another object

        var a = 3
        function add(a) {
            a = a + 1;
            console.log(a);// 4
        }
        add(a);// The function passes data 3
        console.log(a);// 3
        // Understand according to the variable scope

How does the JS engine manage memory

Life cycle of memory

1. Allocate memory and obtain usage rights
2. Data can be stored for repeated operation
3. Free memory space

Free memory

1. Local variable: the function is automatically released after execution. Pay attention to different closures
2. Object: become a garbage Object > garbage collector collection

object

Method is a special property
The property value is the method of the function

When do I have to read or modify an object's properties by using [property name]?

The attribute name wrapped with [] should be quoted to indicate that it is a string
Variables are represented without quotation marks

1. The property name contains special characters: - spaces

        var p = {}
        // p.a-b = 'aaa';// error
        p['a-b'] = 'aaa';
        console.log(p['a-b']);// aaa

2. The property name is variable

        var p ={}
        var a1 = 'myAge';
        var value = 18;
        // p.a1 = value;
        // console.log(p);
        // Output a1: 18 instead of myAge: 18
        // a1 should be a variable that holds the attribute name

        p[a1] = value;
        console.log(p);
        // Output myAge: 18

function

Function is the encapsulation of n statements, which is convenient for reuse
Only functions can be executed, and other data cannot be executed
Improve code reuse and facilitate reading and communication

        fun1();
        // fun2(); // error

        // Function declaration method
        // Can be used in advance
        function fun1() {
            console.log('Hello');
        }
        fun1();

        // Define functions in expression mode
        // You can't use it in advance
        var fun2 = function(){
            console.log('Expression mode');
        }
        fun2();
        var obj1 = {}
        function fun3(){
            console.log('Your mother');
        }
        // You can call a function as a method that specifies any object
        fun3.call(obj1);// By function Call (object) causes the function to be called again by a method called an object

Callback function

DOM event callback function

        var btn = document.querySelector('button');
        btn.addEventListener('click',function(){
            // Get text dynamically
            alert(this.innerHTML);
        })

Timer callback function

        setTimeout(function(){
            alert(123456);
        },2000)

Network request callback function
Later

Lifecycle callback function
Later

IIFE

immediately invoked function expression
Execute the function immediately, and the anonymous function calls itself

    (function (){
        var a= 3;
        console.log(a+2);
    })();

    // ES6
    ((a=3) => console.log(a+2))()

Function: hide the implementation, do not pollute the global namespace, and write JS modules

this

Every time the parser calls a function, it will pass an implicit parameter into the function. This implicit parameter is this, which points to an object
This object is called the context object of function execution. Depending on the calling method of the function, this will point to different objects

1. When called as a function, this is always window

2. When called as a method, this is the object that calls the method

3. When called in the form of constructor, this is the newly created object (instance)

4. When call () and apply() are used, this is the specified object

5. In the event response function, this is who the response function is bound to

Function advanced

Prototype and prototype chain (the implicit prototype of the instance object points to the explicit prototype of its constructor)

The prototype property of the function

Each function has a prototype attribute, which by default points to an empty object, the (explicit) prototype object
The prototype object has a property called constructor (constructor), which points to itself (constructor object)

The constructor and its own prototype object refer to each other

console.log(fun1.prototype.constructor === fun1);
// true

Add properties (usually methods) to prototype objects
Role: all instance objects automatically own properties (Methods) in the prototype

        function fun1(){

        }
        // Each function has a prototype attribute
        // Function name A prototype is an object

        // js can dynamically add attributes to objects
        // Add a method
        fun1.prototype.test = function(){
            console.log('test()');
        }
        console.log(fun1.prototype);

Explicit prototype and implicit prototype

Each function has a prototype attribute, that is, an explicit prototype, which points to an empty object (instance object) by default Automatically add when defining a function

Each instance object has one__ proto__ Property, that is, the implicit prototype, is automatically added when the instance object is created,

The implicit prototype of the instance object points to the value of the display prototype of its corresponding constructor
(↑ important!!)

    function Fn(){
    }
    console.log(Fn.prototype);
    var fn = new Fn();
    console.log(fn.__proto__);
    console.log(Fn.prototype === fn__proto__);// true

        // Create function object
        // Fn is the variable name, which stores the address value of the object
        function Fn(){
            this.test1 = function(){
                console.log('test1');
            }
        }
        console.log(Fn.prototype);
        // Each function has a prototype attribute, that is, to display the prototype. By default, it points to an empty Object (prototype Object)

        // Add a method test2 to the prototype object
        Fn.prototype.test2 = function(){
            console.log('test2');
        }
        var fn = new Fn() 

The value of the explicit prototype of the constructor object is equal to the value of the implicit prototype of the instance object

Prototype chain (implicit prototype chain)

When accessing the properties of an instance object
1. First find the attribute of the instance object and find the returned value
2. Otherwise, follow the path of the instance object__ proto__ Look up, find and return
3. Otherwise, return undefined
be careful:
1. All functions are instances of Function (including Function itself)
2. The prototype object of object is the end of the prototype chain

Setting and finding

Search is generally to find yourself first, and if you don't, you can trace the source along the prototype chain
But the settings are set directly on yourself

    function Fn() {}
    // Add attribute a:'jjj' on prototype object
    Fn.prototype.a = 'jjj'

    const fn1 = new Fn()
    const fn2 = new Fn()
    fn2.a = 'yyy'

    console.log(fn1.a,fn1);
    // Find whether it has a, if not, find it along the prototype chain (implicit prototype - explicit prototype - prototype object)
    // jjj
    console.log(fn2.a,fn2);
    // When setting properties for an instance, they are directly set to the instance itself
    // yyy

Prototype inheritance

The instance object of the constructor automatically owns the properties and methods of the constructor prototype object

Detailed explanation of instanceof

A instanceof B
That is, judge whether A is an instance of B
Returns true if the explicit prototype object of the B constructor is on the implicit prototype chain of the A instance object, otherwise returns false

const arr = []

console.log(arr instanceof Array);// true
console.log(arr instanceof Object);// true

const fn = () => {}
console.log(fn instanceof Function);// true
console.log(fn instanceof Object);// true


// const Ff = () => {}
    // Let's review the implementation process of new:
    // 1. Create an empty object
    // 2. The object's__ proto__ prototype that points to a constructor, such as Fn
    // 3. Modify the context of the constructor Fn to an empty object
    // 4. Returns an empty object (actually this)
    // The arrow function does not meet the second step, that is, there is no prototype, so you cannot use the new keyword to create an instance object of the arrow function

function Ff(){}
const ff = new Ff
console.log(ff);
console.log(ff instanceof Ff);// true
console.log(ff instanceof Function);// false
// Because there is no Function on the prototype chain of the ff instance object
// ff.__proto__ === Ff.prototype → object
// object.__proto__ === Object.prototype
// Object.__proto__ === null (end of prototype chain)
// It can be seen that there is no Function in the middle
console.log(ff instanceof Object);// true

console.log(Ff.prototype instanceof Object);// true
console.log(ff.__proto__ instanceof Object);// true



console.log(Object instanceof Function);// true
console.log(Object instanceof Object);// true
console.log(Function instanceof Function);// true
console.log(Function instanceof Object);// true

function Fun(){}
console.log(Object instanceof Fun);// false

Own thinking

The so-called = = = and pointing actually have the same meaning, because both the implicit prototype of the instance object and the display prototype of the constructor are saved address values, and the address values are all equal. It can also be said that the implicit prototype points to the display prototype, and the display prototype points to the prototype object (an object)

Prototype topic

1

    // Create constructor
    var A = function(){}
    // Add the attribute n to the instance object and assign a value of 1
    A.prototype.n = 1;
    // Create instance object
    var b = new A();
    // At this point, the display prototype of the constructor points to the new prototype object (address change)
    A.prototype = {
        n:2,
        m:3
    }
    var c = new A();
    console.log(b.n,b.m,c.n,c.m);
    // 1 undefined 2 3

2

    // Define function
    var F = function(){}
    // Add a method to the Object prototype
    Object.prototype.a = function(){
        console.log('a()');
    }
     // Add b method to Function prototype
    Function.prototype.b = function(){
        console.log('b()');
    }
    var f = new F();
    f.a() // a()
    f.b()// error
    F.a()// a()
    F.b()// b()
    // Note: this section understands the prototype chain diagram

Prototype chain diagram

[the external chain picture transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the picture and upload it directly (img-YTl3HlO5-1627938283454)(./images/js advanced / SRC = http__ img2018.cnblogs.com_blog_1762947_201909_1762947-20190926094156327-588943618. JPG & refer = http__ img2018. Cnblogs. JPG)]

Variable declaration promotion

var is declared in advance but not assigned. It is assigned only after execution, and the access before execution is undefined

Both const and let in ES6 do not have variable promotion. There is a dead zone before declaration. If you use variables, you will report an error

Function declaration promotion

function is declared in advance and can be called directly
Function promotion must be declared
function fun(){}

Global execution context

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

2. Pre parse global data
The global variable defined by var is undefined and added as the attribute of window
Assignment of global function declared by function and added as the method of window
this is assigned to window

3. Start executing global code

Function execution context

1. Before calling the function and preparing to execute the function body, create the corresponding function execution context object

2. Pre analyze local data
Formal parameter variable → assignment (argument) → attribute added as execution context
arguments → assignment (pseudo array of all argument lists) → attribute added as execution context
Defined local variable → assign undefined and add it as the attribute of the execution context
Function declared function → assignment, added as the method of execution context
this → assignment

3. Start executing function code

    var c = 1;
    function C(c) {
        console.log(c);// Output passed argument 3
        var c = 2;// Declared advance value undefined
    }
    C(3);
    // 3

Execution Context Stack

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

2. After the global execution context (window) is determined, add it to the stack for stack pressing

3. After the function execution context is created, add it to the stack for stack pressing

4. After the current function is executed, remove the stack top object and exit the stack

5. After all the code is executed, only window remains in the stack

Example 1

        var i = 1;
        fun(1);// Function declaration is called directly in advance
        function fun(i){
            if(i == 4){
                return;
            }
            console.log(i);
            fun(i+1);// Recursive call
            console.log(i);

        }
        console.log(i);
        // 1 2 3 | 3 2 1 1 

Example 2

        function a(){}
        var a;
        console.log(typeof a);
        // function
        // Perform variable promotion before function promotion

Example 3

        if (!(b in window)) {
            var b = 1;
        }
        console.log(b);
        // undefined

Example 4

        var c = 1;
        function c(c){
            console.log(c);
            var c = 3;
        }
        c(2);
        // error
        
        
        // amount to
        
        
        var c;// Variable promotion
        // Function promotion
        function c(c){
            console.log(c);
            var c = 3;
        }
        // Variable assignment
        c = 1;
        // At this time, c is not a function, so an error is reported
        c(2);

Scope and scope chain

Scope

The area where the code segment is located. It is static and is determined when writing code

Classification: global scope, function scope, ES6 block level scope

Scope: isolate variables. Variables with the same name under different scopes will not conflict

Scope and execution context

Difference 1:
Outside the global scope, each function will create its own scope. The scope has been determined when the function is defined, not when the function is called

The global execution context is created immediately after the global scope is determined and before the js code is executed
The function execution context is created before the function body code is executed when the function is called

Difference 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 a function is called. At the end of a function call, the execution context is out of the stack and released

Contact:
The execution context is subordinate to the scope in which it resides

Example 1

let x = 10
function fn(){
    console.log(x);
}

function show(f){
    let x = 20
    f()
    // Note that executing f() at this time will find x in the local scope of fn function
    // Global x = 10 not found along scope chain
}
show(fn)
// 10

Example 2

const obj = {
    fn(){
        console.log(fn);
    }
}
obj.fn()
// report errors
// The {} of obj does not form a layer of scope. Outside the function, it is directly global, and there is no fn in the global

closure

        // Pop up message box corresponding to implementation button
        var btns = document.querySelectorAll('button');
        // closure
        for (var i = 0; i < btns.length; i++) {
            (function (i) {
                var btn = btns[i];
                btn.onclick = function () {
                    alert('The first' + (i + 1) + 'individual');
                }
            })(i);

        }

        // for (var i = 0; i < btns.length; i++) {
        //     var btn = btns[i];
        //     btn.index = i;
        //     btn.onclick = function () {
        //         alert('the '+ (this.index + 1) +' number ');
        //     }
        // }

How to generate closures?

When the nested internal child function references the variable (or function) of the external parent function, the execution of the external parent function generates closures. The execution of the external function several times generates several closures

What is a closure?

Closures are the nested internal sub functions mentioned above, and their references to external function variables or functions are called closures as a whole

Closures are functions that can read internal variables of other functions—— Ruan Yifeng

Function of closure

1. Use the variables inside the function to survive in memory after the function is executed (prolonging the life cycle of local variables)

2. Data (variable / function) that can be manipulated (read / write) from outside the function to inside the function

3. Encapsulate private data and some functional functions into the same function, and then expose them to the outside to form an independent functional module

Shortcomings and solutions of closures: memory overflow and memory leak

Because the local variables used in closures will always exist, they cannot be released
Release the nested function object in time to make it a garbage object and be recycled

function fun(n, o) {
    console.log(o)
    return {
        fun: function (m) {
            return fun(m, n)
        }
    }
}

var a = fun(0) //undefined
a.fun(1) //0
a.fun(2) //0
a.fun(3) //0

var b = fun(0).fun(1).fun(2).fun(3) // undefined 0 1 2

var c = fun(0).fun(1) // undefined 0
c.fun(2) //1
c.fun(3) //1

Object advanced

new Object() constructor pattern

Object literals are created using {}

Factory mode

Disadvantages: objects have no specific type, they are all objects

function Person (name,age) {
    const obj = {
        name:name,
        age:age,
        setName:function(){
            this.name = name
        }
    }
    return obj
}

const p1 = new Person('jrj',16)
const p2 = new Person('Bob',22)
console.log(p1);

Custom constructor mode

Different objects have specific types
console.log(p1 instanceof Person);

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

const p1 = new Person('jrj', 16)
const p2 = new Person('Bob', 22)
p2.setName('HHH')
console.log(p1)
console.log(p2);;

Constructor + prototype

Put the method on a common prototype

function Person(name, age) {
    // Only general properties are initialized in the constructor
    this.name = name
    this.age = age
}
Person.prototype.setName = function (name) {
    this.name = name
}

const p1 = new Person('jrj', 16)
const p2 = new Person('Bob', 22)
p2.setName('HHH')
console.log(p1)
console.log(p2)

Inheritance mode

1. Prototype chain inheritance

The prototype object of the subtype should be an instance object of the parent type

function Father() {
    this.fatherProp = 'father'
}
Father.prototype.showFatherProp = function () {
    console.log(this.fatherProp);
}

function Son() {
    this.sonProp = 'son'
}

// To implement prototype chain inheritance
// The prototype object of the subtype should be an instance object of the parent type
Son.prototype = new Father()

const s1 = new Son()
s1.showFatherProp()// 'Father'

console.log(s1.__proto__ === Son.prototype);// true
console.log(Son.prototype.__proto__ === Father.prototype);
// true

2. Borrow constructor

That is, the subclass calls the properties and methods of the parent class through js apply and call;
The prototype chain method can realize the sharing of all attribute methods, but it cannot achieve attribute Method exclusive (for example, Sub1 modifies the function of the parent class, and all other subclasses Sub2 and Sub3... Cannot be implemented if they want to call the old function); while the borrowing constructor can not only enjoy the properties and methods, but also pass parameters in the subclass constructor, but the code cannot be reused. Generally speaking, all properties and methods can be exclusive, but the properties and methods cannot be shared (for example, Sub1 adds a function, and if you want Sub2 and Sub3... To work, you can't implement it. You can only add Sub2 and Sub3... In the constructor respectively)

3. Combinatorial inheritance

Combined above

4. Optimal solution: parasitism + combinatorial inheritance

To be continued

Process and thread

imperfect

process

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

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 must run on a thread of a process

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

A process can also 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 the threads in it

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

JS is single threaded

However, using Web Workers in H5 can run in multiple threads

Advantages and disadvantages of single thread / multithreading

Multithreading

advantage:

  • Effectively improve CPU efficiency

Disadvantages:

  • Create multithreading overhead
  • Thread switching overhead
  • Deadlock and state synchronization problems

Single thread

advantage:

  • Sequential coding is easy to understand

Disadvantages:

  • Low efficiency

Browsers are multithreaded

But some are single process (Firefox old IE)
There are many processes (Chrome new IE)

Browser kernel

The browser kernel consists of multiple modules

Chrome | Safari : webkit

firefox: Gecko

IE : Trident

Domestic: Trident + webkit

Main thread

JS engine thread

Responsible for compiling and running JS program

GUI rendering thread

Responsible for rendering browser interface, parsing HTML and CSS, building DOM tree and RenderObject tree, layout and rendering, etc.
When the interface needs to be repainted or reflow is caused by some operation, the thread will execute
Note that the GUI rendering thread and the JS engine thread are mutually exclusive. When the JS engine executes, the GUI thread will be suspended (equivalent to being frozen), and the GUI update will be saved in a queue and executed immediately when the JS engine is idle.

GUI rendering thread and JavaScript engine thread are mutually exclusive!

Because JavaScript can manipulate DOM, If you render the interface while modifying these element attributes (that is, the JavaScript thread and UI thread run at the same time), then the element data obtained before and after the rendering thread may be inconsistent. Therefore, in order to prevent unexpected results in rendering, the browser sets the GUI rendering thread and the JavaScript engine as mutually exclusive. When the JavaScript engine executes, the GUI thread will be suspended, and the GUI update will be saved in a queue until the engine The thread is executed immediately when it is idle. This is why the < script > tag should be placed at the bottom of the body tag.

Sub thread

Timer thread

Responsible for timer management

DOM event response thread

Responsible for DOM event management

Network request thread

Such as Ajax request

The basic process of executing code by JS engine

Execute the initialization code first, including some special codes, such as setting the timer, binding event listening, and sending AJAX requests

The callback code will be executed at a later time

H5 Web Workers multithreading

H5 specification provides the implementation of JS threading, which is called Web Workers
We can run some large amount of code by Web Workers without freezing the user interface
However, the child thread is completely controlled by the main thread and cannot operate DOM. The global object of the worker is not window
So this new standard does not change the single threaded nature of JavaScript
Cannot cross domain
Not all browsers support