前端基础:ECMAScript 6

时间:2022-07-24
本文章向大家介绍前端基础:ECMAScript 6,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

Introduction to ECMAScript 6

ECMAScript 6.0(以下简称 ES6)是 JavaScript 语言的下一代标准。

ES6 的目标是使得 JavaScript 语言可以用来编写复杂的大型应用程序,成为企业级开发语言。

ECMAScript and JavaScript

ECMAScript 是 JavaScript 的规格,JavaScript 是 ECMAScript 的一种实现

ES6 and ECMAScript 2015
  • 1996 年 JavaScript 的创造者 Netscape 公司,决定将 JavaScript 提交给标准化组织 ECMA,希望这种语言能够成为国际标准。
  • ECMA 发布 262 号标准文件(ECMA-262)的第一版,规定了浏览器脚本语言的标准,并将这种语言称为 ECMAScript,这个版本就是 1.0 版。
  • 2011 年,ECMAScript 5.1 版发布后,就开始制定 6.0 版了。因此,ES6 这个词的原意,就是指 JavaScript 语言的下一个版本。
  • ES6 既是一个历史名词,也是一个泛指,含义是 5.1 版以后的 JavaScript 的下一代标准,涵盖了 ES2015、ES2016、ES2017 等等

搭建前端环境

Node 环境
什么是 Node.js

简单的说 Node.js 就是运行在服务端的 JavaScript。

Node.js 是脱离浏览器环境运行的 JavaScript 程序,基于 Google 的 V8 引擎,V8 引擎执行 Javascript 的速度非常快,性能非常好。

Node.js 可以部署一些高性能的服务。

运行 node.js

在 dos 窗口中执行命令查看版本号

node -v

创建 hello.js 文件,写 js 代码

console.log("hello, nodejs");

打开命令行终端并输入命令

node hello.js

这样,没有使用浏览器也可以运行 js 程序了

服务器端应用开发
  • 创建 node-server.js
// node 中自带的 require 引入方法,http 也是 node 中自带的服务对象
const http = require("http");
http.createServer(function(request,response){
    // 发出 http 请求的头部信息
    // http 的状态码:200 OK
    // 请求的内容类型:text/plain
    response.writeHead(200, {"Content-Type": "text/plain"});
    // 响应的数据 "hello,welcome",此时并不支持中文
    response.end("hello,welcome");
}).listen(8888);

console.log("服务器已启动,请访问 http://127.0.0.1:8888");
  • 服务器启动成功后,在浏览器中输入:http://localhost:8888/
  • 查看 WebServer 成功运行,并输出 html 页面
  • 停止服务:ctrl + c
NPM 环境
什么是 NPM

NPM 全称 Node Package Manager,是 Node.js 包管理工具。

NPM 是全球最大的模块生态系统,里面所有的模块都是开源免费的,也是 Node.js 的包管理工具,相当于 Maven。

如果一个项目需要引用很多第三方的 js 文件,比如地图、报表等文件,那么可以把这些 js 文件统一放在一个仓库里,谁需要谁就去仓库中拿过来。NPM 就是这个仓库系统。如果需要某个 js 文件,那就去远程仓库中下载,放在本地磁盘中,进而引用到项目中。

NPM 工具的安装位置

Node 的环境在安装的过程中,npm 工具就已经安装好了。

Node.js 默认安装的 npm 包和工具的位置在 Node.js 目录下的 node_modules。在这个目录下可以看见 npm 目录,npm 本身就是被 NPM 包管理器管理的一个工具,这说明 Node.js 已经集成了 npm 工具。

# 在命令提示符查看当前 npm 版本
npm -v
使用 NPM 管理项目

项目初始化:全新创建一个目录,作为项目目录,使用 dos 命令进入此目录,输入命令 。

npm init

# 接下来是一堆项目信息等待输入
# 如果使用默认值或不知道怎么填写,则直接回车即可。

# package name: 项目名
# version: 版本号
# description: 项目的描述
# entry point: 项目的入口文件(作为 node 服务的 js 文件)
# test command: 项目启动时来执行脚本文件的命令(默认为 node app.js)
# git repository: git 的仓库地址(可以不写)
# keywirds:项目关键字(可以不写)
# author: 作者名字
# license: 发行项目需要的证书(可以不写)

最后会生成 package.json 文件,这个是包的配置文件,相当于 maven 的 pom.xml,之后可以根据需要进行修改。

如果按照默认值初始化可使用如下命令:

npm init -y
修改 NPM 镜像和存储地址

NPM 官方的管理的包都是从 http://npmjs.com 下载的,但是这个网站在国内速度很慢。推荐使用淘宝 NPM 镜像 http://npm.taobao.org/,它是一个完整的 npmjs.com 镜像且尽量保持同步。

设置镜像和存储地址:

# 配置镜像地址
npm config set registry https://registry.npm.taobao.org

# 设置 npm 下载包的存储地址(建议英文目录)
npm config set prefix "E:\repo_npm"

# 查看 npm 配置信息
npm config list
npm install 命令的使用
npm install jquery

使用 npm install 安装依赖包的最新版

模块安装的位置:项目目录node_modules

安装会自动在项目目录下添加 package-lock.json 文件,这个文件帮助锁定安装包的版本

同时 package.json 文件中,依赖包会被添加到 dependencies 节点下,类似 maven 中的 <dependencies>

上述命令下载的是最新版的 jQuery。

如果项目使用 1.9.1 版本进行开发,通过 npm 安装的版本太新,就会导致项目失效,可以执行以下命令安装对应的版本:

npm install jquery@1.9.1

ES6 基本语法

ES 标准中不包含 DOM 和 BOM的定义,只涵盖基本数据类型、关键字、语句、运算符、内建对象、内建函数等通用语法。

let 声明变量

let 声明变量与 JavaScript 中 var 声明变量有什么区别?

  1. 作用域不同
{
    // var 声明的变量是全局变量
    var a = 0;
    // let 声明的变量是局部变量
    let b = 0;
}

console.log(a);
// 错误:b 未定义
console.log(b);
  1. 声明次数不同
// var 可以声明多次
var m = 1;
var m = 2;
// let 只能声明一次
let n = 3;
// 语法错误:n 已经声明过了
let n = 4;

console.log(m);
console.log(n);
  1. 声明与使用顺序不同
// var 声明的变量会全局存储
// 没有报错,输出:undefined
console.log( x );
var x = "苹果";

// let 声明的变量只能在执行后才存储
// 错误:y 没有定义
console.log(y);
let y = "香蕉";
const 声明常量

const 声明常量为只读变量

  1. 一旦声明之后,其值是不允许改变的
  2. 一但声明必须初始化,否则会报错: SyntaxError: Missing initializer in const declaration
const PI = 3.14;
// 错误:Assignment to constant variable
PI = 3.1415;
console.log( PI );
解构赋值

解构赋值是对赋值运算符的扩展,它是一种针对数组或者对象进行模式匹配,然后对其中的变量进行赋值。

解构,就是将集合型数据进行分解和拆分,把里面的值逐一遍历获取。这在代码书写上简洁且易读,语义更加清晰明了;也方便了复杂对象中数据字段获取。

数组解构
var arr = [1,2,3];

// 传统的 js
let a = arr[0];
let b = arr[1];
let c = arr[2];
console.log(a,b,c);

// ES6 的解构
var [x,y,z] = arr;
console.log(x,y,z);
对象解构
var user = {
    username : "布莱尔",
    weapon:"菜刀",
    horse:"白马"
};

// 传统的 js
let name = user.username;
let weapon = user.weapon;
let horse = user.horse;
console.log("姓名:"+name+",武器:"+weapon+",坐骑:"+horse);

// ES6 的解构
// 注意:解构的变量名必须是对象中的属性
let {username,weapon,horse} = user;
console.log("姓名:"+username+",武器:"+weapon+",坐骑:"+horse);
模板字符串

模板字符串相当于加强版的字符串,用反引号来表示。除了作为普通字符串,还可以用来定义多行字符串,以及在字符串中加入变量和表达式。

定义多行字符串
let str = `hello,
where are you?
Let's go out for happy hour.`;
console.log(str);
字符串插入变量和表达式
let name = `布莱尔`;
let age = 20;

// 传统的拼接字符串
var info1 = "我叫:"+name+",今年"+age+"岁";
console.log(info1);

// ES6 的拼接字符串
var info2 = `我叫:${name},明年${age+1}岁`;
console.log(info2);
字符串中调用函数
function test(){
    return "布莱尔";
}
let str = `我的名字叫${test()},很高兴认识你。`;
console.log(str);
声明对象简写

定义对象的时候,可以用变量名作为属性名

let name = `布莱尔`;
let age = 19;

// 传统
let user1 = {
    name : name,
    age : age
};
console.log(user1);

// ES6 新语法中的简写
let user2 = {name,age};
console.log(user2);
定义方法简写
// 传统
let user1 = {
    say : function(){
        console.log("大家好");
    }
};
user1.say();

// ES6
let user2 = {
    say(){
        console.log("大家好哦");
    }
};
user2.say();
对象拓展运算符

拓展运算符 {...} 将参数对象中所有可以遍历的属性拿出来,然后拷贝给新对象。

拷贝对象(深拷贝)
let user1 = {
    name:"布莱尔",
    age:20
};
let user2 = {...user1};

console.log(user1);
console.log(user2);
合并对象

两个对象合并成一个对象。

let user1 = {
    name:"布莱尔",
    age:18
};
let user2 = {head:"诸葛亮"};
let user = {...user1, ...user2};

console.log(user);
函数的默认参数
function test(name , age = 18){
    console.log(`我叫${name},我今年${age}岁`);
}
//我叫小明,我今年33岁
test("小明",33);
//我叫小红,我今年18岁
test("小红");
 //我叫小赵,我今年null岁
test("小赵",null);
//我叫小马,我今年岁
test("小马","");
// 我叫小张,我今年18岁
test("小张",undefined);
函数的不定参数
function test( ...arg ){
    console.log(`传入了${arg.length}个参数`);
    for(var i = 0; i<arg.length; i++){
        console.log(arg[i]);
    }
}

test();
test(1);
test(1,2);
test(1,2,3,4,5,6);
test("布","莱","尔",17);
箭头函数

箭头函数提供了一种更加简洁的函数书写方式。基本语法是:参数 => 函数体

// 传统
var f1 = function(a){
    return a*10;
}
console.log(f1(10));

// ES6
// 当箭头函数没有参数或者有多个参数,要用 "()" 括起来
// 当箭头函数的函数体有多行语句,用 "{}" 括起来,表示代码块
var f3 = (a,b) => {
    let sum = a+b;
    return sum;
}
console.log(f3(3,7));
// 当只有一条语句,并且需要返回时,可以省略 "{}",结果会自动返回
var f4 = (a,b) => a + b;
console.log(f4(11,22));
// 当箭头函数一个参数时,可以省略 "()"
var f2 = a=>a*10;
console.log(f2(20));
Promise

Promise 用来解决回调函数的嵌套问题。

setTimeout(()=>{
    console.log(1);
    setTimeout(()=>{
        console.log(2);
        setTimeout(()=>{
            console.log(3);
            setTimeout(()=>{
                console.log(4);
            },1000);
        },1000);
    },1000);
},1000);
// 使用 promise:
// Promise 的构造函数接收一个参数,是函数,
// 并且传入两个参数:
// resolve (异步操作执行成功后的回调函数),
// reject (异步操作执行失败后的回调函数)
next = n =>
new Promise(function(resolve, reject) {
    setTimeout(function() {
        resolve(n);
    }, 1000);
});

next(1).then(res => { // 成功
    console.log(res);
    // 在 then 方法中调用的 next 方法,
    // 一定要用 return ,
    // 否则不会通过 resolve 把数据往下传递
    return next(2);
}).then(res => {
    console.log(res);
    return next(3);
}).then(res => {
    console.log(res);
}).catch(() => {
    // 处理失败:catch 方法的第二个参数是失败的回调
    console.log("出错");
});
模块化

Java 语言的模块化做法是 import 引入之后,就能使用了。ES6 的模块化,需要将一个 js 文件声明成一个模块导出之后,另一个 js 文件才能引入这个模块;每一个模块只加载一次(是单例的), 若再去加载同目录下同文件,直接从内存中读取。

传统的模块化

创建 user.js 文件

function addUser(name){
    return `保存${name}成功!`;
}

function removeUser(id){
    return `删除${id}号用户!`;
}

// 声明模块并导出
/*
module.exports={
    save:addUser,
    delete:removeUser
}*/

// 声明模块导出的简写
module.exports={
    addUser,
    removeUser
}

test.js

// 引入 user 模块
let user = require("./user.js");
console.log( user );

let result1 = user.addUser("布莱尔");
let result2 = user.removeUser(15);
console.log(result1);
console.log(result2);
ES6 的模块化

user.js

let name = "布莱尔";
let age = 20;
let fn = function(){
    return `我是${name}!我今年${age}岁了!`;
}

// 声明模块并导出
export{
    name,
    age,
    fn
}

test.js

import {name,age,fn} from "./user.js"

console.log(name);
console.log(age);
console.log(fn);

运行 test.js 出现错误,原因是 node.js 并不支持 ES6 的 import 语法,需要将 ES6 转换降级为 ES5。

babel 环境

babel 是一个广泛使用的转码器,可以将 ES6 代码转为 ES5 代码,从而在现有的环境中执行。

这意味着可以用 ES6 编写程序,而不用担心现有环境是否支持。

安装 babel 客户端环境

运行命令:

npm install --global babel-cli

查看版本:

babel --version
安装转码器
  1. 创建专属目录,在其中初始化项目。
npm init -y
  1. 创建 babel 配置文件 .babelrc,并输入代码配置:
{
  "presets": ["es2015"],
  "plugins": []
}
  1. 安装转码器
npm install --save-dev babel-preset-es2015
  1. 转码。创建 dist 目录,用来存放转码后的文件。
babel user.js --out-file .distuser.js
# 或者
babel user.js -o .distuser.js
  1. 运行转码后的文件。
node .disttest.js
ES6 模块化的另一种写法
as 的用法

user.js:如果不想暴露模块当中的变量名字,可以通过 as 来进行操作:

let name = "布莱尔";
let age = 18;
let fn = function(){
    return `我是${name}!我今年${age}岁了!`;
}

// 声明模块并导出
export{
    name as a,
    age as b,
    fn as c
}

test.js

import {a,b,c} from "./user.js";

console.log(a);
console.log(b);
console.log(c());

也可以接收整个模块

test.js

// 通过 "*" 来批量接收,as 来指定接收的名字
import * as info from "./user.js";

console.log(info.a);
console.log(into.b);
console.log(into.c());
默认导出

可以将所有需要导出的变量放入一个对象中,然后通过 default export 进行导出

/**** person.js 导出 ****/
export default{
    name:"布莱尔",
    eat(){
        return "吃饭";
    }
}

/**** test.js 导入 ****/
import p from "./person.js";
console.log(p.name, p.eat());
重命名 export 和 import

如果导入的多个文件中,变量名字相同,即会产生命名冲突的问题;为了解决该问题,ES6 提供了重命名的方法。在导入名称时可以这样做:

/**** student1.js ****/
export let name = "我来自 student1.js";

/**** student2.js ****/
export let name = "我来自 student2.js";

/**** test_student.js ****/
import {name as name1} from './student1.js';
import {name as name2} from './student2.js';
// 我来自 student1.js
console.log(name1);
// 我来自 student2.js
console.log(name2);