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