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 = 18
var 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] = names
console.log(a, b, c) // 当只需要后两位元素时,第一个元素空着
var [, m, n] = names
console.log(m,n) // 当只对应了一个元素时,使用剩余参数放置到一个数组里
var [x, ...list] = names
console.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 } = user
console.log(name, age)

以上两种获取属性值的方式结果一致

通过babel将es6代码编译成es5代码可以发现,对象解构的原理还是对象.属性名的形式

模板字符串

在没有模板字符串之前,拼接字符串和变量需要用引号(""),代码的可读性比较弱,增加了模板字符之后,可以直接在``中写字符串,通过 ${expression} 来嵌入动态的内容

const name = 'aclie'
const age = 18
const 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 = 18
function 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 = 0b100
const b = 0o100
const c = 0x100 console.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高级,还有很多需要开发者掌握的地方,可以看看我写的其他博文,持续更新中~

你知道ES6中的这些属性吗的更多相关文章

  1. ES6中object对象属性

    //////es5中定义对象属性要么字面量.要么点.要么[],变量与空格在这些方法中没有得到好的支持 /////在es6中可以这么定义: let w='www'; let obj1={w};//obj ...

  2. es6中顶层对象属性≠全局属性

    先思考一下下面代码的输出结果是什么 const a = { x:1, fn:()=>this.x+=1 } const x = 1 a.fn() console.log(a.x,x) 正确答案为 ...

  3. es6中的属性名表达式

    代码如下: 问题: 为什么我可以这样给obj1对象添加动态属性? 为什么我最终的结果是只添加了right属性? 解答: 1. 第一个问题解答如下: 我们知道在es5中给对象添加属性有两种方法,一种是通 ...

  4. Nodejs与ES6系列4:ES6中的类

    ES6中的类 4.1.class基本语法 在之前的javascript语法中是不存在class这样的概念,如果要通过构造函数生成一个新对象代码 function Shape(width,height) ...

  5. ES6中Arguments和Parameters用法解析

    原文链接 译文 ECMAScript 6 (也称 ECMAScript 2015) 是ECMAScript 标准的最新版本,显著地完善了JS中参数的处理方式.除了其它新特性外,我们还可以使用rest参 ...

  6. ES6中的Class

    对于javascript来说,类是一种可选(而不是必须)的设计模式,而且在JavaScript这样的[[Prototype]] 语言中实现类是很蹩脚的. 这种蹩脚的感觉不只是来源于语法,虽然语法是很重 ...

  7. ES5和ES6中对于继承的实现方法

    在ES5继承的实现非常有趣的,由于没有传统面向对象类的概念,Javascript利用原型链的特性来实现继承,这其中有很多的属性指向和需要注意的地方. 原型链的特点和实现已经在之前的一篇整理说过了,就是 ...

  8. ES6中的高阶函数:如同 a => b => c 一样简单

    作者:Sequoia McDowell 2016年01月16日 ES6来啦!随着越来越多的代码库和思潮引领者开始在他们的代码中使用ES6,以往被认为是"仅需了解"的ES6特性变成了 ...

  9. 深入理解 JavaScript 异步系列(3)—— ES6 中的 Promise

    第一部分,Promise 加入 ES6 标准 原文地址 http://www.cnblogs.com/wangfupeng1988/p/6515855.html 未经作者允许不得转载! 从 jquer ...

  10. ES6中的Symbol类型

    前面的话 ES5中包含5种原始类型:字符串.数字.布尔值.null和undefined.ES6引入了第6种原始类型——Symbol ES5的对象属性名都是字符串,很容易造成属性名冲突.比如,使用了一个 ...

随机推荐

  1. Nginx Web快速入门

    Nginx Web快速入门 目录 Nginx Web快速入门 Nginx概述 为什么选择Nginx服务 Nginx的应用场景 源码安装nginx Yum安装nginx Nginx相关命令总结 Ngin ...

  2. Django transaction.atomic 事务的使用

    函数 transaction.atomic 数据库的读写操作中,事务在保证数据的安全性和一致性方面起着关键的作用,而回滚正是这里面的核心操作. 遇到并发的时候常常会因为接口的访问顺序或者其他情况,导致 ...

  3. vue中点击其他任意位置关闭弹框

    mounted() { //点击任意位置关闭区域弹窗 document.addEventListener('click', (e) => { //获取弹窗对象 const userCon = d ...

  4. Vue2积分商城项目

    一.清空项目非必要文件和用户片段,路径提示的配置 views 下面的文件只保留 Home.vue ,其余删除,删除 components/HelloWorld.vue,并且 Home.vue 中不再引 ...

  5. 2022-03-15:给定一棵树的头节点head,原本是一棵正常的树, 现在,在树上多加了一条冗余的边, 请找到这条冗余的边并返回。

    2022-03-15:给定一棵树的头节点head,原本是一棵正常的树, 现在,在树上多加了一条冗余的边, 请找到这条冗余的边并返回. 答案2022-03-15: 1.指向头,入度没有0的.入度没有2的 ...

  6. 11g ADG级联备库基础测试环境准备

    客户通过duplicate生产备库的方式创建cascade备库. 发现每次都会遇到两个文件报错,ORA-17628: Oracle error 19505错误,且每一次跑,报错文件不一样. 现在想帮客 ...

  7. MySQL的varchar存储原理:InnoDB记录存储结构

    摘要:varchar(M) 能存多少个字符,为什么提示最大16383?innodb怎么知道varchar真正有多长?记录为NULL,innodb如何处理?某个列数据占用的字节数非常多怎么办?影响每行实 ...

  8. 每周更新 | Verilog测试用例及波形展示图功能上线

    Hi,亲爱的技术伙伴,经过产研团队的努力,本周ShowMeBug有以下4个功能上线啦- 芯片语言 Verilog 支持测试用例 芯片语言 Verilog 支持测试用例,自动评分同步上线- 同时,Ver ...

  9. SpringBoot定义优雅全局统一Restful API 响应框架五

    闲话不多说,继续优化 全局统一Restful API 响应框架 做到项目通用 接口可扩展. 如果没有看前面几篇文章请先看前面几篇 SpringBoot定义优雅全局统一Restful API 响应框架 ...

  10. deepin系统更新谷歌浏览器chrome的方法

    deepin系统更新谷歌浏览器chrome的方法 1 为什么要更新谷歌浏览器谷歌浏览器更新频繁,隔一段时间不更新,打开浏览器时会自动弹出一个提示更新的窗口,有点烦,如果使用python自动处理程序时, ...