At the beginning of 2020, we experienced hardship and panic;

In a blink of an eye, 2020 has come to an end, keep working hard, don’t lose time!

It’s too late to look back and think,

We have fought for our dreams, and we have cried for setbacks;

Time is in haste and time is long,

Sweet and sour, bitter and sweet,

Experience, miss, let people cherish the present life.

For the first 11 months of 2020,

With harvest and regret, with joy and deficiency,

In the last month, by working hard to fight anxiety,

Let 2020 enrich the end!

let & const

Previously, JS had only two types of scope, global scope and function scope. There was no block-level scope

Variables declared through a let are only accessible in their scope.

var elements = [{}, {}, {}] for (var i = 0; i < elements.length; = function() {console.log(I)}} elements[0].onclick() // 3 = = function() {console.log(I)}} elements[0].onclick() I has added up to 3Copy the code

This is also a typical case of closures

var elements = [{}, {}, {}] for (var i = 0; i < elements.length; (function(I) {console.log(I))(I)} elements[0].onclick() // 3 By the end of the loop, I has added up to 3Copy the code

Closures also use function scope to escape the effects of global scope

Now that you have a let, it’s easy

var elements = [{}, {}, {}] for (let i = 0; i < elements.length; = function() {console.log(I)}} elements[0].onclick() = function() {console.log(I)}} elements[0].onclick() = function() {console.log(I)}} elements[0].onclick()Copy the code

Let’s look at another example

for (let i = 0; i < 3; i++) { let i = 'foo'; Console.log (I)} outputs foo three times normally. The two I's do not affect each otherCopy the code

The code is dismantled

let i = 0;
if (i < 3) {
  let i = 'foo'
  console.log(i)
}
i++
if (i < 3) {
  let i = 'foo'
  console.log(i)
}
i++
if (i < 3) {
  let i = 'foo'
  console.log(i)
}
i++
Copy the code

In addition, const/let does not have a variable lift, so it must be declared in the code block before it can be used. This is called a temporary dead zone.

Let name = 'test' if (true) {name = 'test' let name} console.log(name)Copy the code

Const /let does not allow repeated declarations within the same scope;

Const must be initialized and cannot be modified, but if an object is initialized, the memory address of the object cannot be modified.

const person = { name: } person.name = 'test' console.log(person.name) // 'test' only changes the memory space data, does not change the memory address person = '' // TypeError this changes the memory pointCopy the code

Const /let const/ variable declared in global scope does not hang in the properties of the top-level object (window in the browser);

Var name = 'test' let age = 12 console.log(window.name) // 'test' console.log(window.age) // undefinedCopy the code

Best practice: Don’t use var, use const instead, and work with lets. This will significantly improve the quality of your code.

deconstruction

An array of deconstruction

Log (a, b, c) = [1, 2] console.log(a, b, c) = [1, 2] console.log(a, b, c) = [1, 2] console.log(a, b, c) 200, 300] const [foo,...reset] = arr console.log(reset) // Assign const [foo, bar, baz = 123, more = 'test'] = arr; console.log(more)Copy the code

Object to deconstruct

const obj = { name: '123', age: 12} const {name} = obj console.log(name) const name = 'memo' const {name: ObjName = 'jack'} = obj // If there is a large number of console.log const {log} = console log('123') then the overall size of our code will be reduced considerablyCopy the code

Function argument destruct: actually use the above object destruct and array destruct rules;

function move({x = 0, y = 0} = {}) {
    console.log([x, y])
    return [x, y];
}
move({x: 1, y: 2})  // [3, 8]
move({x: 3})        // [3, 0]
move({})            // [0, 0]
move()              // [0, 0]
Copy the code

Template string

Template strings are marked with two backquotes (‘ ‘), which can be used to define multi-line strings or to insert variables into strings:

let name = 'hero'
let tips = `Hello ${name} ---- ${ 1 + 2 }, 
    welcome to my world.`
console.log( tips )
Copy the code

The label template

const str = console.log`hello world`

const name = 'element'
const gender = true
function myFunc(strings, name, gender) {
	const sex = gender ? 'man' : 'woman'
	return strings[0] + name + string[1] + gender + strings[2]
}
const result = myFunc`hey, ${ name } is a ${ gender }.`
Copy the code

Scenario: This template string can be used in multiple languages (e.g. switching between Chinese and English)

Parameter Default values

The previous way

function foo(enable) {
	enable = enable === undefined ? true : ''
	console.log(enable)
}
foo(false)
Copy the code

You have parameter defaults

Function foo(enable = true) {console.log(enable)} foo(false) enable = true) { console.log(enable) } foo(false)Copy the code

The remaining parameters

The previous way we used the pseudo-array, Arguments

Function foo() {console.log(arguments) // arguments (4) [1, 2, 3, 4, callee: ƒ, Symbol(symbol.iterator): ƒ]} foo (1, 2, 3, 4)Copy the code

now

function foo(... Args) {console.log(args)} foo(1,2,3,4)Copy the code

An array of

Const arr = ['foo', 'bar', 'baz'] console.log.apply(console, arr) now simplifies the operation console.log(... arr)Copy the code

Arrow function

Arrow function syntax is more concise than function expressions and does not have its own this, arguments, and cannot be used as constructors and generators.

const arr = [1, 2, 3, 4, 5, 6]
arr.filter(i => i % 2)


const person = {
	name: 'tom',
    sayHi: () => {
    	console.log(`hi, my name is ${this.name}`)  //undefined
    },
    sayHiName: () => {
    	setTimeout(() => {
        	console.log(this.name)
        }, 1000)
    }
}
person.sayHiName()
Copy the code

Object literal enhancement

const bar = 345 const obj = { //bar: bar, bar, methond() { console.log(this) }, [Math.random()]: 123, // The result of calculating the property name math.random () will be the property name [bar]: '23ew'} obj[math.random ()] = 123Copy the code

Object extension method

Object.assign()

const source = { a: 123, b: 345 } const source1 = { a: 789, b: 789 } const target = { a: 678, c: 908 } const result = Object.assign(target, source, Function func(obj) {obj. Name = 'Tom' console.log(obj)} const obj = {name: 'lili'} func(obj) console.log(obj) function func(obj) { const objNew = Object.assign({}, obj) objNew.name = 'tom' console.log(objNew) } const obj = { name: 'lili' } func(obj) console.log(obj)Copy the code

Object.is() === === === =

Object.is(+0, -0)
Object.is(NaN, NaN)
Copy the code

Proxy Proxy object

object.defineProperty

const person = { name: 'li', age: 25 } cosnt personProxy = new Proxy(person, { get(target, property) { return property in target ? target[property] : 'defalut' }, set(target, property, value) { if(property === 'age') { if(! Number.isInteger(value)) { throw new TypeError(`${value} is not an int`) } } target[property] = value } }) personProxy.gender = true console.log(personProxy.name)Copy the code

Proxy advantage defineProperty can only listen to read and write of object attributes

Proxy advantage can monitor more object operations such as: delete operation,

const person = {
	name: 'li',
    age: 25
}
cosnt personProxy = new Proxy(person, {
	deleteProperty(target, property) {
    	delete target[property]
    }
})
Copy the code

Proxy monitors the reads and writes of objects in a non-intrusive manner

Reflect (static class)

Reflect internally encapsulates a set of low-level operations on an object

const person = {
	name: 'li',
    age: 25
}
console.log('name' in person)
console.log(delete obj['age'])
console.log(Object.keys())

console.log(Reflect.has(obj, 'name'))
console.log(Reflect.deleteProperty(obj, 'age'))
console.log(Reflect.ownKeys(obj))
Copy the code

Set data structure

const s = new Set() s.add(1).add(2).add(3).add(4).add(2) console.log(s) console.log(s.size) console.log(s.has(100)) // Console. log(s.delete(3)) // Delete a value s.clear() // All request scenarios: Const result = Array. From (new Set(arr)) const result = [...new Set(arr)] console.log(result)Copy the code

Map data structure (strictly a set of key-value pairs)

const obj = {} obj[true] = 'value' obj[123] = 'value' obj[{ a: 1 }] = 'value' console.log(Object.keys(obj)) // ['123', 'true', '[object, objecct]'] const m = new Map() const tom = { name: 'Tom'} m.count (Tom, 90) console.log(m) m.count (Tom) m.count () m.count () m.count () m.count () m.count () m.count () m.count () m.count () key) => { console.log(value, key) })Copy the code

Symbol

Shared.js const cache = {} a.js cache['foo'] = math.random () b.js cache['foo'] = '124 '123' What if someone doesn't keep this agreement? Log (Symbol() === Symbol())) // false Scenario: Const name = Symbol() const person = {[name]: '234', say() {console.log(this[name])}} person[Symbol] Const s1 = Symbol. For ('foo') const S2 = Symbol. For ('foo') console.log(s1 === s2) // true console.log(Symbol.for(true) === Symbol.for('true')) // trueCopy the code

Promise (a better asynchronous programming)

const promise = new Promise(function (resolve, reject) { resolve(100) reject(new Error('promise rejected')) }) promise.then(function (value) { console.log('resolve', Function (error) {console.log('rejected', error)})  function ajax(url) { return new Promise(function (resolve, reject) { let xhr = new XMLHttoRequest() xhr.open('GET', url) xhr.responseType = 'json' xhr.onload = function() { if(this.status === 200) { resolve(this.response) } else { reject(new Error(this.statusText)) } } xhr.send() }) } let promise = ajax('www.www.com') let pronise2 = promise.then( function onFullfilled(value) { console.log('onFullfilled', value) }, function onRejected(error) { console.log('onRejected', Error)}) solution callback inferno ajax(' API ').then(function (value)) {console.log(111) return ajax('/ API /a')}).then(function (value)) (value)) { console.log(222) return ajax('/api/b') }) .then(function (value)) { console.log(333) return ajax('/api/c') })  .catch(function (error) { console.log(error) })Copy the code

Parallel execution

const urls = [
    'https://api.github.com',
    'https://api.github.com/users',
    'https://api.github.com/uasdfs/asdfad'
]
const promises = urls.map(item => { axios(item).catch(e => ({})) })

const promise = Promise.allSettled(urls.map(item => axios(item)))
promise.then(res => console.log(res))

Copy the code

Async/Await

async function main () {
  try {
      const users = await ajax('/api')
      console.log(users)
  } catch (e) {
      console.log(e)
  }
}
main()
Copy the code

The Iterator (Iterator)

const set = new Set(['foo', 'bar', 'baz']) const iterator = set[Symbol.iterator]() console.log(iterator.next()) console.log(iterator.next()) Console.log (iterator.next()) console.log(iterator.next()) console.log(iterator.next()) console.log(iterator.next() obj = { [Symbol.iterator]: function() { return { next: function() { return{ value: 'test', done: True}}}}} for(const item of obj) {console.log(' body ') // will not be executed.  const obj = { store: ['foo' , 'bar', 'baz'], [Symbol.iterator]: function() { let index = 0 const self = this return { next: function() { const reult = { value: self.store[index], done: Index >= self.store. Length} index++ return result}}}} for(const item of obj) {console.log(' loop body ', item)}Copy the code

Iterator Design Pattern scenario: You and I thank you for developing a to-do list application

// My code ==================

Const todos = {life: ['eat', 'sleep', 'play doung'], learn: [' Chinese ', 'math', 'English ']}Copy the code

// The code for you

Render the object to the interface for(const item of todos.life) {console.log(item)}, etc. What if my object structure changes? Const todos = {life: ['eat', 'sleep', 'play doung'], learn: [' Chinese ', 'math', 'English '], each: function (callback) { const all = [].concat(this.life, This.learn) for(const item of all) {callback(item)}}} todos.each(function(item) {console.log(item)}) const  todos = { life: ['eat', 'sleep', 'play doung'], learn: ['chinese', 'math', 'english'], [Symbol.iterator]: function() { const all = [...this.life, ...this.learn] let index = 0 return { next: function() { value: all[index], done: index++ >= all.length } } } } for(const item of todos) { console.log(item) }Copy the code

Generator

Avoid deep nesting of callbacks in asynchronous programming and provide better asynchronous programming solutions

function *foo() { console.log('test') return 200 } const result = foo() console.log(result) console.log(result.next()) Function *foo() {console.log('111') yield 100 console.log('222') yield 200} Scene autoid function *createIdMaker() {let ID  = 1 while(true) { yield id++ } } const idMaker = createIdMaker() console.log(idMaker.next().value) console.log(idMaker.next().value) console.log(idMaker.next().value) console.log(idMaker.next().value)Copy the code

Array.includes

Const arr = ['foo', 1, NaN, fale] console.log(arr.indexof(NaN)) // -1 Cannot find NaN console.log(arr.includes) // trueCopy the code

Exponential operator

console.log(Math.pow(2, 10))

console.log(2 ** 10)
Copy the code

Object.values

const obj = {
	foo: 'value1',
    bar: 'value2'
}

console.log(Object.values()) // ['value1', 'value2' ]
Copy the code

Object.entries

console.log(Object.entries()) // [['foo', 'value1'], ['bar', 'value2']]

for(const [key, value]) of Object.entries(obj) {
	console.log(key, value)
}
Copy the code

Object.getOwnPropertyDescriptors

const p1 = { firstName: 'li', lastName: 'xiang', get fullName(){ return this.firstName + ' ' + this.lastName } } console.log(p1.fullName) const p2 = Object.assign({}, P2.firstname = 'wang' console.log(p2.fullname)// Li xiang const descriptors = Object.getOwnPropertyDescriptors(p1) const p2 = Object.defineProperties({}, descriptors) p2.firstName = 'wang' console.log(p2.fullName) // wang xiangCopy the code

String.prototype.padStart / String.prototype.padEnd

const obj = { html: 5, css: 23, javascript: 234 } for(const [name, count] of Object.entries(obj)) { console.log(`${name.padEnd(16, '-')} | ${count.padStart(3, '0')}} `)Copy the code