目标:学习 ES6的新语法;为未来的工做打下基础;javascript
ES6 介绍html
let const:定义变量的新途径;前端
解构赋值:快速给变量赋值;java
内置对象的扩展:加强功能;node
ES 6 降级处理:对不支持es6版本的环境如何处理?git
提供了更加方便的新语法弥补 JS 语言自己的缺陷,新增了便捷的语法程序员
给内置对象增长了更多的方法es6
ES6 让 JS 能够开发复杂的大型项目,成为企业级开发语言github
新的前端项目中大量使用 ES6 的新语法面试
ECMAScript 6,简称ES6 。它是一种语言标准,6表示版本号。 它是Ecma国际(European Computer Manufacturers Association)于2015年6月正式发布的 JavaScript 语言的下一代标准,正式名为ECMAScript 2015(简写ES2015)。它的目标是使得JavaScript语言能够用来编写复杂的大型应用程序,成为企业级开发语言。相比较ES5(2011年发布的),它改进是很是大的,因此在一些场景下ES6也泛指ES2015及以后的新增特性,虽然以后的版本应当称为ES七、ES8等,但统称es6。
ECMA的第39号技术专家委员会(Technical Committee 39,简称TC39)负责制订ECMAScript标准组织每一年都会发布ECMAScript的版本
ES2015:称为es6。
ES2018: https://www.ecma-international.org/ecma-262/8.0/index.html
ES2019:极可能也会在今年6月份发布
与javascript的关系:ECMAScript是一种语言标准,javascript实现了这个标准。javascipt由三部分组成
ECMAScript
DOM
BOM
es6新增了不少强大的语法,以下是比较常使用的:
let 和 const
解构赋值
函数
字符串扩展
数组扩展
新的定义对象的方式
参考:
各类环境中对es6的支持程度: http://kangax.github.io/compat-table/es6/
es5中提供了定义变量的关键字var,可是这个关键字的功能有限,它定义的变量也有不少奇怪的特性,并不能彻底知足如今愈来愈复杂的环境,因此在es6中新增了两个关键字:let,const。
它用来定义变量,基本使用格式与var关键字同样。在能够在使用var 的地方改为let。
不能重复定义
具备块级做用域
没有变量提高(var定义的变量是有变量提高的),必须先定义再使用
不会附加到window对象的属性中
// 1. let 定义变量,变量不能够再次定义,但能够改变其值
let name = 'zhangsan';
name = 'lisi';
console.log(name); // lisi
let name = 'wangwu'; // 再次定义,报错:Identifier 'name' has already been declared
// 2. 具备块级做用域,块就是大括号
{
let age = 18;
console.log(age); // 18
}
console.log(age); // 报错,此做用域中没有age的定义
for (let i = 0; i < 10; i++) {
// i 只能在此范围内使用,由于有块级做用域
}
console.log(i); // 报错,此做用域中没有age的定义
// 3. 没有变量提高,必须先定义再使用
console.log(gender); // 报错,此时尚未定义gender
let gender = '男';
console.log(1); // 不报错,输出undefined
var a = 1;
// 4. let声明的变量不会压到window对象中,是独立的
let hobby = '吃饭';
var a = 1
console.log(window.hobby); // undefined
console.log(window.a); // undefined
若是使用var声明了变量,也不能再次用let声明了,反之也是不行的。缘由也是这个变量已经被声明过了。
最佳实践:实际开发要么所有使用var,要么所有使用let。由团队开发规范来定。
多个程序员共同开发项项目时,会遇到一种场景:有一些数据你们都须要用到,可是都不能修改,即数据是只读的。
举个例子:在开发公司的网站时,公司的基本信息:地址,公司名,电话等等信息能够在多个地方都须要使用,但不容许去修改。 这个时候,就能够把这些数据保存在常量中。
// 格式:
const 常量名 = 常量值;
const COMPANY_NAME = "XXX公司"
区别于变量名,常量名通常采用全大写的方式
多个单词之间使用_划线分隔。
const obj = {a:1};
obj.a = 2;
console.log(obj); // 问题:obj对象的属性值a是否修改了。
const实际上保证的,并非变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动。
对于简单类型的数据(数值、字符串、布尔值),值就保存在变量指向的那个内存地址,所以等同于常量。
对于复合类型的数据(主要是对象和数组),变量指向的内存地址,保存的只是一个指向实际数据的指针,const只能保证这个指针是固定的(即老是指向另外一个固定的地址),至于它指向的数据结构是否是可变的,就彻底不能控制了。所以,将一个对象声明为常量必须很是当心,它的属性是能够修改的。
具备块级做用域
没有变量提高,必须先定义再使用
常量也是独立的,定义后不会压入到window对象中,不是window对象的属性
关键字 | 变量提高 | 块级做用域 | 初始值 | 更改值 | 经过window调用 |
---|---|---|---|---|---|
let | × | √ | - | Yes | No |
const | × | √ | Yes | No | No |
var | √ | × | - | Yes | Yes |
ES 6 容许按照必定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)。
它有两个动做:
- 解构:意思是把有结构的数据分解开成为一个一个的值;
- 赋值:把解构以后的值保存到变量。
demo
let arr = [1,2,3,4];
// 需求,快速地从数组中取出值来赋值给变量
let a = arr[0];
它可以快速从数组中取出值保存到变量中。它的本质是给变量赋值。
内容:
语法格式及解构规则
常规使用:变量个数等于数组长值
很是规使用
变量个数大于数组长度
变量个数小于数组长度
高级使用
用空跳过不须要的值
剩余值
复杂嵌套场景
小面试题
// 格式:
let [变量1,变量2,
// 场景1,变量和值一一对应
let arr = [5, 9, 10];
let [a, b, c] = arr;
console.log(a, b, c); // 输出 5 9 10
// 等价于:
let a = arr[0];
let b = arr[1];
let c = arr[2];
注意:
“=”左右两边的格式要统一。
// 场景2,变量多,值少
let arr = [5, 9, 10];
let [a, b, c, d] = arr;
console.log(a, b, c, d); // 输出 5 9 10 undefined
// 结论:没有匹配上的值是undefined
// 场景3,变量少,值多
let arr = [5, 9, 10, 8, 3, 2];
let [a, b] = arr;
console.log(a, b); // 5, 9
// 结论:多余的忽略
// 场景4,按需取值
let arr = [5, 9, 10, 8, 3, 2];
let [, , a, , b] = arr; // 不须要用变量接收的值,用空位占位
console.log(a, b); // 10, 3
// 场景5,剩余值
let arr = [5, 9, 10, 8, 3, 2];
let [a, b,
注意:
... 的收集
Rest element must be last element。必须在最后;
// 场景6,复杂的场景,只要符合模式,便可解构
let arr = ['zhangsan', 18, ['175cm', '65kg']];
let [, , [a, b]] = arr;
console.log(a, b); // 175cm 65kg
交换两个变量的值?
var a = 1, b = 2;
// 写代码,实现互换a,b的值
// ????
console.info(a,b); // 要求输出 2, 1
做用:快速从对象中获取值保存到变量中。它的本质是给变量赋值。
也经过以下几种场景来学习
变量名和属性名同样
变量更名
剩余值
复杂嵌套
完整格式:
let {"属性名1":变量名1, "属性名2":变量名2 } = {"属性名1":属性值1,"属性名2":属性值2,
解析规则:
右边的"属性名"与左边的“属性名” 一致,则把右边的属性值赋值给左边的变量名。
精简格式:
若是左侧对象中属性名与变量名相同,则可左侧合并:
let {变量名1,变量名2} = {"属性名1":属性值1,"属性名2":属性值2,
解析规则:
右边的"属性名"与左边的变量名 一致,则把右边的属性值赋值给左边的变量名。
场景1,变量名和属性名同样
// 场景1,默认要求变量名和属性名同样
let { name, age } = {age: 27, name: '阳明'};
console.log(name, age);
let {a, c} = {a: 'hello', b: 'world'};
console.log(a, c); // hello, undefined
注意:
“=” 左右两边的格式一致。
对象是属性的无序集合,因此不须要管顺序
场景2,变量更名
// 场景2,能够经过:为变量更名
let {a, b:c} = {name: '王阳明', b: 'world'};
console.log(a, c); // hello, world
// 把其它的属性全收集起来
let obj = {name:'zs', age:20, gender:'男'};
let {name,
只要符合模式,便可解构
// 复杂的场景,只要符合模式,便可解构
let obj = {
name: 'zhangsan',
age: 22,
dog: {
name: '毛毛',
age: 3
}
};
let {dog: {name, age}} = obj;
console.log(name, age); // 毛毛 3
// 假设从服务器上获取的数据以下
let response = {
data: ['a', 'b', 'c'],
meta: {
code: 200,
msg: '获取数据成功'
}
}
// 如何获取到 code 和 msg
let { meta: { code, msg } } = response;
console.log(code, msg); // 200, 获取数据成功
es6对函数的功能进行了一些拓展,补充了不少功能。学习这个部分的内容咱们就能够灵活地使用函数。
内容
参数默认值
箭头函数(重点)
rest参数
参数默认值是一个很是实用的功能,学习这个部分咱们能够更加地理解api中的默认参数的实现,能写出用户体验更好的函数。
参数的默认值在以前的课程内容已经涉及,例如在xhr.open(type,url,是否异步)方法中,第3个参数默认是true,即表示异步ajax。
默认值的意思是:
若是传入,就用你传的值
若是不传入,就使用某一个特殊的、事先定义好的值。这个值也就是默认值。
ES6 以前,函数不支持设置参数的默认值(其它大多数编程语言都是支持的)。但虽然在语法层面上不支持,程序员们也会想一些变通的方法。
// ES5 中给参数设置默认值的变通作法
function open(type, url,isAsync) {
if(isAsync === undefined){
isAsync = true;
}
console.log(type, url, isAsync);
}
// 下面这两句是等价的
open("get","common/get");//
open("get","common/get",true);
open("get","common/get",false);
function 函数名(参数名1='默认值1',参数名2='默认值3',参数名1='默认值3'){
}
// E65 给参数设置默认值
function open(type, url,isAsync=true) {
console.log(type, url, isAsync);
}
思考:可否给type设置默认值,为'get' ?
function open(type='get', url,isAsync=true)
注意:
带默认值的形参放在形参列表的后面
let obj1 = { url: "/common/get", type:"get"}
function open(obj){
console.info(obj.url, obj.get)
}
function open({url,type}){
console.info(url,type)
}
function open({url,type='get'}){
console.info(url,type)
}
学习箭头函数能让代码更简洁,效率更高;能看懂别人写的代码 ;
let fn3 = x => x * 2;
内容
定义及格式
三种简化原则
三个特色
典型应用场景
ES6 中容许使用箭头函数的方式来定义一个函数。前面学习的定义一个函数有两种方式:
函数声明式
函数表达式
如今有了一个新的方式:
3. 箭头函数
let 函数名 = (形参1,
// 1. 函数声明式
function fu1(x){
return x * 2;
}
// 2. 函数表达式
let fn2 = function (x) {
return x * 2;
}
// 3. 箭头函数
let fn3 = (x) => {
return x * 2;
}
第一眼看到这个箭头函数时,会以为很奇怪。若是从函数表达式的格式出发, 通过以下2步演化步骤就能够获得。
把function 关键字 后移动到 ()和 {} 中间
把function 改写成 =>
注意:
- `=>`是一个总体,不要加空格
- 箭头函数只在定义上有些区别,但在函数调用格式上,是没有区别的。
当形参有且只有一个,能够省略小括号
当函数体只有一条语句,能够省略大括号;
当函数体只有一条语句,而且就是return语句,则能够省略return
// 完整箭头函数
let fn = (x) => {
return x * 2;
}
// 参数只有一个,省略小括号
let fn = x => {
return x * 2;
}
// 函数体中只有一个返回语句,能够省略大括号
let fn = x => x*2
它与普通函数的区别
内部没有arguments
内部没有this
不能做为构造器
let fn = (a,b) => {
console.log(arguments); // 报错,arguments is not defined
};
fn(1, 2);
var name = 'lisi'; // 测试时,这里必须用var,由于用let声明的变量不能使用window调用 let obj = { name: 'zhangsan', fn : () => { console.log(this); // window对象 console.log(this.name); // lisi } }; obj.fn();
let Person = () => { }; let obj = new Person(); // 报错,Person is not a constructor // 换个角度理解,箭头函数中都没有本身的this,怎么处理成员,因此不能当构造函数
定义函数
回调函数
事件响应函数
var arr = [1,2,3] arr.sort(function(a,b){ return a - b}); // 简化 arr.sort((a,b)=>a-b)
rest: 其它的,剩余的; rest 参数 用于获取函数多余参数,把它们放在一个数组中。
在定义函数时,在最后一个参数前面加上..., 则这个参数就是剩余参数;
let fn = function(参数1,参数2,...rest参数){} let fn = (参数1,参数2,...rest参数)=>{ }
只是在定义函数时,在形参列表中区别一下,而在调用函数时并没有区别。
回答以下问题
function f1 (x,y){ console.log(x,y) } f1(1,2); f1(2,3,4); function f2 (x,...y){ console.log(x,y) } f2(1,2); f2(2,3,4);
问题:编写一个函数,求全部参数之和;
方法一:arguments
方法二:rest参数
function getSum (){ // 在这里写你的代码 var sum = 0 ; for(var i = 0; i < arguments.length; i++){ console.info( arguemnts[i]) sum += arguments[i]; } }
若是以箭头函数 的方式去定义这个函数,则内部不可使用arguments这个对象了。此时,咱们就可使用
rest 参数,它能够替代 arguments 的使用。 代码以下:
// 参数不少,不肯定多少个,可使用剩余参数 const getSum = (...values) => { var sum = 0 ; for(var i = 0; i < values.length; i++){ console.info( values[i]) sum += values[i]; } } // 调用 console.log(fn(6, 1, 100, 9, 10));
数组对象是js中很是重要的对象,它自己提供了很是多的方法:sort,push,pop,unshift, splice,concat.... 。因为前端的主要工做内容之一是与后端进行数据交互,而数据交互的载体大可能是数组,因此咱们对数组的操做要求也很是高。
曾经有一道面试题:写出10个你用过的与数组相关的方法。
这一小节的学习会让咱们多掌握几个数组的方法。
功能:它的做用是把数组中的元素一项项地展开:把一个总体的数组拆开成单个的元素。
格式:...数组
基本用法
console.info(...[1,2,3]);
应用1: 数组合并
从把一个数组中的值全取出来,放在另外一个数组中的
var arr0 = ['a','b']; var arr1 = [1,2,3]; var arr2 = [4, ...arr1]; var arr3 = [..arr0 ,...arr1];
应用2:Math.max()
Math.max(1,3,4,6); var arr = [1,3,4,6]; Math.max(...arr);
功能:把其它非数组的对象转成数组。
格式: 数组 = Array.from(非数组对象)
它的实参有三种状况:
自定义的,特殊格式的对象
let fakeArr = { 0: 'a', 1: 'b', 2: 'c', length: 3 };
arguments对象
DOM 操做返回的 NodeList 集合
在实际的开发中,咱们常常会遇到一种场景:从一个数组中找出符合条件的元素。咱们要的讨论的重点是如何从数组中找出符合条件的元素,固然,咱们能够经过手写循环的方式来实现这个功能,可是如今es6中提供了现成的功能。find/findIndex
做用:从数组中找出咱们符合条件的第一个元素(或者是下标)。
find和findIndex的格式是一致的。
let result = [].find(function(item,index,self){ //.... // 若是知足查找的条件 return true; })
回调函数有三个参数,分别表示:数组元素的值、索引及整个数组
若是某次循环返回的是true,find和findIndex方法的返回值就是知足这个条件的第一个元素或索引
find和findIndex方法,会遍历传递进来的数组
若是在回调函数体内,某个时刻return true,则表示查找过程结果,返回值就是本轮循环中的元素(或者是下标);若是所有的循环结束,也没有返回true,则表示没有找到。
findIndex 找到数组中第一个知足条件的成员并返回该成员的索引,若是找不到返回 -1。
let arr = [1, 2, 4, 0, -4, 3, -2, 9]; arr.find(function (item, index, self) { console.log(item); // 数组中的每一个值 console.log(index); // 数组中的每一个索引/下标 console.log(self); // 当前的数组 });
// 用法:找数组中第一个小于0的数字 let arr = [1, 2, 4, 0, -4, 3, -2, 9]; let result = arr.find(function (item) { return item < 0; //遍历过程当中,根据这个条件去查找 }); console.log(result); // -4
注意经过箭头函数来简化代码。
从一个复杂的对象数组中找出符合条件的对象。
let data = [ {id:2,name:'严高',age:15}, {id:3,name:'徐阶',age:17}, {id:4,name:'高拱',age:18}, {id:1,name:'张居正',age:12}, ]
findIndex 的使用和 find 相似,只不过它查找的不是数组中的元素,而是元素的下标。
功能:判断数组是否包含某个值,返回 true / false
格式:数组.includes(参数1,参数2)
参数1,必须,表示查找的内容
参数2,可选,表示开始查找的位置,0表示从第一个元素开始找。默认值是0。
示例:
let arr = [1, 4, 3, 9]; console.log(arr.includes(4)); // true console.log(arr.includes(4, 2)); // false, 从2的位置开始查,因此没有找到4 console.log(arr.includes(5)); // false
字符串也有这个方法,功能也是类似的。
es6中对字符串提供了新的特性,咱们介绍其中几个方法:
模板字符串
includes
startsWith
endWith
repeat
在作字符串拼接时,使用+来拼接复杂内容是很麻烦的,而模板字符串能够解决这个问题。
格式:`${变量} ${表达式}`
语法:
模板字符串使用反引号 ` 把内容括起来,相似于普通字符串的""。
${}充当界定符的做用,其中能够写变量名,表达式等。
容许字符串内部进行换行,代码更好读更好的体验
示例:
let name = 'zs'; let age = 18; // 拼接多个变量,在模板字符串中使用占位的方式,更易懂 let str = `我是${name},今年${age}`; // 内容过多能够直接换行 let obj = [{name: 'flex', age: 20},{name: 'james', age: 21}]; let arr = ['175cm', '60kg']; let html = ` <div> <ul> <li>${obj.name}</li> <li>${obj.age}</li> <li>${arr[0]}</li> <li>${arr[1]}</li> </ul> </div>
格式:str.includes(searchString, [position])
功能:返回布尔值,表示是否找到了参数字符串
position: 从当前字符串的哪一个索引位置开始搜寻子字符串,默认值为0。
格式:str.startsWidth(searchString, [position])
功能:返回布尔值,表示参数字符串是否在原字符串的头部或指定位置
position: 在 str 中搜索 searchString 的开始位置,默认值为 0,也就是真正的字符串开头处。
格式:str.endsWith(searchString, [len])
功能:返回布尔值,表示参数字符串是否在原字符串的尾部或指定位置.
len:可选。做为 str 的长度。默认值为 str.length。
repeat方法返回一个新字符串,表示将原字符串重复n次。
语法:str.repeat(n)
let html = '<li>itheima</li>'; html = html.repeat(10);
ES6 将全局方法parseInt()和parseFloat(),移植到Number对象上面,行为彻底保持不变。
Number.parseInt()
Number.parseFloat()
Set是集合的意思。是ES6 中新增的内置对象,它相似于数组,可是成员的值都是惟一的,即没有重复的值。使用它能够方便地实现用它就能够实现数组去重的操做。
建立空set;
根据已有数组建立set
// 1. 基本使用 let set = new Set(); // 获得一个空的Set对象 let set = new Set([1,2,3])
size:属性,获取 set 中成员的个数,至关于数组中的 length
add(value):添加某个值,返回 Set 结构自己。
delete(value):删除某个值,返回一个布尔值,表示删除是否成功。
has(value):返回一个布尔值,表示该值是否为Set的成员。
clear():清除全部成员,没有返回值。
遍历for of
let arr = [1,1,2,3,3]; console.info([...new Set(arr)])
对属性名的简化
对方法的简化
let name = 'zhangsan', age = 20, gender = '女'; let obj = { name: name, // 原来的写法 age, // 对象属性和变量名相同,能够省略后面的 “:age”,下面的gender同理 gender, fn1:function(){ // 常规写法 console.log(123); }, fn2 () { // 能够省略 console.log(456); } }; console.log(obj.age); // 20 obj.fn2(); // 456
ES6 (2015年10月)虽好,可是有兼容性问题,IE7-IE11 基本不支持 ES6
在最新的现代浏览器、移动端、Node.js 中都支持 ES6
后续咱们会讲解如何处理 ES6 的兼容性
由于 ES 6 有浏览器兼容性问题,可使用一些工具进行降级处理,例如:babel
降级处理 babel 的使用步骤
安装 Node.js
命令行中安装 babel
配置文件 .babelrc
运行
安装 Node.js
项目初始化(项目文件夹不能有中文)
npm init -y
在命令行中,安装 babel babel官网
npm install @babel/core @babel/cli @babel/preset-env
配置文件 .babelrc (手工建立这个文件)
babel 的降级处理配置
{ "presets": ["@babel/preset-env"] }
在命令行中,运行
# 把转换的结果输出到指定的文件 npx babel index.js -o test.js # 把转换的结果输出到指定的目录 npx babel 包含有js的原目录 -d 转换后的新目录
参考:babel官网