Primary knowledge points of JavaScript (prototype, closure, asynchronous) sorting

Time:2021-12-13

JS

Variable types and calculations

  • typeofCan you judge which types
  • When to use = = = when to use==
  • Difference between value type and reference type
  • Handwritten deep copy

Value type and reference type

Value types are stored in stack memory and reference types are stored in heap memory

//Value type
let a = 100
let b = a
a = 200
console.log(b)  // 100
//Reference type
let a = { age: 20 }
let b = a
b.age = 21
console.log(a.age)  // 21

Common value types and reference types

//Common value types
let u   // undefined
const s = 'abc'
const n = 100
const b = true
const s = Symbol('s')
//Common reference types
const obj = { x: 100 }
const arr = ['a', 'b', 'c']

Const n = null // special reference type, pointer to null address

//Special reference types are not used to store data, so there is no theory of copy and copy functions
function fun() {}

Type judgment

typeofoperator

  • Identify all value types
  • Recognition function
  • Judge whether it is a reference type (can’t be subdivided)

Deep cloning

function deepClone(obj = {}) {
    if (typeof obj !== 'object' || obj === null) {
        //If obj is null, or is it an object or array, it will be returned directly
        return obj
    }

    //Initialization return result
    let result
    if (obj instanceof Array) {
        result = []
    } else {
        result = {}
    }

    for (let key in obj) {
        //Ensure that the key is not an attribute of the prototype
        if (obj.hasOwnProperty(key)) {
            //Recursion
            result[key] = deepClone(obj[key])
        }
    }

    return result
}

Type conversion

  • String splicing
  • ==
  • If statement logic operation
const a = 100 + 10 // 110
const b = 100 + '10' // 10010
const c = true + '10' // true10

const d = 100 + parseInt('10') // 110

==

100 == '100' // true
0 == '0' // true
0 == false // true
false == '' // true
null == undefined // true
NaN == NaN // false

//Except = = null, all others use = = =, for example:
const obj = { x: 100 }
if (obj.a == null) {}
//Equivalent to
if (obj.a === null || obj.a === undefined) {}

Logical operation

If statements and logical operations

  • Truly variable:!! A = = = true variable
  • False variable:!! A = = = false variable

Prototype and prototype chain

  • How to judge whether a variable is an array?
  • Write a simple jQuery, considering plug-ins and extensibility
  • How to understand the prototype essence of class?

class

class Student {
    constructor(name, number) {
        this.name = name
        this.number = number
    }
    greeting() {
        console.log(`Hello, My name is ${this.name}, number is ${this.number}`)
    }
}

//Instantiation
const zhangsan = new Student('zhangsan', 1)
zhangsan.greeting() // Hello, My name is zhangsan, number is 1

inherit

//Parent class
class Person {
    constructor(name) {
        this.name = name
    }
    eat() {
        console.log(`${this.name} eat something`)
    }
}

//Subclass
class Student extends Person {
    constructor(name, number) {
        super(name)
        this.number = number
    }
    greeting() {
        console.log(`Hello, My name is ${this.name}, number is ${this.number}`)
    }
}

//Subclass
class Teacher extends Person {
    constructor(name, subject) {
        super(name)
        this.subject = subject
    }
    teach() {
        console.log(`My name is ${this.name}, and I am teaching ${this.subject}`)
    }
}

//Instantiation
const zhangsan = new Student('zhangsan', 1)
zhangsan.greeting() // Hello, My name is zhangsan, number is 1
zhangsan.eat() // zhangsan eat something

const mrWang = new Teacher('wang', 'Math')
mrWang.eat()  // wang eat something
mrWang.teach()  // My name is wang, and I am teaching Math

//Type judgment
console.log(zhangsan instanceof Student) // true
console.log(zhangsan instanceof Person) // true
console.log(zhangsan instanceof Object) // true

// true
console.log([] instanceof Array)
console.log([] instanceof Object)
console.log({} instanceof Object)

prototype

//Class is actually a function, just a syntax sugar
typeof Person // function
typeof Student // function

//Implicit prototype and display prototype
console.log(zhangsan.__proto__)
console.log(Student.prototype)
console.log(zhangsan.__proto__ === Student.prototype) // true

Prototype relationship

  • Each class has a prototype to display
  • Each instance has an implicit prototype__ proto__
  • Instance__ proto__ Point to the prototype of the corresponding class

Prototype chain

console.log(Student.prototype.__proto__)
console.log(Person.prototype)
console.log(Person.prototype === Student.prototype.__proto__) // true

instanceof

Manual implementationinstanceof

function myInstanceof(left, right) {
    //Gets the prototype of the class
    let prototype = right.prototype
    //Gets the prototype of the object
    left = left.__proto__
    //Determine whether the type of the object is equal to the prototype of the type
    while (true) {
        if (left === null)
            return false
        if (prototype === left)
            return true
        left = left.__proto__
    }
}

Write a simple jQuery, considering plug-ins and extensibility

class jQuery {
    constructor(selector) {
        const result = document.querySelectorAll(selector)
        const length = result.length
        for (let i = 0; i < length; i++) {
            this[i] = result[i]
        }
        this.length = length
        this.selector = selector
    }
    get(index) {
        return this[index]
    }
    each(fn) {
        for (let i = 0; i < this.length; i ++) {
            const elem = this[i]
            fn(elem)
        }
    }
    on(type, fn) {
        return this.each(elem => {
            elem.addEventListener(type, fn, false)
        })
    }
}

//Plug in
jQuery.prototype.dialog = function (info) {
    alert(info)
}

//"Making wheels"
class myJQuery extends jQuery {
    constructor(selector) {
        super(selector)
    }
    //Expand your own methods
    addClass(className) {
        // ...
    }
    style(data) {
        // ...
    }
}

Scope and closure

  • How to get values for different application scenarios of this?
  • Handwritten bind function
  • The application scenario of closure in actual development is illustrated by an example
  • Create 10<a>When the tag is clicked, the corresponding serial number will pop up

Scope

let a = 0
function fn1() {
    let a1 = 100

    function fn2() {
        let a2 = 200

        function fn3() {
            let a3 = 300
            return a + a1 + a2 + a3
        }
        fn3()
    }
    fn2()
}
fn1()
  • global scope
  • Function scope
  • Block level scope (new in ES6)

Free variable

  • A variable is not defined in the current scope, but is used
  • Search the parent scope layer by layer until it is found
  • If it is not found in the global scope, an error XXX is not defined is reported

closure

  • There are two special cases of scope application
  • Functions are passed as arguments
  • Function is returned as a value
//Function as return value
function create() {
    let a = 100
    return function () {
        console.log(a)
    }
}

let fn = create()
let a = 200
fn() // 100

//Function as parameter
function print(fn) {
    let a = 200
    fn()
}

let a = 100
function fn() {
    console.log(a)
}
print(fn) // 100

Closure: the search of free variables refers to the search from the superior scope where the function is defined

Not in the place of execution!!!

this

  • As a normal function
  • Using call apply bind
  • Called as an object method
  • Call in the class method
  • Arrow function

The value of this is determined when the function is executed, not when it is defined

function fn1() {
    console.log(this)
}
fn1() // window

fn1.call({x: 100}) // {x: 100}

const fn2 = fn1.bind({x: 200})
fn2() // {x: 200}

Arrow function

const zhangsan = {
    name: 'zhangsan',
    greeting() {
        //This is the current object
        console.log(this)
    },
    wait() {
        setTimeout(function() {
            // this === window
            console.log(this)
        })
    }
}

//This of the arrow function always takes this of the superior scope
const zhangsan = {
    name: 'zhangsan',
    //This is the current object
    greeting() {
        console.log(this)
    },
    wait() {
        setTimeout(() => {
            //This is the current object
            console.log(this)
        })
    }
}

Create 10<a>When the tag is clicked, the corresponding serial number will pop up

let a
for (let i = 0; i < 10; i++) {
    a = document.createElement('a')
    a.innerHTML = i + '<br>'
    a.addEventListener('click', function(e) {
        e.preventDefault()
        alert(i)
    })
    document.body.appendChild(a)
}

Handwritten bind function

Function.prototype.myBind = function() {
    //Disassemble parameters into arrays
    const args = Array.prototype.slice.call(arguments)

    //Get this (the first item in the array)
    const that = args.shift()

    // fn. bind(...)  FN in
    const self = this

    //Returns a function
    return function() {
        return self.apply(that, args)
    }
}

Application of closure in practical development

  • Hide data

  • Such as making a simple cache tool

  • function createCache() {
        Const data = {} // the data in the closure is hidden and not accessed by the outside world
        return {
            set(key, value) {
                data[key] = value
            },
            get(key) {
                return data[key]
            }
        }
    }
    
    const c = createCache()
    c.set('a', 100)
    console.log(c.get('a'))

asynchronous

  • What is the difference between synchronous and asynchronous?

  • Handwritten promise loads a picture

  • Scenarios where the front end uses asynchrony

  • Please describe the mechanism of event loop (event loop / event polling), which can be drawn

  • What are macro tasks and micro tasks, and what is the difference between them?

  • What are the three states of promise? How does it change?

  • The connection between promise then and catch

  • Async / await syntax

  • The order of promise and setTimeout

Single thread

  • JS is a single threaded language and can only do one thing at the same time
  • The browser and nodejs support JS startupprocess, such as web worker
  • JS and DOM rendering share the same thread because JS can modify the DOM structure
  • Asynchronous callback based callback function form

callback

//Asynchronous
console.log(100)
setTimeout(function() {
  console.log(200)
}, 1000)
console.log(300)

//Synchronization
console.log(100)
alert(200)
console.log(300)

Asynchrony does not block code execution

Synchronization blocks code execution

Application scenario

  • Network requests, such as Ajax image loading
  • Scheduled tasks, such as setTimeout

promise

Basic use

//Load picture
function loadImg(src) {
    const p = new Promise(
        (resolve, reject) => {
            const img = document.createElement('img')
            img.onload = () => {
                resolve(img)
            }
            img.onerror = () => {
                Const err = new error (` picture loading failed ${SRC} `)
                reject(err)
            }
            img.src = src
        }
    )
    return p
}
const url = 'www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png'
loadImg(url).then(img => {
    console.log(img.width)
    return img
}).then(img => {
    console.log(img.height)
}).catch(ex => console.error(ex))

state

  • Three states
    • pending
    • resolved
    • rejected
    • Change: pending = > resolved or pending = > rejected
    • Change is irreversible
  • Performance and change of state
    • In pending status, then and catch will not be triggered
    • In the resolved state, the subsequent then callback function will be triggered
    • In the rejected state, the subsequent catch callback function will be triggered
const p1 = new Promise((resolve, reject) => {})
console.log(p1) // pending

const p2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve()
  })
})
console. Log (P2) // pending at the beginning of printing
setTimeout(() => console.log(p2)) // resolved

const p3 = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject()
  })
})
console. Log (P3) // pending at the beginning of printing
setTimeout(() => console.log(p3)) // rejected

//Obtain a promise in the resolved state directly
const resolved = Promise.resolve(100)
console.log(resolved) // resolved

//Get a promise in the rejected state directly
const resolved = Promise.reject('err')
console.log(resolved) // rejected
  • The influence of then and catch on state
    • Then returns resolved normally. If there is an error, it returns rejected
    • Catch returns resolved normally. If there is an error, it returns rejected
//Then() normally returns promise in the resolved state
Promise.resolve().then(() => {
    return 100
})

//If an error is thrown in then (), it will return the promise in the rejected state
Promise.resolve().then(() => {
    throw new Error('err')
})

//Catch () does not throw an error and returns promise in the resolved state
Promise.reject().catch(() => {
    console.error('catch some error')
})

//Catch() throws an error and returns promise in the rejected state
Promise.reject().catch(() => {
    console.error('catch some error')
    throw new Error('err')
})

topic

//First question
Promise.resolve().then(() => {
    console.log(1)
}).catch(() => {
    console.log(2)
}).then(() => {
    console.log(3)
})

//Second question
Promise. resolve(). Then (() = > {// returns promise in rejected status
    console.log(1)
    throw new Error('erro1')
}). Catch (() = > {// returns promise in resolved status
    console.log(2)
}).then(() => {
    console.log(3)
})

//Question 3
Promise. resolve(). Then (() = > {// returns promise in rejected status
    console.log(1)
    throw new Error('erro1')
}). Catch (() = > {// returns promise in resolved status
    console.log(2)
}).catch(() => {
    console.log(3)
})

event-loop

  • JS is single threaded
  • Asynchrony is implemented based on callbacks
  • Event loop is the implementation principle of asynchronous callback

How does JS execute

  • From front to back, execute line by line
  • If an error is reported in the execution of a line, stop the execution of the following code
  • The synchronous code is executed first, and then the asynchronous code is executed

Event loop execution process

  • The synchronization code is executed on the call stack line by line
  • In case of asynchrony, it will first “record” and wait for the opportunity (timing, network request)
  • When the time comes, move to the callback queue
  • If the call stack is empty (i.e. the synchronization code is executed), the event loop starts to work
  • Poll to find the callback queue. If any, move it to the call stack for execution
  • Then continue polling (like a perpetual motion machine)

DOM events and event loop

  • Asynchronous (setTimeout, AJAX, etc.) uses callbacks based on event loop
  • DOM events also use callbacks, based on event loop

async/await

  • Asynchronous callback shell
  • Promise is based on the then catch chain call, but it is also based on the callback function
  • Async / await is a synchronous syntax that completely eliminates callback functions

There are many async interview questions, such as

  • Async returns directly. What is it
  • Async returns promise directly
  • Promise is not added after await

Basic grammar

function loadImg(src) {
    const promise = new Promise((resolve, reject) => {
        const img = document.createElement('img')
        img.onload = () => {
            resolve(img)
        }
        img.onerror = () => {
            Reject (new error ('picture loading failed ${SRC} '))
        }
        img.src = src
    })
    return promise
}

async function loadImg1() {
    const src1 = 'www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png'
    const img1 = await loadImg(src1)
    return img1
}

async function loadImg2() {
    const src2 = 'https://avatars3.githubusercontent.com/u/9583120'
    const img2 = await loadImg(src2)
    return img2
}

(async function () {
    //Note: await must be placed in the async function, or an error will be reported
    try {
        //Load first picture
        const img1 = await loadImg1()
        console.log(img1)
        //Load second picture
        const img2 = await loadImg2()
        console.log(img2)
    } catch (ex) {
        console.error(ex)
    }
})()

Relationship between async / await and promise

  • Async / await is the ultimate weapon against asynchronous callbacks
  • But promise and promise are not mutually exclusive
  • Instead, they complement each other
  • Await is equivalent to promise’s then
  • try… Catch can catch exceptions instead of promise’s catch
  • The returned results of async function are promise objects (if promise is not returned in the function, it will be encapsulated automatically)
async function fn2() {
    return new Promise(() => {})
}
console.log( fn2() )

async function fn1() {
    return 100
}
console. Log (fn1()) // equivalent to promise resolve(100)
  • Await is followed by promise object: it will block subsequent code and wait until the status changes to resolved before obtaining the result and continuing execution
  • Await is followed by non promise objects: it will be returned directly
(async function () {
    const p1 = new Promise(() => {})
    await p1
    console. Log ('p1 ') // not executed
})()

(async function () {
    const p2 = Promise.resolve(100)
    const res = await p2
    console.log(res) // 100
})()

(async function () {
    const res = await 100
    console.log(res) // 100
})()

(async function () {
    const p3 = Promise.reject('some err')
    const res = await p3
    console. Log (RES) // not executed
})()
  • try… Catch captures the rejected status
(async function () {
    const p4 = Promise.reject('some err')
    try {
        const res = await p4
        console.log(res)
    } catch (ex) {
        console.error(ex)
    }
})()

In summary:

  • Async package promise
  • Promise processed successfully by await
  • try… Catch processing promise failed

Asynchronous nature

Await is written synchronously, but its essence is asynchronous call.

async function async1 () {
  console.log('async1 start')
  await async2()
  console. Log ('async1 end ') // the key is this step. It is equivalent to putting it in the callback and executing it finally
}

async function async2 () {
  console.log('async2')
}

console.log('script start')
async1()
console.log('script end')

That is, as long as you encounterawait, the following codes are equivalent to being placed in callback.

for…of

  • for … In (and foreach for) are regular synchronous traversals
  • for … Of common and asynchronous loops
//Timing multiplication
function multi(num) {
    return new Promise((resolve) => {
        setTimeout(() => {
            resolve(num * num)
        }, 1000)
    })
}

//// use foreach to print all the results after 1s, that is, the three values are calculated together
// function test1 () {
//     const nums = [1, 2, 3];
//     nums.forEach(async x => {
//         const res = await multi(x);
//         console.log(res);
//     })
// }
// test1();

//Use for Of, allowing calculations to be executed serially one by one
async function test2 () {
    const nums = [1, 2, 3];
    for (let x of nums) {
        //In for Within the of loop body, await will be calculated serially one by one
        const res = await multi(x)
        console.log(res)
    }
}
test2()

Micro task / macro task

  • Macro task: setTimeout setinterval DOM event
  • Micro task: Promise (for the front end)
  • Micro tasks execute earlier than macro tasks
console.log(100)
setTimeout(() => {
    console.log(200)
})
Promise.resolve().then(() => {
    console.log(300)
})
console.log(400)
// 100 400 300 200

Event loop and DOM rendering

  • Every time the call stack ends, DOM rendering will be triggered (you don’t have to render, just give a DOM rendering opportunity!)
  • Then perform event loop
Const $P1 = $('< p > a text < / P >')
Const $P2 = $('< p > a text < / P >')
Const $P3 = $('< p > a text < / P >')
$('#container')
            .append($p1)
            .append($p2)
            .append($p3)

console.log('length',  $('#container').children().length )
Alert ('after this call stack, the DOM structure has been updated, but the rendering has not been triggered ')
//(alert will block JS execution and DOM rendering for easy viewing)
//At this point, that is, after the call stack is completed (all synchronization tasks are executed), the browser will automatically trigger rendering without code intervention

//In addition, you can see the result of DOM rendering by triggering the DOM rendering time according to the event loop and alerting during setTimeout
setTimeout(function () {
    Alert ('settimeout is the result of DOM rendering in the next call stack ')
})

Difference between macro task and micro task

  • Macro task: triggered after DOM rendering
  • Micro task: triggered before DOM rendering
//Modify DOM
Const $P1 = $('< p > a text < / P >')
Const $P2 = $('< p > a text < / P >')
Const $P3 = $('< p > a text < / P >')
$('#container')
    .append($p1)
    .append($p2)
    .append($p3)

//// micro task: executed before rendering (DOM structure updated)
// Promise.resolve().then(() => {
//     const length = $('#container').children().length
//     alert(`micro task ${length}`)
// })

//Macro task: execute after rendering (DOM structure updated)
setTimeout(() => {
    const length = $('#container').children().length
    alert(`macro task ${length}`)
})

Think more deeply: why do the two have the above differences, one before rendering and one after rendering?

  • Micro tasks: within the ES Syntax Standard, JS engine handles them uniformly. That is, it can be processed at one time without any information from the browser, which is faster and more timely.
  • Macro task: no es syntax, no JS engine processing, browser (or nodejs) intervention processing.

Classic interview questions

async function async1 () {
  console.log('async1 start')
  Await async2() // this sentence will be executed synchronously and return promise, where ` console Log ('async2 ') ` will also be executed synchronously
  console. Log ('async1 end ') // there is await on it, and it becomes "asynchronous" below, which is similar to the function of cakkback (micro task)
}

async function async2 () {
  console.log('async2')
}

console.log('script start')

SetTimeout (function() {// asynchronous, macro task
  console.log('setTimeout')
}, 0)

async1()

New promise (function (resolve) {// after the promise is returned, the synchronous execution is completed. Then is the asynchronous code
  console. Log ('promise1 ') // the promise function will be executed immediately
  resolve()
}). Then (function() {// asynchronous, micro task
  console.log('promise2')
})

console.log('script end')

//After the synchronous code is executed, repeat the existing asynchronous unexecuted code in order
// 1.  Content after await in async1 function -- Micro task
// 2.  SetTimeout -- macro task
// 3.  Then -- Micro task

modularization

ES6 Module

slightly

Recommended Today

MySQL related

Indexes Bottom structure Disadvantages of hash table index: Using hash storage requires adding all files to memory, which consumes more memory space If all queries are equivalent queries, the hash is indeed fast, but in the actual scene, more data is found, and not all queries are equivalent queries, so the hash table is not […]