let 与 const
let
let a = 1
let b = 2,
c = 3
console.log(a, b, c) // 1 2 3
let
用于声明一个块级作用域的变量,所以它不会造成变量提升。声明后的变量不允许重复声明。let
解决了 var
造成变量提升、覆盖和泄露等问题。
const
const a = 1
console.log(a) // 1
const
用于声明常量,即不允许重新赋值(修改变量指向的内存地址)和重复声明。const
也不会造成变量提升。
有关 var
、let
与 const
的详细介绍,可以参考 JS:var、let 与 const 总结
解构
对象解构
基础用法
const tom = {
name: "Tom",
age: 18,
city: "Beijing",
}
const { name, age } = tom
console.log(name, age) // Tom 18
属性重命名
const { name: myName } = tom
console.log(myName) // Tom
设置默认值
const { city, country = "China" } = tom
console.log(city, country) // Beijing China
数组解构
const arr = [1, 2, 3]
const [a, b, c] = arr
console.log(a, b, c) // 1 2 3
如果数组的长度不一致,可以使用 ...
来解构,只保留长度一致的部分。
const arr = [1, 2, 3]
const [a, ...rest] = arr
console.log(a, rest) // 1 [2, 3]
const [a, b, c, ...rest] = arr
console.log(a, b, c, rest) // 1 2 3 []
参数解构
function foo({ name, age }) {
console.log(name, age)
}
foo({ name: "Tom", age: 18 }) // Tom 18
function bar([a, b, c]) {
console.log(a, b, c)
}
bar([1, 2, 3]) // 1 2 3
字符串解构
const str = "hello"
const [a, b, c] = str
console.log(a, b, c) // h e l l
字符串相关
模板字符串
const name = "Tom"
const age = 18
const str = `Hello, I'm ${name}, ${age} years old.`
console.log(str) // Hello, I'm Tom, 18 years old.
模板字符串的出现,是字符串的一个重要特性,它可以提供更加灵活的字符串拼接方式。
startsWith()
startsWith()
方法用于判断字符串是否以指定的字符串开头,如果是,返回 true,否则返回 false。
const str = "hello"
console.log(str.startsWith("h")) // true
console.log(str.startsWith("e")) // false
endsWith()
startsWith()
的兄弟,用于判断字符串是否以指定的字符串结尾,如果是,返回 true,否则返回 false。
const str = "hello"
console.log(str.endsWith("o")) // true
console.log(str.endsWith("e")) // false
includes()
用于判断字符串是否包含指定的字符串,如果是,返回 true,否则返回 false。
const str = "hello"
console.log(str.includes("h")) // true
console.log(str.includes("e")) // true
console.log(str.includes("x")) // false
repeat()
用于将一个字符串重复 n 次,如果 n 是小于 1 的数值,则返回一个空字符串。
const str = "ha~"
console.log(str.repeat(3)) // ha~ha~ha~
数字相关
Math.sign()
用于获取一个数的符号,如果是正数,则返回 1,如果是负数,则返回 -1,如果是 0,则返回 0。
const a = -3
const b = 0
const c = 3
console.log(Math.sign(a)) // -1
console.log(Math.sign(b)) // 0
console.log(Math.sign(c)) // 1
数组相关
Array.from()
用于将一个伪数组(也成为类数组)或者可迭代对象转换成一个真正的数组。
将伪数组转换为数组
const arrayLike = {
0: "a",
1: "b",
2: "c",
length: 3,
}
console.log(Array.from(arrayLike)) // ['a', 'b', 'c']
将字符串转换为数组
const str = "hello"
console.log(Array.from(str)) // ['h', 'e', 'l', 'l', 'o']
将 Set 转换为数组
const mySet = new Set([1, 2, 3])
console.log(Array.from(mySet)) // [1, 2, 3]
将 Map 转换为数组
const myMap = new Map([
["a", 1],
["b", 2],
["c", 3],
])
console.log(Array.from(myMap)) // [['a', 1], ['b', 2], ['c', 3]]
Array.of()
Array.of()
用于将一组值(用逗号隔开)转换成一个数组。
const arr = Array.of(1, 2, 3)
console.log(arr) // [1, 2, 3]
find()
用于获取数组中满足条件(函数形式返回)的第一个元素。
const studentList = [
{
id: 1,
name: "Tom",
age: 12,
},
{
id: 2,
name: "Jerry",
age: 13,
},
{
id: 3,
name: "Bob",
age: 11,
},
]
const student = studentList.find(item => item.age === 13)
console.log(student) // { id: 2, name: 'Jerry', age: 13 }
findIndex()
用于获取数组中满足条件的第一个元素的索引。
const studentList = [
{
id: 1,
name: "Tom",
age: 12,
},
{
id: 2,
name: "Jerry",
age: 13,
},
{
id: 3,
name: "Bob",
age: 11,
},
]
const index = studentList.findIndex(item => item.age === 13)
console.log(index) // 1
fill()
fill()
方法用于用指定值填充数组。
const arr = [1, 1, 1, 1, 1]
console.log(arr.fill(0)) // [0, 0, 0, 0, 0]
console.log(arr.fill(0, 1)) // [1, 0, 0, 0, 0]
console.log(arr.fill(0, 1, 3)) // [1, 0, 0, 1, 1]
其中第一个参数就是指定值,第二个参数为起始索引,默认为 0,第三个参数为终止索引,默认为数组的长度,即填充到最后一位。
对象
Object.assign()
Object.assign()
用于将所有可枚举属性的值从一个或多个源对象复制(浅拷贝)到目标对象。
const groupA = {
a: 1,
b: 2,
c: 3,
}
const groupB = {
b: 4,
c: 5,
d: 6,
}
const all = Object.assign(groupA, groupB)
console.log(all) // { a: 1, b: 4, c: 5, d: 6 }
对于重复的元素,将以后面的(最新的)为准。
简洁表示法
ES6 允许在对象 {}
里面,直接写入变量或函数名,然后作为对象内的属性名。
const str = "hello"
const arr = [1, 2, 3]
const obj = {
str, // 等同于 str: str
arr, // 等同于 arr: arr
num: 1,
}
console.log(obj) // { str: 'hello', arr: [1, 2, 3], num: 1 }
在函数内也可以:
function test() {
let x = 1,
y = 2
return { x, y }
}
console.log(test()) // { x: 1, y: 2 }
函数
箭头函数
const foo = () => {
console.log("foo")
}
foo() // foo
箭头函数的语法比函数表达式更简洁,并且没有自己的 this,arguments,super 或 new.target。很适用于需要匿名函数的地方。
const arr = [1, 2, 3, 4, 5]
const bigger = arr.filter(item => item >= 3)
console.log(bigger) // [ 3, 4, 5 ]
参数默认值
function foo(x = 1, y = 2) {
console.log(x, y)
}
foo() // 1 2
foo(2) // 2 2
foo(2, 3) // 2 3
foo(undefined, 3) // 1 3
参数展开
function foo(x, y, ...rest) {
console.log(x, y, rest)
}
foo(1, 2, 3, 4, 5) // 1 2 [3, 4, 5]
...
一般放在参数的最后一位,用于获取函数调用时所有未被使用的参数。
新的数据结构
Set
const set = new Set([1, 2, 3, 4, 5])
console.log(set.has(1)) // true
console.log(set.has(6)) // false
console.log(set.size) // 5
Set
数据结构是一个无序的集合,每个元素都唯一。
Map
Map
和对象 {}
类似,都是一些键值对的集合。但是更加灵活。
const map = new Map()
map.set("a", 1)
console.log(map) // Map(1) { 'a' => 1 }
Map
的键可以是任意值,甚至可以是函数、对象
function b() {}
map.set(b, 2)
console.log(map) // Map(2) { 'a' => 1, [Function: b] => 2 }
Map
可以直接被迭代
map.forEach((value, key) => {
console.log(key + " = " + value)
})
// 输出
// a = 1
// function b() {} = 2
Map
的键值对个数可以通过 size
获取
console.log(map.size) // 2
通用
扩展运算符(展开语法)
const arr = [1, 2]
console.log(...arr) // 1 2
const str = "hello"
console.log(...str) // h e l l o
for in
const obj = { a: 1, b: 2 }
for (let key in obj) {
console.log(key) // a b
}
for in
可以遍历对象的键名。
for of
const arr = [1, 2]
for (let item of arr) {
console.log(item) // 1 2
}
for of
可以遍历数组的成员。
class
class Student {
constructor(name) {
this.name = name
}
sayName() {
console.log(`My name is ${this.name}`)
}
}
const student = new Student("Bob")
student.sayName() // My name is Bob
class
关键字用于创建一个类。可以理解为 ES5 的构造函数的语法糖。
关于构造函数与 class
,可以参考 JS:构造函数总结。
Promise
const asyncFunc = new Promise((resolve, rejcet) => {
Math.random() > 0.5 ? resolve("fulfilled") : rejcet("rejected")
})
asyncFunc
.then(data => {
console.log(data) // fulfilled
})
.catch(err => {
console.log(err) // rejected
})
.finally(() => {
console.log("finally")
})
Promise
是 ES6 新增的一种异步操作解决方案。Promise
对象的状态可以有 3 个:pending
、fulfilled
和 rejected
。当状态发生改变时,会触发相应的回调函数。
关于更多 Promise
的介绍,可以参考:JS:手写实现 Promise。
async/await
async function hello() {
return await Promise.resolve("Hello")
}
hello().then(console.log) // Hello
async/await
是 ES2017 中新增的异步解决方案。简单来说,它们是基于 Promise
的语法糖,使异步代码更易于编写和阅读。
async
函数返回一个 Promise
对象,await
关键字只能用在 async
函数中,不能用在其他函数中。
关于更多 async/await
的介绍,可以参考 JS:async/await 总结。
Proxy
Proxy 用于创建一个对象的代理,从而实现基本操作的拦截和自定义(如属性查找、赋值、枚举、函数调用等)。可以代理任何对象,包括数组。可以直接监听整个对象而非属性,比 Object.defineProperty()
更加简洁,更加高效,更加安全。
Proxy 返回的一个新对象,可以只操作新的对象达到目的。
const cat = {
name: "Tom",
}
const myCat = new Proxy(cat, {
get(target, property) {
console.log(`我的 ${property} 被读取了`)
return property in target ? target[property] : undefined
},
set(target, property, value) {
console.log(`我的 ${property} 被设置成了 ${value}`)
target[property] = value
return true
},
})
myCat.name // expected output: 我被读取了:name
myCat.name = "Kitty" // expected output: 我的 name 被设置成了 Kitty
Reflect
Reflect 对象主要用于访问和修改对象的属性。
const cat = {
name: "Tom",
}
Reflect.set(cat, "age", 5)
console.log(Reflect.get(cat, "name")) // Tom
console.log(cat.age) // 5
console.log(Reflect.has(cat, "name")) // true
console.log(Reflect.ownKeys(cat)) // ['name', 'age']
Reflect
和 Object
看似雷同,但存在许多差异,具体可以参考 比较 Reflect 和 Object 方法。
Symbol
const mySymbol = Symbol()
console.log(typeof mySymbol) // "symbol"
console.log(Symbol() === Symbol()) // false
Symbol
是 ES6 新增的一种基本数据类型。Symbol
表示一个独一无二的值。
Generator
Generator 是 ES6 新增的一种异步编程模型。
Generator 函数是一个状态机,遇到 yield
就会暂停执行,并返回一个 { value, done }
的对象,value
属性表示返回的值,done
属性表示是否完成。
function* helloWorldGenerator() {
yield "hello"
yield "world"
return "ending"
}
const hw = helloWorldGenerator()
console.log(hw.next()) // { value: 'hello', done: false }
console.log(hw.next()) // { value: 'world', done: false }
console.log(hw.next()) // { value: 'ending', done: true }
Module
Module
是 ES6 新增的模块化语法,可以将代码拆分成多个文件,并且可以通过 import
和 export
来导入和导出。
// math.js
export function add(x, y) {
return x + y
}
// app.js
import { add } from "./math"
console.log(add(1, 2)) // 3
如何将 ES6+ 转换为 ES5
-
为什么要将 ES6+ 转换为 ES5?
因为 ES6+ 是 JavaScript 的新语法,我们虽然可以在开发时使用,但是直接运行在浏览器中的话,许多语法浏览器是不支持的,所以要将 ES6+ 转换为 ES5。
-
安装 Babel
Babel 是一个 JavaScript 编译器,可以将 ES6+ 转换为 ES5。
npm i @babel/core babel-loader @babel/preset-env -D
@babel/core
是 Babel 的核心包。babel-loader
是 Webpack 的 loader,用于在 Webpack 打包时调用 Babel,从而将 ES6+ 转换为 ES5。@babel/preset-env
提供了一些预置的 Babel 配置,这是一个智能预设,只要安装这一个 preset,就会根据你设置的目标浏览器,自动将代码中的新特性转换成目标浏览器支持的代码。-D
表示安装到package.json
中的开发依赖。 -
在 Webpack 中使用 Babel
module.exports = { module: { rules: [ { test: /\.js$/, exclude: /node_modules/, use: { loader: "babel-loader", options: { presets: ["@babel/preset-env"], }, }, }, ], }, }
参考资料: