「掘金日新计划 · 8 月更文挑战」的第4天——JavaScript 的进阶版——es6(上)

94 阅读7分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第4天,点击查看活动详情

image.png

昨天已经更新完JavaScript的基本内容,接下来就是它的进阶版es6,现在大部分项目开发都是使用es6,所以也是必不可少的

正文开始了

一、ECMAScript6简介

1.ECMAScript 6简介

1)ECMAScript 6是什么?
ECMAScript 6.0(以下简称 ES6)是 JavaScript 语言的下一代标准,已经在2015年6月正式发布 了。它的目标,是使得 JavaScript 语言可以用来编写复杂的大型应用程序,成为企业级开发语言。

2)ECMAScript 和 JavaScript 的关系
ECMAScript是JavaScript的标准,JavaScript是ECMAScript的实现。换句话说,如果说JavaScript是一⻔语言的话,那么ECMAScript就是这⻔语言遵循的语法书。

3) ES6 与 ECMAScript 2015 的关系
2011年的时候,ECMAScript5.1版本发布,ECMA组织就开始准备6.0版本了。但因为这个版本引入的语法功能太多了,所以不可能通过一个版本就将所有功能涵盖。所以,标准委员会决定,标准 在每年的6月份正式发布一次,作为当年的正式版本。接下来的时间,就在这个版本的基础上做改动,直到下一年的6月份,草案就自然变成了新一年的版本。这样一来,就不需要以前的版本号了,只要用年份标记就可以了。
就这样ES6的第一个版本就在2015.6正式发布了,正式名称就是《ECMAScript 2015标准》(简称ES2015)

4) 总结
因此,ES6 既是一个历史名词,也是一个泛指,含义是5.1版以后的 JavaScript 的下一代标准,涵盖了ES2015、ES2016、ES2017等等,而ES2015  则是正式名称,特指该年发布的正式版本的语言标准

2、使用babel工具搭建ES6项目环境

1)node安装 官网:nodejs.cn/download/

2)初始化工程项目

npm init -y

3)安装对应的依赖包

# 本地安装babel-cli及对应的转化规则
npm install --save-dev babel-cli babel-preset-es2015

4)创建项目目录

  • src⽬录⽤于存放编写的es6代码
  • dist⽬录⽤于存放由es6转化后的代码

5)配置babel

(1)新建 .babelrc 文件

// 配置用于转化当前代码的规则集
{
"presets": ["es2015"]
}

(2)babel的基本用法

# 这是局部安装babel的用法,全局安装的话就不用输入目录了

# 转码结果写入一个文件
# --out-file 或 -o 参数指定输出文件
$ node_modules/.bin/babel-node test.js --out-file test.js # 或 者
$ node_modules/.bin/babel-node test.js -o test.js


# 整个目录转码
# --out-dir 或 -d 参数指定输出目录
$ node_modules/.bin/babel-node src --out-dir dist # 或 者
$ node_modules/.bin/babel-node src -d dist

(3)配置package.json文件

// 配置启动脚本的命令
"scripts": {
// 监听index.js文件,一发生变化就执行babel转译的命令
"dev": "babel src/index.js -w -o dist/index.js",
// 将指定文件转译后输出到指定目录下
"build": "babel src/index.js -o dist/index.js",
// 将src目录下所有es6文件转译后输出到dist目录
"buildall": "babel src -d dist"
}

6)对比
(1)在es6之前(也就是es5),用来声明变量的就是var
思考:Var 有一个特点:它声明只有局部和全局这个概念会引起什么问题?

  • 问题一:1. 循环问题

image.png
在循环题内部声明的变量i能在循环外部使用,也就是说i成为了全局变量,显然不是需要的,i只是用来计数(循环的次数)的,并没有什么作用,这时候会造成内存泄露的问题

  • 问题二:在函数里面引起的问题(变量提升)

image.png//undefine

image.png
JS里面有个局部作用域的概念,局部作用域指得就是函数里面的作用域了,它会在里面找,找不到才回到外面找,但是这边它又找到了,里面有个默认操作的行为,会把变量声明提前

  • 问题三:相对于es5来说 引入块级作用域  简单来说就是大括号包住的代码,在这里面的变量外部是无法改变的

image.png

image.png

二、全新的声明及数据赋值方式

1.新的变量声明关键字let与const

1)作用域

  • 全局作用域
  • 局部作用域
  • 块级作用域

2)let和const

  • let
    1.用法:声明一个变量
    2.特点:
    1).只在声明的代码块内有效
    2).在同一作用域内不允许重复声明
    3).没有变量升
    4).暂时性死区  在变量声明之前,无法访问以及操作

  • const
    1.用法:声明一个只读的变量——常量
    2.特点:同let命令
    3.注意事项:
    变量声明的同时必须立即赋值
    如声明的是简单类型的数据,变量的值不可改变
    4.实质:
    保证变量指向的内存地址所保存的数据不允许改动。
    补充:简单类型如字符串、数字和布尔值,值就保存在变量指向的内存地址。 而复杂类型的数据如对象、数组和函数,变量指向的内存地址,实际上是保存了指向实际数据的指针。所以const 只能保证指针是固定的,至于指针指向的数据结构变不变就无法控制了,所以使用const 声明复杂类型对象时要慎重

2.第七种数据类型Symbol

1)引入的背景:

对象的属性名容易产生命名冲突,为保证键名的唯一性,故es6引入Symbol这种新的原始数据类型,确保创建的每个变量都是独一无二的

2)特点:
1)类似字符串的数据类型
2)返回的值是原始类型的数据,不是对象
3)不能使用new命令,否则会报错
4)可选参数

// 这里的a1,a2的作用可以说是为了备注,以至于我们输出Symbol变量时能够区分不同的变量。
let a1 = Symbol('a1') let a2 = Symbol('a2')

3)用法
1.定义对象的唯一属性名

// 在对象里用Symbol作为属性名的三种写法

let name = Symbol()
// 第一种方式: 借助数组读取name变量,此时不能用点运算符,点运算符默认后面的参数是字符串
let a = {} a[name] = 'miaozai'

// 第二种方式: 构造时声明
let a = { [name]'miaozai'
}

// 第三种 Object.defineProperty let a = {}
Object.defineProperty(a, name, { value: 'miaozai' });

2.定义常量

// 定义字符串常量
const name = Symbol("miaozai");

三、不可不知的解构赋值

1)解构赋值理解:
为赋值操作的语法糖,它是针对数组或者对象进行模式匹配,然后对其中的变量进行赋值

2)实质:
ES6中只要某种数据有Iterator接口(也就是可以循环遍历),都可以 进行数组的解构赋值。

3)使用场景:
1)数组解构:

//数组解构
{
    let ab, c
    [a, b, c] = [1, 2]
    console.log(ab, c)
}
//1,2,undefined(如果数组中找不到一个值就会返回undefined)

//上面问题可以这样解决,给它一个默认值
{
    let ab, c
    [a, b, c = 6] = [1, 2, 3]
    console.log(ab, c)
}
//1,2,6
 
 //数组分割
 let a, other
    [a, ...other] = [1, 2, 3]
    console.log(a, other)
}
//1,[2,3]

 

//如果只要数组的第一项和第三项:
{
    let ab
    [a, , b] = [1, 2, 3]
    console.log(ab)
}
//1 3

2).对象解构:

{
    let ab
    ({ ab } = { a2, b: 3 })
    console.log(ab)
}

//如果只想要这个属性,但是不想要属性名
{
    let num, total
    ({ a: num, b: total } = { a2, b: 3 })
    console.log(num, total)
}

// 2 3
{
    let num, total
    ({ a: num, b: total } = { a2, b: 3 })
    console.log(num, total)
}


//使用场景最大的作用就前后端之间的联系 后端返回的是JSON数据,JSON数据也就是个对象,可以定义变量去解构数据,来获取想要的参数
{
    function fn() {
        return {
           name: 'miaozai',
           nameList: [{
                name: 'miaozai2'
            }]
        }
    }

    

    let b = fn();
    let {name: person, nameList:[{name: otherPerson}]} = b;
    console.log(person, otherPerson)

}
//用变量b来接收,对这个对象进行解构,取到两个name属性,主要是一一对应

3)字符串解构
4)布尔值解构
5)函数参数解构
6)数值解构等