JS
Variable types and calculations
-
typeof
Can 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
typeof
operator
- 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