ES6,也称ESMAScript2015,这个版本减少了很多好用的个性
变量申明
ES6之前用var来定义变量,ES6减少了两个变量申明的形式,别离为const和let,const用来定义常量,let用于定义变量,补救了应用var来定义的破绽。
- var 有变量晋升,在全局/函数中定义的变量都会被晋升到全局/函数的最上方,值为undefined
- var 没有块级作用域的概念,通过 if / for /switch 定义的变量都会被晋升到全局
- let 定义变量,可被批改,不可被反复申明,有块级作用域
- const 定义常量,定义时需赋值,不可被批改,不可被反复申明,有块级作用域
他们三者次要区别如下
初始化需赋值 | 变量晋升 | 反复申明 | 从新赋值 | 块级作用域 | 跨块拜访 | 跨函数拜访 | |
---|---|---|---|---|---|---|---|
var | × | ✔ | ✔ | ✔ | × | ✔ | × |
let | × | × | × | ✔ | ✔ | × | × |
const | ✔ | × | × | × | ✔ | × | × |
let和const在定义之前会将变量保留到变量环境中,然而不可被拜访。
let userName = 'alice'if (true) { console.log(userName) let userName = 'kiki'}
以上代码的执行后果如下
在以上代码中,通过if创立的块级作用中有userName变量,尽管全局中也有userName变量,然而此时块中曾经通过let定义曾经保留到了块的变量环境中,会间接从块中获取,但在赋值之前依然是无法访问的,所以就存在了一个【暂时性死区(temporal dead zone)】的问题
字面量加强
在对象中,属性的定义有了更简洁的形式。
- 对象中定义的属性key和value统一时,能够合并
- 办法简写能够去掉function申明
- 对象中的属性能够通过[]来定义非字符串的变量
var name = 'alice'var age = 18var info = 'hobby'var user = { name: name, age: age, eating: function () { console.log('user eating~') }}user[info + 's'] = 'swimming'const person = { name, age, eating() { console.log('person eating~') }, [info + 's']: 'swimming'}console.log(user)console.log(person)
以上两种定义对象的形式最终成果是统一的
解构
数组解构
当咱们想要获取数组的元素时,很多时候都会通过下标值,es6给咱们提供了一种解构的形式,通过下标值的一一对应来获取每一个元素
//通过下标值获取元素var names = ['alice', 'kiki', 'macus']var x = names[0]var y = names[1]var z = names[2]console.log(x, y, z)// 解构var [a, b, c] = namesconsole.log(a, b, c)// 当只须要后两位元素时,第一个元素空着var [, m, n] = namesconsole.log(m,n)// 当只对应了一个元素时,应用残余参数搁置到一个数组里var [x, ...list] = namesconsole.log(x, list)
执行后果如下
通过babel将es6代码编译成es5代码能够发现,数组解构还是通过下标值来获取元素
对象解构
当获取对象的value时,咱们通常应用 .key 或者 [key],es6对于对象也提供了更为简便的解构的形式,需注意解构进去的变量要与key值绝对应
var user = { name: 'alice', age: 20}console.log(user.name, user.age)var { name, age } = userconsole.log(name, age)
以上两种获取属性值的形式后果统一
通过babel将es6代码编译成es5代码能够发现,对象解构的原理还是对象.属性名的模式
模板字符串
在没有模板字符串之前,拼接字符串和变量须要用引号(""),代码的可读性比拟弱,减少了模板字符之后,能够间接在``中写字符串,通过 ${expression} 来嵌入动静的内容
const name = 'aclie'const age = 18const user = 'My name is ' + name + ' and i am ' + age + ' years old.'const person = `My name is ${name} and i am ${age} years old.`console.log(user)console.log(person)
以上两种定义变量的形式后果是统一的
``中还能够拼接函数的执行后果
function getAnimalName(){ return 'cat'}const animal = 'This is a ' + getAnimalName()const pet = `This is a ${getAnimalName()}`console.log(animal)console.log(pet)
通过 + 号拼接和模板字符串是一样的后果
``还能够用来调用函数,通过模板字符串来宰割传参
const name = 'aclie'const age = 18function foo(a, b, c, d) { console.log(a) console.log(b) console.log(c) console.log(d)}foo`1${name}2${age}3${100}`
每个模板字符串中的数据对应传入函数的一个参数,宰割的残余数据组成一个数组作为参数
模板字符串转es5代码的实现是通过字符串的concat办法进行拼接
函数的默认参数
在es6以前须要本人判断函数有没有入参,没有就将入参的变量赋值为一个初始化的值
function getUserInfo(name, age){ name = name || 'kiki' age = age || 18 console.log(name,age)}getUserInfo('', 0)function getPersonInfo(name = 'alice', age = 18){ console.log(name, age)}getPersonInfo('alice', 0)
如果有 || 运算符时,当传入参数为空字符串或者0时,将被认为是false后执行 || 运算符后的代码
应用函数的默认参数还能够解构对象
function getUserInfo({ name, age } = { name: 'kiki', age: 18 }) { console.log(name, age)}getUserInfo()function getPersonInfo({name = 'kiki', age = 18} = {}){ console.log(name, age)}getPersonInfo()
两种形式解构进去的后果是一样的
通过babel编译函数的默认参数发现是通过arguments来进行解决的
残余参数
在es6之前,获取函数的所有入参能够通过arguments,es6减少了残余参数的语法用来指代没有被对应形参的实参
function foo(a, b, ...rest) { console.log('arguments', arguments) console.log(a, b, rest)}foo(1, 2, 3, 4, 5, 6)
通过 ...的运算符来获取残余参数
arguments和残余参数还是有一些不同之处的
- 通过arguments能够获取所有的实参,而残余参数只能获取没有被对应到形参的实参,而且箭头函数中是没有arguments的
- arguments的数据结构像数组,但它并不是真正的数组,是不能够间接应用数组的办法的,而残余参数就是一个数组,可间接应用数组办法
残余参数通过babel编译成可兼容浏览器的es5语法时,是通过创立数组逐个增加通过arguments获取的数据
开展语法
开展语法也是通过 ... 来进行对数据的操作,开展语法有三个利用场景
- 函数调用时
- 数组结构时
- 构建对象字面量时(ES9语法)
const array = [1, 2, 3]const obj = { name: 'alice', age: 20}const name = 'kiki'// 函数调用function foo(a, b, c){ console.log(a, b, c)}foo(...array)foo(...name)// 数组构建const newArr = [...array, 4, 5]console.log(newArr)// 构建对象字面量const newObj = {...obj, name: 'kiki'}console.log(newObj)
可通过开展语法开展对象、数组、字符串
须要留神的是,开展语法实际上是浅拷贝
const user = { name: 'alice', favorite: { sport: 'tennis'}}const newUser = {...user}newUser.name = 'kiki'newUser.favorite.sport = 'football'console.log(user)
user中favorite属性是一个对象,由user通过开展语法创立的newUser对象批改了对象中的属性,原来的user对象的favorite属性也会更改
它们在内存中的体现如下图所示
数组和函数的开展语法通过babel编译比较简单,别离是通过concat办法和apply第二个参数可传数组的个性,对象的开展语法简单一些,有一些函数封装和逻辑判断,就没有截图了
数值的示意
规定了进制的示意形式
- 二进制数据,以 0b 结尾,每一位数字最大值为1
- 八进制数据,以 0o 结尾,每一位数字最大值为7
- 十六进制数据,以 0x 结尾,A-F示意数字10-15,每一位数字最大值为F
const a = 0b100const b = 0o100const c = 0x100console.log(a, b, c)
最初还是会转换成十进制数据
Symbol
Symbol示意惟一的值,是一种新的数据类型,对象中的key值在此之前只能应用字符串,如果key值雷同的状况下会进行笼罩,但应用Symbol就不会呈现笼罩的状况。
Symbol定义时,还有一些注意事项
- 通过Symbol申明的变量能够在括号里定义一个形容,通过description来获取(ES10增加的)
- Symbol定义的变量即便有雷同的descripton也不会反复
- Symbol.for定义的变量在全局,可通过Symbol.keyFor查找,有雷同的descrition时指向同一个元素
- Symbol作为对象中的key值时,须要应用 [],不能应用 . 来赋值
const a = Symbol('hello')const b = Symbol('hello')const c = Symbol.for('alice')const d = Symbol.for('alice')const obj = { [a]: 'alice'}obj[b] = 'kiki'Object.defineProperty(obj, c, { value: 'macus'})console.log(a)console.log(a.description)console.log(a === b)console.log(c === d)console.log(Symbol.keyFor(a), Symbol.keyFor(c))console.log(obj[a], obj[b], obj[c])
执行后果如下
Set和WeakSet
Set
Set意思是汇合,相似于数组,但它存储的元素不能反复。
Set有这些属性和办法
- size:返回Set中元素的个数
- add(value):增加某个元素,返回Set对象自身
- delete(value):从set中删除和这个值相等的元素,返回boolean类型
- has(value):判断set中是否存在某个元素,返回boolean类型
- clear():清空set中所有的元素,没有返回值
- forEach(callback, [, thisArg]):通过forEach遍历set
- 反对for / for of的遍历
const arr = [{ name: "alice" }, 2, 3, 4, 5, 4, 3, 2, 1]const set = new Set(arr)set.add(0)set.delete(3)console.log(set.size)console.log(set.has(1))console.log(set)console.log([...set])console.log(Array.from(set))for (let item of set) { console.log(item)}set.forEach(item => { console.log(item)})
执行后果如下
WeakSet
还有一个与Set相似的数据结构叫WeakSet,它和Set的区别在于
- WeakSet中只能寄存对象类型,不能寄存根本数据类型
- WeakSet对元素是弱援用,如果没有其余援用对某个对象进行援用,那么垃圾回收器(GC)能够对该对象进行回收
它有这些办法
- add(value):增加某个元素,返回WeakSet对象自身
- delete(value):从WeakSet中删除和这个值相等的元素,返回boolean类型
- has(value):判断WeakSet中是否存在某个元素,返回boolean类型
const student = { grade: 4 }let person = { hobby: 'running' }const arr = [student, person]const weakSet = new WeakSet(arr)weakSet.add({ grade: 4 })weakSet.delete(student)console.log(weakSet.has(student))console.log(weakSet)
因为WeakSet对元素是弱援用,引入的内容可能被GC回收,所以是不可能遍历和应用toString()办法获取元素的
当set中存储的对象由内存地址0x100改为指向null时,原来的内存地址0x100不会被垃圾回收器回收,因为set中是强援用,而weakMap中存储的对象由内存地址0x200改为指向null时,原来的内存地址0x200会被垃圾回收器回收,因为weakSet中是强援用
Map和WeakMap
Map
Map示意字典存储映射关系,相似于对象,但对象中的Key数据类型只能为字符串或者Symbol,在Map中就没有限度
Map常见的属性和办法
- size:返回Map中元素的个数
- set(key, value):在Map中增加key、value,并且返回整个Map对象
- get(key):依据key获取Map中的value
- has(key):判断是否包含某一个key,返回Boolean类型
- delete(key):依据key删除一个键值对,返回Boolean类型
- clear():清空所有的元素
- forEach(callback, [, thisArg]):通过forEach遍历Map
- 能够通过for of进行遍历
const user = { name: 'alice' }const info = { message: 'hello' }const map = new Map()map.set(user, info)// map.clear()console.log(map.size)console.log(map.has(user))console.log(map.get(user))console.log(map)map.forEach((value, key)=>{ console.log(value, key)})for(let [key, value] of map){ console.log('item', key, value)}
执行后果如下
WeakMap
与Map相似,但有一些区别(与set 和 WeakSet中的区别相似)
- WeakMap的key只能应用对象,不承受其余的类型作为key
- WeakMap的key对对象想的援用是弱援用,如果没有其余援用援用这个对象, 那么垃圾回收器(GC)能够回收该对象
它有这些办法
- set(key, value):在Map中增加key、value,并且返回整个Map对象
- get(key):依据key获取Map中的value
- has(key):判断是否包含某一个key,返回Boolean类型
- delete(key):依据key删除一个键值对,返回Boolean类型
因为WeakMap对元素是弱援用,引入的内容可能被GC回收,所以是不可能遍历和应用toString()办法获取元素的
以上就是ES6蕴含的大部分属性,对于js高级,还有很多须要开发者把握的中央,能够看看我写的其余博文,继续更新中~