作为后端开发,工作中也经常需要开发后台页面,而无论是使用哪种Web前端框架都是要使用JavaScript开发的。这门语言经过多年的发展,不仅出现了ES2015这样的现代JavaScript标准,也出现了TypeScript这样的具有类型系统且可编译为JavaScript代码的语言。
之前写js代码基本就是参考着已有代码写,或者遇到不会的Google一下,这个月每天花二十分钟在excuteprogram 上学习了js相关的4个课程(JavaScript Array、Modern JavaScript、TypeScript、Regex),都是基本的语法,好处是可以边学边练印象更深刻了。这里把常用的一些语法记录下备查。
JavaScript Array BASICS 1 2 3 4 5 6 > a.length array length > a[i] get index i > a[i] = x store x at index i
STACK 1 2 3 4 > a.push(x) append x to array a > a.pop() remove last element of a
FOR EACH 1 2 > a.forEach(f) call f on each element
SLICE 1 2 3 4 5 6 > [10 ,20 ,30 ].slice(1 ) [20 , 30 ] > [10 ,20 ,30 ].slice(1 , 2 ) [20 ] > a.slice() copy array
MAP 1 2 > a.map(f) [f(a[0 ]), f(a[1 ]), ...]
SLICE WITH NEGATIVE ARGUMENTS 1 2 3 4 > [10 , 20 , 30 , 40 , 50 ].slice(-2 ) [40 , 50 ] > [10 , 20 , 30 ].slice(-3 , -1 ) [10 , 20 ]
JOIN 1 2 3 4 5 6 > [1 , 2 ].join() '1,2' > [1 , 2 ].join('' ) '12' > [1 , 2 ].join('_' ) '1_2'
CONCAT 1 2 > a1.concat(a2) combine two arrays
INCLUDES 1 2 3 4 > [10 , 20 ].includes(10 ) true > [10 , 20 ].includes(30 ) false
REDUCE 1 2 > [1 ,2 ].reduce((sum, x ) => sum + x) 3
INDEX OF NEW AND FILL 1 2 3 4 5 6 > new Array (2 ).length 2 > new Array (2 )[0 ] undefined > new Array (2 ).fill('a' ) ['a' , 'a' ]
FILTER 1 2 3 4 > [1 , 2 ].filter(x => x > 1 ) [2 ] > [1 , 2 ].filter(x => x < 3 ) [1 , 2 ]
SORT 1 2 3 4 5 6 > ['a' , 'b' ].sort() ['a' , 'b' ] > [10 , 2 ].sort() [10 , 2 ] > [10 , 2 ].sort((x, y ) => x - y) [2 , 10 ]
FIND INDEX 1 2 > [5 , 6 ].findIndex(x => x === 6 ) 1
SOME AND EVERY 1 2 3 4 > [10 , 20 ].some(x => x > 10 ) true > [10 , 20 ].every(x => x > 10 ) false
SHIFT 1 2 3 4 > a.shift() remove element 0 > a.unshift(x) insert at element 0
FIND 1 2 3 4 > [10 , 20 ].find(x => x > 10 ) 20 > [10 , 20 ].find(x => x < 0 ) undefined
REVERSE 1 2 > [1 , 2 ].reverse() [2 , 1 ]
REDUCE RIGHT 1 2 > ['a' ,'b' ].reduceRight((a,x )=> a+x) 'ba'
EMPTY SLOTS 1 2 3 4 5 6 > new Array (1 )[0 ] undefined > 0 in ['something' ] true > 0 in new Array (1 ) false
FLAT AND FLATMAP 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 > [ [1 , 2 ], [3 , 4 ] ].flat() [1 , 2 , 3 , 4 ] > [ [1 , 2 ], [ 3 , [4 ] ] ].flat(1 ) [1 , 2 , 3 , [4 ]] > [ {numbers : [1 , 2 ]}, {numbers : [3 , 4 ]}, ].flatMap(obj => obj.numbers) [1 , 2 , 3 , 4 ]
Modern JavaScript Modern JavaScript features, from ES5 (released in 2009) through ES2017
STRICT MODE 1 2 3 4 5 6 > function defineX ( ) { x = 1 return 'ok' } defineX() ReferenceError : x is not defined
LET 1 2 3 4 5 > if (true ) { let x = 1 } x ReferenceError : x is not defined
CONST 1 2 3 > const x = 1 x = 2 TypeError : Assignment to constant variable.
FOR OF LOOPS 1 2 3 4 5 6 7 > const letters = ['a' , 'b' , 'c' ] const result = [] for (const letter of letters) { result.push(letter) } result ['a' , 'b' , 'c' ]
REST PARAMETERS 1 2 3 4 5 > function f (...args ) { return args } f(1 , 2 , 3 ) [1 , 2 , 3 ]
TEMPLATE LITERALS 1 2 > `1 + 1 = ${1 + 1 } ` '1 + 1 = 2'
ACCESSORS IN OBJECT LITERALS 1 2 3 4 5 6 > const user = { realName: 'Amir' , get name() { return this .realName }, set name(newName) { this .realName = newName }, } undefined
BASIC ARRAY DESTRUCTURING 1 2 3 4 5 6 7 8 > const letters = ['a' , 'b' , 'c' ] const [a, b, c, d] = letters; [c, d] ['c' , undefined ] > const letters = ['a' , 'b' , 'c' ] const [a, ...others] = letters others ['b' , 'c' ]
COMPUTED PROPERTIES 1 2 3 4 5 > const loginCounts = { ['Be' + 'tty' ]: 7 } loginCounts.Betty 7
BASIC OBJECT DESTRUCTURING 1 2 3 4 5 6 7 8 > const user = {name : 'Amir' , email : 'amir@example.com' , age : 36 } const {name, age} = user; [name, age] ['Amir' , 36 ] > const key = 'NaMe' const {[key.toLowerCase()]: value} = {name : 'Amir' } value 'Amir'
SHORTHAND PROPERTIES 1 2 3 4 5 6 7 8 > const name = 'Amir' const catName = 'Ms. Fluff' const city = 'Paris' const age = 36 const user = {name, catName, city, age}; [user.name, user.age] ['Amir' , 36 ]
DESTRUCTURING 1 2 3 4 5 6 7 8 9 > function city ({address: {city}} ) { return city } city({name : 'Amir' , address : {city : 'Paris' }}) 'Paris' > const users = [{name : 'Amir' }, {name : 'Betty' }] const [, {name}] = users name 'Betty'
SHORTHAND METHODS 1 2 3 4 5 6 7 > const address = { city: 'Paris' , country: 'France' , addressString() { return `${this .city} , ${this .country} ` }, } address.addressString() 'Paris, France'
BIND 1 2 3 4 5 6 7 > const user = {name : 'Amir' } function userName ( ) { return this .name } const userNameBound = userName.bind(user) userNameBound() 'Amir'
ARROW FUNCTIONS 1 2 3 4 5 6 7 8 9 > [1 , 2 , 3 ].map(x => x * 2 ) [2 , 4 , 6 ] > const user = {name : 'Amir' } const getName = ({name} ) => name getName(user) 'Amir' > const rest = (first, ...rest ) => rest rest(1 , 2 , 3 , 4 ) [2 , 3 , 4 ]
CLASSES 1 2 3 4 5 6 7 8 9 10 11 12 13 > class Cat { constructor (name, vaccinated) { this .name = name this .vaccinated = vaccinated } needsVaccination() { return !this .vaccinated } } new Cat('Ms. Fluff' , true ).needsVaccination() false
EXTENDING CLASSES 1 2 3 4 5 6 7 8 9 10 11 12 13 14 > class Animal { constructor (name) { this .name = name } } class Cat extends Animal { constructor (name) { super (name + ' the cat' ) } } new Cat('Ms. Fluff' ).name 'Ms. Fluff the cat'
FUNCTION NAME PROPERTY 1 2 3 4 5 6 7 8 9 > ( function ( ) { return 5 } ).name '' > const f = function ( ) { return 5 } const f2 = f f2.name 'f'
ANONYMOUS AND INLINE CLASSES 1 2 3 4 5 6 7 8 > new ( class { speak() { return 'yaong' } } )().speak() 'yaong'
ACCESSOR PROPERTIES ON CLASSES 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 > class User { constructor (name) { this .actualName = name } get name() { return `${this .actualName} the user` } } new User('Betty' ).name 'Betty the user' > class User { constructor (name) { this .actualName = name } set name(newName) { this .actualName = newName } } const user = new User('Amir' ) user.name = 'Betty' user.actualName 'Betty'
DEFAULT PARAMETERS 1 2 3 4 5 > function add (x, y=0 ) { return x + y } [add(1 , 2 ), add(1 )] [3 , 1 ]
JSON STRINGIFY AND PARSE 1 2 3 4 5 6 7 8 9 10 11 12 > JSON .stringify({a : 2 }) === '{"a":2}' true > JSON .parse('{"a": 1, "b" : 2}' ) {a : 1 , b : 2 } > const user = { name: 'Amir' , toJSON: () => 'This is Amir!' } JSON .parse(JSON .stringify(user)) 'This is Amir!'
STRING KEYED METHODS 1 2 3 4 5 > const user = { 'name of the ~user~' () { return 'Betty' } } user['name of the ~user~' ]() 'Betty'
STATIC METHODS 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 > class User { static getUserName(user) { return user.name } } User.getUserName({name : 'Amir' }) 'Amir' > class User { static get defaultName() { return 'Amir' } } User.defaultName 'Amir'
COMPUTED METHODS AND ACCESSORS 1 2 3 4 5 6 7 8 9 10 11 12 > class User { constructor (name) { this .name = name } get ['user' + 'Name']() { return this .name } } new User('Betty' ).userName 'Betty'
SYMBOL BASICS 1 2 3 4 5 6 7 8 9 10 11 12 > Symbol ('a' ) === Symbol ('a' ) false > const obj = {} obj[true ] = 1 Object .keys(obj) ['true' ] > const nameSymbol = Symbol ('name' ) const user = {[nameSymbol]: 'Amir' } user[nameSymbol] 'Amir'
SYMBOLS 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 > class User { constructor (name) { this [Symbol .toStringTag] = name } } const user = new User('Amir' ) user.name = 'Betty' user.toString() '[object Amir]' > const user = { name: 'Amir' , [Symbol .toStringTag]: 'Amir' } JSON .parse(JSON .stringify(user)) {name : 'Amir' }
ISNAN 1 2 3 4 5 6 7 8 > isNaN (undefined ) true > Number .isNaN(undefined ) false > Number .isNaN(NaN ) true
NEW NUMBER METHODS 1 2 3 4 5 6 7 8 > Number .isFinite(-Infinity ) false > Number .isSafeInteger(Number .MAX_SAFE_INTEGER + 1 ) false > 2 ** 8 256
DEFINING ITERATORS 1 2 3 4 5 6 7 8 9 10 11 12 13 > const letters = ['a' , 'b' , 'c' ] const iterator = letters[Symbol .iterator]() iterator.next() iterator.next() {done : false , value : 'b' } > const letters = ['a' , 'b' , 'c' ] const iterator = letters[Symbol .iterator]() iterator.next() iterator.next() iterator.next() iterator.next() {done : true , value : undefined }
GENERATORS 1 2 3 4 5 6 7 > function * numbersBelow (maximum ) { for (let i=0 ; i<maximum; i++) { yield i } } Array .from(numbersBelow(3 )) [0 , 1 , 2 ]
PROBLEMS WITH OBJECT KEYS 1 2 3 4 5 6 > const obj = { [{key1 : 'value1' }]: 1 , [{key2 : 'value2' }]: 2 , } Object .keys(obj) ['[object Object]' ]
ITERATORS 1 2 3 4 5 6 7 8 9 10 11 12 13 > function * letters ( ) { yield 'a' yield 'b' yield 'c' } const [, b, c] = letters(); [b, c] ['b' , 'c' ] > const notAnIterator = 5 for (const x of notAnIterator) { } TypeError : notAnIterator is not iterable
MAPS 1 2 3 4 5 6 7 8 9 10 11 12 > const userEmails = new Map ([ ['Amir' , 'amir@example.com' ], ['Betty' , 'betty@example.com' ] ]) userEmails.get('Betty' ) 'betty@example.com' > const emails = new Map () emails.set('Betty' , 'betty.j@example.com' ) emails.set('Betty' , 'betty.k@example.com' ) emails.get('Betty' ) 'betty.k@example.com'
SETS 1 2 3 4 5 6 7 8 9 10 > const names = new Set (['Amir' , 'Betty' , 'Cindy' ]) names.add('Dalili' ) names.has('Dalili' ) true > const names = new Set (['Amir' ]) names.add('Betty' ) names.add('Betty' ) Array .from(names.values()) ['Amir' , 'Betty' ]
TAGGED TEMPLATE LITERALS 1 2 3 4 5 6 7 8 9 10 11 12 > function doubleNumbers (strings, ...values ) { let result = '' for (let i=0 ; i<strings.length; i++) { result += strings[i] if (i < values.length) { result += (2 * values[i]).toString() } } return result } doubleNumbers`the numbers ${1 } and ${2 } ` 'the numbers 2 and 4'
SPREAD 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 > const numbers = [ 1 , ...[2 , 3 ], 4 , ] numbers [1 , 2 , 3 , 4 ] > const amir = { name: 'Amir' , age: 36 , } const amirWithEmail = { ...amir, email: 'amir@example.com' } amirWithEmail {age : 36 , email : 'amir@example.com' , name : 'Amir' }
CLASS SCOPING 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 > function createGorilla (name ) { class Gorilla { constructor () { this .name = name } } return new Gorilla() } createGorilla('Michael' ).name 'Michael' > if (true ) { class Cat { } } new Cat() ReferenceError : Cat is not defined
CUSTOMIZING JSON SERIALIZATION 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 > JSON .parse( JSON .stringify( {name : 'Amir' , age : 36 , city : 'Paris' }, ['name' , 'city' ] ) ) {city : 'Paris' , name : 'Amir' } > JSON .parse( JSON .stringify( {name : 'Amir' , catName : 'Ms. Fluff' , city : 'Paris' }, (key, value) => { if (key === 'catName' ) { return undefined } else { return value } } ) ) {city : 'Paris' , name : 'Amir' } > JSON .parse( `{"name": "Amir", "age": 36}` , (key, value) => { if (key === 'age' && value === 36 ) { return 'thirty six' } else { return value } } ) {age : 'thirty six' , name : 'Amir' }
PROPERTY ORDER 1 2 3 4 5 > const user = {name : 'Amir' , age : 36 } user.email = 'amir@example.com' Object .keys(user) ['name' , 'age' , 'email' ]
MAP ITERATORS 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 > const catAges = new Map ([ ['Ms. Fluff' , 4 ], ['Keanu' , 2 ], ]) Array .from(catAges.keys()) ['Ms. Fluff' , 'Keanu' ] > const catAges = new Map ([ ['Keanu' , 2 ], ['Ms. Fluff' , 4 ], ]) Array .from(catAges.values()) [2 , 4 ] > const emails = new Map () emails.set('Amir' , 'amir@example.com' ) emails.set('Betty' , 'betty@example.com' ) Array .from(emails) [['Amir' , 'amir@example.com' ], ['Betty' , 'betty@example.com' ]]
SET OPERATIONS 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 > const set1 = new Set ([1 , 2 , 3 ]) const set2 = new Set ([2 , 3 , 4 ]) const unionSet = new Set ([...set1, ...set2]); [unionSet.has(1 ), unionSet.has(4 )] Array .from(unionSet) [1 , 2 , 3 , 4 ] > const set1 = new Set ([1 , 2 , 3 ]) const set2 = new Set ([2 , 3 , 4 ]) const intersectionSet = new Set ( Array .from(set1).filter(n => set2.has(n)) ); Array .from(intersectionSet) [2 , 3 ] > const set1 = new Set ([1 , 2 , 3 ]) const set2 = new Set ([2 , 3 , 4 ]) const differenceSet = new Set ( Array .from(set1).filter(n => !set2.has(n)) ); Array .from(differenceSet) [1 ]