1.什么是ECMA
1.1 什么是ECMA
ECMA(European Computer Manufacturers Association)中文名称为欧洲计算机制造商协会,这个组织的目标是评估、开发和认可电信和计算机标准。1994 年后该组织改名为 Ecma 国际。
1.2 什么是ECMAScript
ECMAScript 是由 Ecma 国际通过 ECMA-262 标准化的脚本程序设计语言。
1.3 为什么要学习ES6
ES6 的版本变动内容最多,具有里程碑意义
ES6 加入许多新的语法特性,编程实现更简单、高效
ES6 是前端发展趋势,就业必备技能
1.4 兼容性
可查看兼容性:http://kangax.github.io/compat-table/es6/
2.ECMAScript6新特性
2.1 let关键字
let 关键字用来声明变量,使用 let 声明的变量有几个特点:
不允许重复声明
块级作用域
不存在变量提升
不影响作用域链
代码演示:
//声明变量let a;let b,c,d;let e = 100;let f = 521, g = 'iloveyou', h = [];//1. 变量不能重复声明let star = '罗志祥';let star = '小猪';//2. 块级作用域 (if else while for){let girl = '周扬青';}console.log(girl);//3. 不存在变量提升console.log(song);let song = '恋爱达人';//4. 不影响作用域链{let school = '清华大学';function fn(){console.log(school);}fn();}
实践案例:
//获取div元素对象let items = document.getElementsByClassName('item');//遍历并绑定事件for(let i = 0;i<items.length;i++){items[i].onclick = function(){//修改当前元素的背景颜色// this.style.background = 'pink';items[i].style.background = 'pink';}}
当我们使用var变量声明i
时,由于变量是全局的,当循环执行完毕后,i
的值已经变为items.length了,使用items[i]将选不中任何标签。而let声明的变量只在对应的代码块生效,互不影响。
应用场景:以后声明变量使用let就对了
2.2 const关键字
const 关键字用来声明常量,const 声明有以下特点:
声明必须赋初始值
标识符一般为大写
不允许重复声明
值不允许修改
块级作用域
代码演示:
//声明常量const SCHOOL = '清华大学';//1. 一定要赋初始值const A;//2. 一般常量使用大写(潜规则)const a = 100;//3. 常量的值不能修改SCHOOL = '北京大学';//4. 块儿级作用域{const PLAYER = 'UZI';}console.log(PLAYER);//5. 对于数组和对象的元素修改, 不算做对常量的修改, 不会报错const TEAM = ['UZI','MLXG','Ming','Letme','XiaoHu'];// TEAM.push('Meiko');
注意: 对象属性修改和数组元素变化不会触发const错误
应用场景:声明对象类型使用 const,非对象类型声明选择let
2.3 变量的解构赋值
ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构赋值。
// 1. 数组的解构const F4 = ['小沈阳','刘能','赵四','宋小宝'];let [xiao, liu, zhao, song] = F4;console.log(xiao);console.log(liu);console.log(zhao);console.log(song);//2. 对象的解构const zhao = {name: '赵本山',age: '不详',xiaopin: function(){console.log("我可以演小品");}};let {name, age, xiaopin} = zhao;console.log(name);console.log(age);console.log(xiaopin);xiaopin();let {xiaopin} = zhao;xiaopin();
注意:频繁使用对象方法、数组元素,就可以使用解构赋值形式
2.4 模板字符串
模板字符串(template string)是增强版的字符串,用反引号(`)标识,特点:
1) 字符串中可以出现换行符
2) 可以使用 ${xxx} 形式输出变量
代码演示:
//2. 内容中可以直接出现换行符let str = `<ul><li>艾伦</li><li>三笠</li><li>阿尔敏</li><li>利威尔</li></ul>`;//3. 变量拼接let lovest = '周星驰';let out = `${lovest}是我心目中最搞笑的演员!!`;console.log(out);
2.5 简化对象写法
ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法。这样的书写更加简洁。
let name = '调查兵团';let change = function(){console.log('为人类献出心脏!!');}const school = {name,change,improve(){console.log("我们可以提高你的技能");}}console.log(school);
2.6 箭头函数
ES6 允许使用「箭头」(=>)定义函数。
let fn = (a,b) => {return a + b;}//调用函数let result = fn(1, 2);console.log(result);
箭头函数的注意点:
如果形参只有一个,则小括号可以省略
函数体如果只有一条语句,则花括号可以省略,函数的返回值为该条语句的执行结果
箭头函数 this 指向声明时所在作用域下 this 的值
箭头函数不能作为构造函数实例化
不能使用 arguments
代码演示:
//1. this 是静态的. this 始终指向函数声明时所在作用域下的 this 的值function getName(){console.log(this.name);}let getName2 = () => {console.log(this.name);}//设置 window 对象的 name 属性window.name = '美职篮';const school = {name: "NBA"}//直接调用getName();getName2();//call 方法调用getName.call(school);getName2.call(school);//2. 不能作为构造实例化对象let Person = (name, age) => {this.name = name;this.age = age;}let me = new Person('xiao',30);console.log(me);//3. 不能使用 arguments 变量let fn = () => {console.log(arguments);}fn(1,2,3);//4. 箭头函数的简写//1) 省略小括号, 当形参有且只有一个的时候let add = n => {return n + n;}console.log(add(9));//2) 省略花括号, 当代码体只有一条语句的时候, 此时 return 必须省略// 而且语句的执行结果就是函数的返回值let pow = n => n * n;console.log(pow(8));
2.6 函数初始值
ES6 允许给函数参数赋值初始值
//1. 形参初始值 具有默认值的参数, 一般位置要靠后(潜规则)function add(a,c=10,b) {return a + b + c;}let result = add(1,2);console.log(result);//2. 与解构赋值结合function connect({host="127.0.0.1", username,password, port}){console.log(host)console.log(username)console.log(password)console.log(port)}connect({host: '182.127.71.134',username: 'root',password: 'root',port: 3306})
2.7 rest参数
ES6 引入 rest 参数,用于获取函数的实参,用来代替 arguments
// ES5 获取实参的方式function date(){console.log(arguments);}date('白芷','阿娇','思慧');// rest 参数function date(...args){console.log(args);// filter some every map}date('阿娇','柏芝','思慧');// rest 参数必须要放到参数最后function fn(a,b,...args){console.log(a);console.log(b);console.log(args);}fn(1,2,3,4,5,6);
2.8 spread 扩展运算符
扩展运算符(spread)也是三个点(...)。它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列,对数组进行解包。
// 『...』 扩展运算符能将『数组』转换为逗号分隔的『参数序列』//声明一个数组 ...const tfboys = ['易烊千玺','王源','王俊凯'];// => '易烊千玺','王源','王俊凯'// 声明一个函数function chunwan(){console.log(arguments);}chunwan(...tfboys);// chunwan('易烊千玺','王源','王俊凯')
2.9 Symbol
2.9.1 基本使用
ES6 引入了一种新的原始数据类型 Symbol,表示独一无二的值。它是JavaScript 语言的第七种数据类型,是一种类似于字符串的数据类型。
Symbol 特点
Symbol 的值是唯一的,用来解决命名冲突的问题
Symbol 值不能与其他数据进行运算
Symbol 定义的对象属性不能使用 for…in 循环遍历 ,但是可以使用Reflect.ownKeys 来获取对象的所有键名
代码演示:
//创建Symbollet s = Symbol();console.log(s, typeof s);let s2 = Symbol('海贼王');let s3 = Symbol('海贼王');console.log(s2===s3); //false//Symbol.for 创建// 通过 Symbol.for() 方法创建可共享的 Symbollet s4 = Symbol.for('柯南');let s5 = Symbol.for('柯南');console.log(s4===s5); //true//不能与其他数据进行运算let result = s + 100; //报错let result = s > 100; //报错let result = s + s; //报错
2.9.2 内置值
除了定义自己使用的 Symbol 值以外,ES6 还提供了 11 个内置的 Symbol 值,指向语言内部使用的方法。可以称这些方法为魔术方法,因为它们会在特定的场景下自动执行。
Symbol.hasInstance
:一个在执行instanceof
时调用的内部方法,用于检测对象的继承信息。
Symbol.isConcatSpreadable
:一个布尔值,用于表示当传递一个集合作为Array.prototype.concat()
方法的参数时,是否应该将集合内的元素规整到同一层级。
Symbol.iterator()
:检查指定对象中是否存在默认的函数类型迭代器。
Symbol.match(regex)
:一个在调用String.prototype.match()
方法时调用的方法,用于比较字符串。
Symbol.replace(regex, replacement)
:一个在调用String.prototype.replace()
方法时调用的方法,用于替换字符串的子串。
Symbol.search(regex)
:一个在调用String.prototype.search()
方法时调用的方法,用于在字符串中定位子串。
Symbol.species(regex)
:用于创建派生对象的构造函数。
Symbol.split
:一个在调用String.prototype.split()
方法时调用的方法,用于分割字符串。
Symbol.toPrimitive
:一个返回对象原始值的方法。
Symbol.toStringTag
:一个在调用String.prototype.toString()
方法时使用的字符串,用于创建对象描述。
Symbol.unscopables
:一个定义了一些不可被 with 语句引用的对象属性名称的对象集合。
代码演示:
class Person{static [Symbol.hasInstance](param){console.log(param);console.log("我被用来检测类型了");return false;}}let o = {};console.log(o instanceof Person);const arr = [1,2,3];const arr2 = [4,5,6];arr2[Symbol.isConcatSpreadable] = false;//false则为不展开 concat后为[1,2,3,[4,5,6]] true为展开,concat后为[1,2,3,4,5,6]console.log(arr.concat(arr2));
2.10 迭代器
遍历器(Iterator)就是一种机制。它是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署 Iterator 接口,就可以完成遍历操作。
1) ES6 创造了一种新的遍历命令 for...of 循环,Iterator 接口主要供 for...of 消费
2) 原生具备 iterator 接口的数据(可用 for of 遍历):Array、Arguments、Set、Map、String、TypedArray、NodeList
3) 工作原理
a) 创建一个指针对象,指向当前数据结构的起始位置
b) 第一次调用对象的 next 方法,指针自动指向数据结构的第一个成员
c) 接下来不断调用 next 方法,指针一直往后移动,直到指向最后一个成员
d) 每调用 next 方法返回一个包含 value 和 done 属性的对象
代码演示:
//声明一个数组const xiyou = ['唐僧','孙悟空','猪八戒','沙僧'];//使用 for...of 遍历数组for(let v of xiyou){console.log(v);}let iterator = xiyou[Symbol.iterator]();//调用对象的next方法console.log(iterator.next());console.log(iterator.next());console.log(iterator.next());console.log(iterator.next());console.log(iterator.next());