ES
ES
一、var, let 以及 const的区别
const 只读变量
const name = "Lydia";
// 报错
name = "Juliette";
let 可变变量
let name = "Lydia";
// 不报错
name = "Juliette";
作用域不同
使用var在下面的循环外也能访问变量i
for (var i = 0; i < 100; i++) {
console.log(i)
}
console.log(i)
使用let在下面的循环会出错
for (let i = 0; i < 100; i++) {
console.log(i)
}
console.log(i)
二、箭头函数
简单实例
function getInfo(name, age) {
return `${name}-${age}`
}
console.log(getInfo('name', 21))
// 箭头函数写法
const getInfo2 = (name, age) => {
return `${name}-${age}`
}
console.log(getInfo2('Lydia', 21))
// 可以更简短
const getInfo2 = (name, age) => `${name}-${age}`
console.log(getInfo2('Lydia', 21))
// 如果只有一个参数可以更短
const getInfo2 = name => `${name}`
console.log(getInfo2('Lydia', 21))
对象函数一
注意这两个返回值是不一样的。
var radius = 5
const shape = {
radius: 10,
diameter: function () {
return this.radius * 2
},
// 这里乘的是全局变量var radius = 5
diameter2: () => this.radius * 2
}
// 20
shape.diameter()
// 10
shape.diameter2()
对象函数二
const hero = {
name: 'Super Man',
greet: function () {
setTimeout(
function () {
console.log('Hi, my name is', this.name)
}.bind(this),
1000
)
}
}
// 输出 Hi, my name is Super Man
console.log(hero.greet())
const hero = {
name: 'Super Man',
greet: function () {
setTimeout(
function () {
console.log('Hi, my name is', this.name)
},
1000
)
}
}
// 输出 Hi, my name is
console.log(hero.greet())
const hero = {
name: 'Super Man',
greet: function () {
setTimeout(() => {
console.log('Hi, my name is', this.name)
},
1000
)
}
}
// 用箭头函数可以获取到name变量
console.log(hero.greet())
三、Template Literals
简单实例
// 老写法
function sayHi(name) {
return 'Hello, ' + name
}
console.log(sayHi('Hi'))
// Template Literals
function sayHi(name) {
return `Hello, ${name}!`
}
console.log(sayHi('Hi'))
// Template Literals
const baseUrl = 'https://api.themoviedb.org/3/'
fetch(`${baseUrl}/people/1`)
.then(res => res.json())
.then(json => console.log(json))
const sum = (a, b) => `Sum: ${a + b}`
console.log(sum(1, 3))
const box = document.getElementById('box')
box.style.backgroundColor = 'purple'
const input = document.getElementById('input_box')
input.addEventListener('change', handleUpdate)
function handleUpdate(e) {
box.style.height = `${parseInt(e.target.value) * 2}px`
box.style.width = `${parseInt(e.target.value) * 2}px`
}
换行
// 换行要打]n
const result = 'Sarah : 1\nPeter: 2'
console.log(result)
// 新写法直接会车
const result = `Sarah : 1
Peter: 2`
console.log(result)
直接当参数用
const greet = (greeting, name, age) => {
console.log(greeting)
console.log(name)
console.log(age)
}
const name = 'Lydia'
const age = 5
greet`My name is ${name} and age is ${age}`
四、参数简写
// es6 之前
function createPerson(name, age, admin) {
return {
name: name,
age: age,
isAdmin: admin
}
}
console.log(createPerson('Lydia', 21, false))
// es6之后
function createPerson(name, age, admin) {
return {
name,
age,
isAdmin: admin
}
}
console.log(createPerson('Lydia', 21, false))
五、直接增加对象的键值
const specialProperty = 'nationality'
const person = {
name: 'John',
age: 5,
isAdmin: false
}
person[specialProperty] = 'German'
console.log(person)
// es6可以直接在对象里面新增
const specialProperty = 'nationality'
const person = {
name: 'John',
age: 5,
isAdmin: false,
[specialProperty]: 'German'
}
console.log(person)
六、函数参数
默认参数
function greeting(name = 'Lydia') {
return `Hello there ${name}`
}
console.log(greeting('John'))
console.log(greeting())
function logMessage(message, prefix = getDate()) {
console.log(`${prefix}${message}`)
}
logMessage('I like turtles!')
logMessage('I applied CSS styles', '😂')
多参数,迭代
function sum(a, b, ...values) {
console.log(values)
return a + b
}
console.log(sum(1, 2, 1,2,3))
// 计算values的内容
function sum(a, b, ...values) {
let sum = a + b
values.forEach(value => (sum += value))
return a + b
}
console.log(sum(1, 2, 1, 2, 3))
组合对象
const user = { name: 'John', email: 'john@example.com' }
const cart = {
items: [{ name: 'shirt', quantity: 1 }, { name: 'coat', quantity: 2 }]
}
const deliveryAddress = {
street: '100 Main Street',
city: 'Main City',
state: 'Main State'
}
const purchase = {
...user,
...cart,
...deliveryAddress
}
console.log(purchase)
七、解构
解构对象
const person = {
name: 'Johon doe',
age: 45
}
// 老写法
// const name = person.name;
// const age = person.age;
const { name, age } = person
console.log(name, age)
定义新名称
const person = {
name: 'Johon doe',
age: 45
}
// 老写法
// const name = person.name;
// const age = person.age;
const { name: memberName, age: memberAge } = person
console.log(memberName, memberAge)
解构数组
const fruit = ['apple', 'banana', 'kiwi']
const [first, second, third] = fruit
console.log(first, second, third)
const team = [
{ name: 'Elon Musk' },
{ name: 'Samsung' },
{ name: 'White' },
{ name: 'Will' }
]
const [boss, ...employee] = team
console.log(boss)
console.log(employee)
就算没定义也可以解,还可以设置默认值
const event = {
name: 'Call with John'
}
const { name, createdAt = new Date() } = event
console.log(name)
console.log(createdAt)
交换值
let [min, max] = [5, 9]
if (min > max) {
[min, max] = [max, min]
}
直接传送一个对象的某个值
function fetchDogs({ breed }) {
fetch(`https://xxxx/api/breed/${breed}/images`)
.then(response => response.json())
.then(data => console.log(data))
.then(error => console.log(error))
}
const dog = {
name: 'Ma',
breed: 'labrador',
color: 'green',
age: 8
}
fetchDogs(dog)
八、函数声明导入
老写法
// 声明
function sum(a, b) {
return a + b
}
module.exports = sum
// 导入
const sum = require('./sum')
console.log(sum(1, 2))
新写法
// 声明
export function sum(a, b) {
return a + b
}
export function multiply(a, b) {
return a * b
}
// 导入
import { sum, multiply } from './sum'
console.log(sum(1, 2))
console.log(multiply(1, 2))
声明函数的另一种写法
function sum(a, b) {
return a + b
}
function multiply(a, b) {
return a * b
}
export { sum, multiply }
导入的时候使用别名
单个函数别名
import { sum as addAll, multiply } from './sum'
console.log(addAll(1, 2))
console.log(multiply(1, 2))
所有函数别名,一般来说不这么操作,因为会导入很多不需要的内容。
import * as Calc from './sum'
console.log(Calc.sum(1, 2))
console.log(Calc.multiply(1, 2))
default 声明
// 声明
export default function sum(a, b) {
return a + b
}
export function multiply(a, b) {
return a * b
}
// 使用,默认函数就不需要大括号了
import sum, { multiply } from './sum'
console.log(sum(1, 2))
console.log(multiply(1, 2))
// sum这里可以随便选名字
import sum, { multiply } from './sum'
console.log(sum(1, 2))
console.log(multiply(1, 2))
九、创建类
ES5
function User(firstName, lastName) {
this.firstName = firstName
this.lastName = lastName
this.getFullName = function () {
return this.firstName + ' ' + this.lastName
}
}
const admin = new User('admin', 'Doe')
console.log(admin.getFullName())
ES6
class User {
constructor(name, email, password) {
this.name = name
this.email = email
this.password = password
}
getFullName() {
return `${this.name} ${this.email}`
}
}
const admin = new User('John', 'Doe', '6666')
console.log(admin.getFullName())
扩展类
class User {
constructor(name, email) {
this.name = name
this.email = email
}
getFullName() {
return `${this.name} ${this.email}`
}
}
class Admin extends User {
constructor(name, email) {
super(name, email)
// 构造函数super必须先执行,才能用this
this.role = 'admin'
}
}
const superUser = new Admin('Will', 'Smith')
console.log(superUser)
十、异步操作
const sayHi = () => console.log('hi')
// setTimeout是异步的,所以sayBye会先出来。
const askAboutDay = () => setTimeout(() => console.log('How was your day?'), 1000)
const sayBye = () => console.log('See you later!')
sayHi()
askAboutDay()
sayBye()
十、Promise
const promiseToWalkDog = new Promise((resolve, reject) => {
let hasWalkedDog = true
if (!hasWalkedDog) {
resolve('I walked the dog!')
} else {
resolve('I didn\'t walk the dog!')
}
})
promiseToWalkDog.then(
(fromResolve) => {
console.log(`Did you walk the dog! ${fromResolve}`)
},
(fromReject) => {
console.log(`Did you walk the dog! ${fromReject}`)
}
)
更清楚的写法
const promiseToWalkDog = new Promise((resolve, reject) => {
let hasWalkedDog = true
if (!hasWalkedDog) {
resolve('I walked the dog!')
} else {
resolve('I didn\'t walk the dog!')
}
})
promiseToWalkDog
.then(fromResolve => console.log(`Did you walk the dog! ${fromResolve}`))
.catch(fromReject => console.log(`Did you walk the dog! ${fromReject}`))
实际例子
function loadImage(url) {
return new Promise((resolve, reject) => {
const request = new XMLHttpRequest()
request.open('GET', url)
request.onload = () => {
if (request.status === 200) {
resolve(JSON.parse(request.responseText))
} else {
reject(`Error: ${request.statusText}`)
}
}
request.send()
})
}
loadImage('https://dog.ceo/api/breeds/image/radom')
.then(resolve => console.log(resolve))
并行执行
let cookFood = () => {
return new Promise(res => res('I cooked food!'))
}
let walkDog = () => {
return new Promise(res => res('I walked the dog!'))
}
let cleanRoom = () => {
return new Promise(res => res('Clean room!'))
}
// 顺序执行
cleanRoom()
.then(() => walkDog())
.then(() => cookFood())
.then(() => console.log('All done!'))
// 改为并行
Promise.all([cleanRoom(), walkDog(), cookFood()])
.then(res => console.log(res))
.catch(err => console.log(err))
第三方API
有时候第三方的函数可能是Promis也有可能不是,可以通过Promis.resolve()
处理,这样能保证我们代码总能正确执行
const myPromis = new Promise(res => res('I am'))
const name = 'Lydia'
Promise.resolve(myPromis).then(res => console.log(res))
Promise.resolve(name).then(res => console.log(res))
十一、Async/Await
原本的异步操作
因为myPromiseFunction是异步的,所以会先输出second
function myPromiseFunction() {
return new Promise(res => res('first'))
}
function firstFunction() {
myPromiseFunction().then(res => console.log(res))
console.log('second')
}
firstFunction()
使用Async/Await等待异步操作
因为使用了async/await,所以会等myPromiseFunction()执行完毕。
function myPromiseFunction() {
return new Promise(res => res('first'))
}
async function secondFunction() {
console.log(await myPromiseFunction())
console.log('second')
}
secondFunction()
async/await改写例子
fetch('http://dog.ceo/api/breeds/image/radom')
.then(res => res.json())
.then(res => console.log(res));
// 用async/await改写
(async () => {
const data = await fetch('http://dog.ceo/api/breeds/image/radom')
const jsonData = await data.json()
console.log(jsonData)
})()
promise和async/wait一样的例子
const myPromise = new Promise(res => res('Hello'))
const makeAsyncRequest = async () => {
await myPromise()
await myPromise()
await myPromise()
}
const makePromiseRequest = () => {
return myPromise()
.then(() => myPromise())
.then(() => myPromise())
.then(() => myPromise())
}
async 总是返回 promise
function myFirstPromise() {
return new Promise(res => res('I resolved!'))
}
async function mySecondPromise() {
return 'I resolved!'
}
myFirstPromise().then(res => console.log(res))
mySecondPromise().then(res => console.log(res))
const getNum = num => Promise.resolve(num)
const getNum2 = async num => num
getNum(5).then(res => console.log(res))
getNum2(5).then(res => console.log(res))
捕获异常
异常实例
async function secondFunction() {
// 这里抛出异常
const data = await Promise.resolve('Oops')
console.log(data)
}
secondFunction()
用try...catch处理
async function fetchUser(id) {
try {
const response = await fetch(`http://127.0.0.1:8000/api/users/${id}`)
return await response.json()
} catch (err) {
console.log(err)
}
}
fetchUser(1)
也可以在调用的时候使用catch
async function fetchUser(id) {
const response = await fetch(`http://127.0.0.1:8000/api/users/${id}`)
return await response.json()
}
fetchUser(1).catch(err => console.log(err))
十二、数组迭代
forEach
const score = [90, 19, 23, 89, 12, 62]
for (const point of score) {
console.log(`${point > 50 ? 'Higher than' : 'Lower than or equal to'} 50`)
}
score.forEach((point) => {
console.log(`${point > 50 ? 'Higher than' : 'Lower than or equal to'} 50`)
})
map
map 返回的也是个数组
const score = [90, 19, 23, 89, 12, 62]
const scoreWords = score.map((point) => {
return point > 50 ? 'higher' : 'lower oe equal'
})
console.log(scoreWords)
返回整数
const numbers = [9.23, 10.23, 5.04, 89.5, 90.34]
const integers = numbers.map(number => Math.round(number))
console.log(integers)
find
返回第一个符合条件的记录
const team = [
{ name: 'John', email: 'john@example.com' },
{ name: 'Johan', email: 'john@example.com' },
{ name: 'Johan2', email: 'john@example.com' },
{ name: 'John', email: 'john@example.com' }
]
function findTeamMemberByName(name) {
return team.find(member => member.name === name)
}
console.log(findTeamMemberByName('John'))
filter
const products = [
{ name: 'Turtle Socks', stock: 0 },
{ name: 'Turtle Shield', stock: 1 },
{ name: 'Wig', stock: 0 },
{ name: 'Samurai Sword', stock: 1 }
]
const productsInStock = products.filter(product => product.stock > 0)
console.log(productsInStock)
const tasks = [
{ task: 'Do dishes', done: false },
{ task: 'Walk dog', done: true },
{ task: 'Do laundry', done: false },
{ task: 'Clean room', done: false },
{ task: 'Cook dinner', done: false }
]
const completedTasks = tasks.filter(task => task.done)
const uncompletedTasks = tasks.filter(task => !task.done)
console.log('Completed:', completedTasks)
console.log('Uncompleted tasks', uncompletedTasks)
console.log('All tasks', tasks)
indexOf
const team = [
{ name: 'John', email: 'john@example.com' },
{ name: 'Johan', email: 'john@example.com' },
{ name: 'Johan2', email: 'john@example.com' },
{ name: 'John', email: 'john@example.com' }
]
const member = team.find(member => member.name === 'Johan2')
console.log(member)
const memberIndex = team.indexOf(member)
console.log(memberIndex)
const firstPart = team.slice(0, memberIndex)
const secondPart = team.slice(memberIndex)
console.log(firstPart)
console.log(secondPart)
不存在会返回-1
const team = [
{ name: 'John', email: 'john@example.com' },
{ name: 'Johan', email: 'john@example.com' },
{ name: 'Johan2', email: 'john@example.com' },
{ name: 'John', email: 'john@example.com' }
]
console.log(team.indexOf(3))
reduce
const team = [
{ name: 'John', email: 'john@example.com', points: 100 },
{ name: 'Johan', email: 'john@example.com', points: 54 },
{ name: 'Johan2', email: 'john@example.com', points: 10 },
{ name: 'John', email: 'john@example.com', points: 90 }
]
// 老姿势
// let points = 0
// for (const member of team) {
// points += team[member.points]
// }
//
// console.log(points)
// 新姿势,设定了500的初始值
const points = team.map(member => member.points)
const totalPoints = points.reduce((acc, cur) => acc + cur,500)
console.log(totalPoints)
组合字符串数组
const members = [
{
name: 'Elon Musk',
companies: ['Tesla', 'SpaceX', 'starlink']
},
{
name: 'Mark Zuckerberg',
companies: ['Facebook', 'WhatsApp', 'Instagram']
},
{
name: 'Jack Dorsey',
companies: ['Twitter', 'Square']
}
]
const memberCompanies = members.reduce((acc, cur) => {
return acc.concat(cur.companies)
}, [])
console.log(memberCompanies)
十三、Map
Map
const map = new Map([[1, 'one'], [2, 'two'], [3, 'three'], [4, 'four']])
console.log(map)
console.log(map.get(1))
map 是有顺序的,object不会
const map = new Map([[2, 'two'], [3, 'three']])
const object = { 2: 'two', 3: 'three' }
map.set(1, 'one')
object[1] = 'one'
console.log(map)
console.log(object)
map的forEach有两个参数,值和键
const map = new Map([[2, 'two'], [3, 'three']])
map.forEach((value, key) => {
console.log(`${key} - ${value}`)
})
购物车逻辑
const cart = new Map()
const shoe = {
id: 0,
name: 'Shoe',
price: 500
}
const shirt = {
id: 1,
name:"shift",
price:100
}
function addToCart(item) {
if (cart.has(item.id)) {
const cartItem = cart.get(item.id)
cartItem.quantity++
} else {
cart.set(item.id, { ...item, quantity: 1 })
}
}
function deleteFromCart(item){
if (cart.get(item.id).quantity > 1){
const cartItem = cart.get(item.id)
cartItem.quantity--;
} else {
cart.delete(item.id)
}
}
addToCart(shoe)
addToCart(shoe)
addToCart(shoe)
addToCart(shoe)
addToCart(shirt)
addToCart(shirt)
deleteFromCart(shoe)
deleteFromCart(shirt)
console.log(shoe)
for (let item of cart.values()) {
console.log(item)
}
console.log("Shoes in cart: ",cart.get(shoe.id).quantity)
console.log("Shirts in cart: ",cart.get(shirt.id).quantity)
console.log("Items in cart: ",cart.size)
十四、Set
去重,但是元素是没有index
const set = new Set([1, 2, 3, 4, 5, 2, 3, 4, 5, 2, 3, 4, 5])
console.log(set[0])
转为数组
const memberCountires = [
'DE',
'USA',
'UK',
'NL',
'ES',
'DE',
'USA',
'CN'
]
const countriesSet = new Set(memberCountires)
countriesSet.add('IT')
const uniqueCountries = [...countriesSet]
console.log(uniqueCountries)
// 清空Set
countriesSet.clear()
十五、String
padStart/padEnd
const phoneNumber = '123456789'
const lastTwoDigits = phoneNumber.slice(7, 10)
const hiddenPhoneNumber = lastTwoDigits.padStart(9, '*')
console.log(hiddenPhoneNumber)
直接转义换行
const members = [
{ name: 'Sarah', points: 100 },
{ name: 'John', points: 84 },
{ name: 'Peter', points: 51 },
{ name: 'Anne', points: 90 }
]
members.map(({ name, points }) => {
console.log(`Name: ${name.padEnd(40)} Points: ${points}`)
})
十五、Object
assign
assign可以用来合并对象,一般来说用来创建一个新的对象。
const name = { firstName: 'John', LastName: 'Doe' }
const auth = { email: 'john@example.com', password: '123456' }
const data = Object.assign(auth, name)
console.log(data)
// 注意name也会改变
console.log(name)
// 如果不想改变name 可以用以下方式合并。
const data = { ...name, ...auth}
嵌套的对象assign之后为引用,修改之后两边都会改动
const person = {
name: 'Lydia',
info: {
country: 'NL'
}
}
const newPerson = Object.assign({}, person)
newPerson.name = 'Sarah'
newPerson.info.country = 'CN'
// name没有问题,但是country都变成CN了。
console.log(person)
console.log(newPerson)
keys/values
const deliveryInfo = {
street: '100 Main St',
postalCode: '11111',
city: 'New Yokr City',
state: 'NY'
}
console.log(Object.keys(deliveryInfo))
console.log(Object.values(deliveryInfo))
const includesState = Object.keys(deliveryInfo).includes('state')
const state = includesState ? deliveryInfo.state : 'CN'
console.log(state)
entries
转换成Map
const deliveryInfo = {
street: '100 Main St',
postalCode: '11111',
city: 'New Yokr City',
state: 'NY'
}
console.log(Object.entries(deliveryInfo))
const deliveryInfoMap = new Map(Object.entries(deliveryInfo))
console.log(deliveryInfoMap)
其他姿势
const deliveryInfo = {
street: '100 Main St',
postalCode: '11111',
city: 'New Yokr City',
state: 'NY'
}
Object.entries(deliveryInfo).forEach((field) => {
const [key, value] = field
console.log(`${key.padEnd(10)} ${value}`)
})
十六、Number
判断是否为number
console.log(isFinite(0))
console.log(isFinite('0'))
// 更安全的判断方式
console.log(Number.isFinite(0))
// 这里'0'就会返回false
console.log(Number.isFinite('0'))
转为number
console.log(parseInt(80.23))
console.log(parseInt("80.23"))
十六、Generators
function getPizzaIngredients() {
console.log('Wheat')
console.log('Tomatoes')
console.log('Ingredients')
console.log('Basil')
}
getPizzaIngredients()
// 改为Generator
function* getPizzaIngredients() {
yield 'Wheat'
yield 'Tomatoes'
yield 'Ingredients'
yield 'Basil'
}
const generatorObject = getPizzaIngredients()
console.log(generatorObject.next())