本文来自于jspang大佬,跟着大佬的博客手撸了一遍。
let 和 const
解构赋值
数组解构
let [a, b, c] = [1, 2, 3]
console.log(a) // 1
console.log(b) // 2
console.log(c) // 3
对象解构
let { foo, bar } = { foo: 'hello', bar: 'world' }
console.log(foo) // hello
console.log(bar) // world
字符串解构
let [a, b, c, d, e] = 'hello'
console.log(a) // h
console.log(b) // e
console.log(c) // l
console.log(d) // l
console.log(e) // o
扩展运算符和 rest 运算符
扩展运算符
function fn(...arg) {
console.log(arg[0])
console.log(arg[1])
console.log(arg[2])
console.log(arg[3])
}
fn(1, 2, 3) //1,2,3,undefined
数组赋值
let arr1 = ['hello', 'world']
let arr2 = [...arr1]
// arr2=arr1 不是真正的赋值,是对堆栈的引用
rest 运算符
function fn(first, ...arg) {
for (let val of arg) {
console.log(val)
}
}
fn(1, 2, 3, 4) // 2,3,4
字符串模板
let world='world'
let blog=`hello${world}
对运算的支持
let a = 1
let b = 2
let result = `${a + b}` // 3
字符串查找
- 查找是否存在
let text = 'world'
let blog = 'hello world'
blog.includes(text) // true
- 判断开头是否存在
let text = 'hello'
let blog = 'hello world'
blog.startsWith(text) // true
- 判断结尾是否存在
let text = 'world'
let blog = 'hello world'
blog.endsWith(text) // true
- 复制字符串
let text = 'world'
text.repeat(3) // worldworldworld
数字操作
整数取值范围操作
let a = Math.pow(2, 53) - 1
console.log(a) // 9007199254740991
- 最大安全整数
console.log(Number.MAX_SAFE_INTEGER) // 9007199254740991
- 最小安全整数
console.log(Number.MIN_SAFE_INTEGER) // -9007199254740991
数字判断和转换
- 数字验证
Number.isFinite(11 / 4) // true
Number.isFinite('hello') // false
- NaN 验证
Number.isNaN(NaN) // true
- 整数判断
Number.isInteger(12) // true
Number.isInteger(1.2) // false
- 安全整数判断
Number.isSafeInteger(Number.MAX_SAFE_INTEGER) // true
新增的数组知识
JSON 数组格式转换
这就是一个标准的 JSON 数组格式,跟普通的 JSON 对比是在最后多了一个 length 属性。只要是这种特殊的 json 格式都可以轻松使用 ES6 的语法转变成数组。
let json = {
'0': '前',
'1': '后',
'2': '全',
length: 3
}
let arr = Array.from(json)
console.log(arr) // ["前", "后", "全"]
Array.of()方法
把一堆文本或者变量转换成数组
let arr = Array.of('前', '后', '全')
console.log(arr) // ["前", "后", "全"]
find()实例方法
find 方法是从数组全查找。在 find 方法全我们需要传入一个匿名函数,函数需要传入三个参数:value:表示当前查找的值。index:表示当前查找的数组索引。arr:表示当前数组。在函数全如果找到符合条件的数组元素就进行 return,并停止查找。
let arr = [1, 2, 3, 4, 5]
console.log(arr.find((value, index, arr) => value > 3)) // 4
fill()实例方法
fill()也是一个实例方法,它的作用是把数组进行填充,它接收三个参数,第一个参数是填充的变量,第二个是开始填充的位置,第三个是填充到的位置。
let arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
arr.fill('hello', 2, 5)
console.log(arr) // [0, 1, "hello", "hello", "hello", 5, 6, 7, 8, 9]
数组遍历
- for...of 循环
打印内容
let arr = ['前', '后', '全']
for (let val of arr) {
console.log(val)
}
打印索引
let arr = ['前', '后', '全']
for (let index of arr.keys()) {
console.log(index)
}
打印内容+索引
let arr = ['前', '后', '全']
for (let [index, val] of arr.entries()) {
console.log(index + ':' + val)
}
- entries( )实例方法
let arr = ['前', '后', '全']
let list = arr.entries()
console.log(list.next().value) // [0, "前"]
console.log(list.next().value) // [1, "后"]
console.log(list.next().value) // [2, "全"]
箭头函数
数组和函数补漏
对象的函数解构
let json = {
a: '前',
b: '后'
}
function fn({ a, b }) {
console.log(a, b)
}
fn(json) // 前 后
数组的函数解构
let arr = ['前', '后', '全']
function fn(a, b, c) {
console.log(a, b, c)
}
fn(...arr) // 前 后 全
in 的用法
in 是用来判断对象或者数组全是否存在某个值的。
- 对象判断
let obj = {
a: 'hello',
b: 'world'
}
console.log('a' in obj) //true
- 数组判断
let arr = ['hello', 'world']
console.log(0 in arr) //true
数组遍历
forEach 循环的特点是会自动省略为空的数组元素,相当于直接给我们筛空了。当是有时候也会给我们帮倒忙。
- forEach
let arr = ['前', '后', '全']
arr.forEach((val, index) => console.log(index, val))
- filter
let arr = ['前', '后', '全']
arr.filter(val => console.log(val))
- some
let arr = ['前', '后', '全']
arr.some(val => console.log(val))
- map
map 可以向上面一样做循环,在这里起到一个替换的作用
let arr = ['前', '后', '全']
console.log(arr.map(val => '中'))
ES6 对象
Symbol
Set
Set 和 Array 的区别是 Set 不允许内部有重复的值,如果有只显示一个,相当于去重。虽然 Set 很像数组,但是他不是数组。
let setArr = new Set([1, 2, 3, 4])
console.log(setArr) // Set(4) {1, 2, 3, 4}
size 属性
let setArr = new Set([1, 2, 3, 4])
console.log(setArr.size) // 4
Set 的增删查
- 追加 add
let setArr = new Set([1, 2, 3, 4])
setArr.add(5)
console.log(setArr) // Set(4) {1, 2, 3, 4, 5}
- 删除 delete
let setArr = new Set([1, 2, 3, 4])
setArr.add(5)
setArr.delete(5)
console.log(setArr) // Set(4) {1, 2, 3, 4}
- 查找 has
let setArr = new Set([1, 2, 3, 4])
console.log(setArr) // Set(4) {1, 2, 3, 4}
console.log(setArr.has(1)) // true
清空 clear
let setArr = new Set([1, 2, 3, 4])
setArr.clear()
console.log(setArr) // Set(0) {}
set 的 for...of 循环
let setArr = new Set([1, 2, 3, 4])
for (let val of setArr) {
console.log(val)
}
set 的 forEach 循环
let setArr = new Set([1, 2, 3, 4])
setArr.forEach(val => console.log(val))
weakSet的声明
这里需要注意的是,如果你直接在new 的时候就放入值,将报错.WeakSet里边的值也是不允许重复的
let weakObj = new WeakSet()
let obj = { a: '前', b: '后' }
weakObj.add(obj)
console.log(weakObj)
Map数据结构
Map的灵活性要更好,你可以把它看成一种特殊的键值对,但你的key可以设置成数组,值也可以设置成字符串,让它不规律对应起来。
let json = {
a:'前',
b:'后'
}
var map=new Map()
map.set(json,'全')
console.log(map)
console.log(map.get(json))
map的增删查
- 增加set
map.set(json,'全')
- 取值get
console.log(map.get(json))
- 删除delete
map.delete(json);
console.log(map)
- size属性
console.log(map.size)
- 查找has
console.log(map.has(json))
- 清空 clear
map.clear()
总结:map在现在开发中已经经常使用,它的灵活性和高效性是我们喜欢的。开发中试着去使用map吧,你一定会喜欢上它的。
用Proxy进行预处理
在运行函数前初始化一些数据,在改变对象值后做一些善后处理。这些都算钩子函数,Proxy的存在就可以让我们给函数加上这样的钩子函数,你也可以理解为在执行方法前预处理一些代码。你可以简单的理解为他是函数或者对象的生命周期。
声明Proxy
我们用new的方法对Proxy进行声明。可以看一下声明Proxy的基本形式。
new Proxy({},{})
需要注意的是这里是两个花括号,第一个花括号就相当于我们方法的主体,后边的花括号就是Proxy代理处理区域,相当于我们写钩子函数的地方。
现在把上边的obj对象改成我们的Proxy形式。
var pro = new Proxy({
add: function (val) {
return val + 10;
},
name: 'I am Jspang'
}, {
get:function(target,key,property){
console.log('come in Get');
return target[key];
}
});
console.log(pro.name);
可以在控制台看到结果,先输出了come in Get。相当于在方法调用前的钩子函数。
get属性
get属性是在你得到某对象属性值时预处理的方法,他接受三个参数
target:得到的目标值 key:目标的key值,相当于对象的属性 property:这个不太常用,用法还在研究中,还请大神指教。
set属性
set属性是值你要改变Proxy属性值时,进行的预先处理。它接收四个参数。
target:目标值。 key:目标的Key值。 value:要改变的值。 receiver:改变前的原始值。
let pro=new Proxy({
add(val){
return val+10
},
name:'hello world'
},{
get(target,key,property){
console.log('come in Get')
return target[key]
},
set(target,key,value,receiver){
console.log(`set ${key} = ${value}`)
return target[key]=value
}
})
console.log(pro.name)
pro.name='你好世界'
console.log(pro.name)
promise
ES6 中的 promise 的出现给我们很好的解决了回调地狱的问题,在使用 ES5 的时候,在多层嵌套回调时,写完的代码层次过多,很难进行维护和二次开发,ES6 认识到了这点问题,现在 promise 的使用,完美解决了这个问题。那我们如何理解 promise 这个单词在 ES5 中的作用那,你可以想象他是一种承诺,当它成功时执行一些代码,当它失败时执行一些代码。它更符合人类的行为思考习惯,而不在是晦涩难懂的冰冷语言。
function step1(resolve, reject) {
console.log('开始洗菜')
if (state == 1) {
resolve('洗菜-完成')
} else {
reject('洗菜-失败')
}
}
function step2(resolve, reject) {
console.log('开始吃饭')
if (state == 2) {
resolve('吃饭-完成')
} else {
reject('吃饭-失败')
}
}
function step3(resolve, reject) {
console.log('开始洗碗')
if (state == 3) {
resolve('洗碗-完成')
} else {
reject('洗碗-失败')
}
}
let state = 1
new Promise(step1)
.then(val => {
console.log(val)
state++
return new Promise(step2)
})
.then(val => {
console.log(val)
state++
return new Promise(step3)
})
.then(val => {
console.log(val)
return val
})
Class
我们在 ES5 中经常使用方法或者对象去模拟类的使用,虽然可以实现功能,但是代码并不优雅,ES6 为我们提供了类的使用。需要注意的是我们在写类的时候和 ES5 中的对象和构造函数要区分开来,不要学混了。
类的声明
我们已经声明了一个类,并在类里声明了 name 方法,现在要实例化类,并使用类中的方法。
class Student {
name(val) {
console.log(val)
return val
}
}
let Tom = new Student()
Tom.name('Tom)
类的多方法声明
这里需要注意的是两个方法中间不要写逗号了,还有这里的 this 指类本身,还有要注意 return 的用法。
class Student {
name(val) {
console.log(val)
return val
}
skill(val) {
console.log(this.name('Tom' + ' skill ' + val))
}
}
let Tom = new Student()
Tom.name('Tom)
Tom.skill('web')
类的传参
在类的参数传递中我们用 constructor( )进行传参。传递参数后可以直接使用 this.xxx 进行调用.
class Student {
name(val) {
console.log(val)
return val
}
skill(val) {
console.log(this.name('Tom' + ' skill ' + val))
}
constructor(a, b) {
this.a = a
this.b = b
}
add() {
return this.a + this.b
}
}
let Tom = new Student(1, 2)
console.log(Tom.add())
我们用 constructor 来约定了传递参数,然后用作了一个 add 方法,把参数相加。这和以前我们的传递方法有些不一样,所以需要小伙伴们多注意下。
class 的继承
class Student {
name(val) {
console.log(val)
return val
}
skill(val) {
console.log(this.name('Tom' + ' skill ' + val))
}
constructor(a, b) {
this.a = a
this.b = b
}
add() {
return this.a + this.b
}
}
class Man extends Student {}
let Jack = new Man(12, 23)
Jack.name('Jack')
Jack.skill('java')
console.log(Jack.add())
模块化
在 ES5 中我们要进行模块华操作需要引入第三方类库,随着前后端分离,前端的业务日渐复杂,ES6 为我们增加了模块话操作。模块化操作主要包括两个方面。
- export :负责进行模块化,也是模块的输出。
- import : 负责把模块引,也是模块的引入操作。
export 的用法:
export 可以让我们把变量,函数,对象进行模块话,提供外部调用接口,让外部进行引用。先来看个最简单的例子,把一个变量模块化。我们新建一个 temp.js 文件,然后在文件中输出一个模块变量。
export var a = 'tom'
然后可以在 index.js 中以 import 的形式引入。
import { a } from './temp.js'
console.log(a)
这就是一个最简单的模块的输出和引入。
多变量的输出
这里声明了 3 个变量,需要把这 3 个变量都进行模块化输出,这时候我们给他们包装成对象就可以了。
var a = 'tom'
var b = 'jack'
var c = 'web'
export {a,b,c}
函数的模块化输出
export function add(a, b) {
return a + b
}
as 的用法 有些时候我们并不想暴露模块里边的变量名称,而给模块起一个更语义话的名称,这时候我们就可以使用 as 来操作。
var a = 'tom'
var b = 'jack'
var c = 'web'
export { x as a, y as b, z as c }
export default 的使用 加上 default 相当是一个默认的入口。在一个文件里 export default 只能有一个。我们来对比一下 export 和 export default 的区别
1.export
export var a = 'tom'
export function add(a, b) {
return a + b
}
对应的导入方式
import {a,add} form './temp' //也可以分开写
2.export defalut
export default var a='tom'
对应的引入方式
import str from './temp'