ES6_新特性
let
let关键字用来声明变量,使用 let声明的变量有几个特点:
1) 不允许重复声明
2) 块级作用域
3) 不存在变量提升
4) 不影响作用域链
<script>
//声明变量
let a;
let b,c,d;
let e = 100;
let f = 521, g = 'iloveyou', h = [];
//1. 变量不能重复声明
// let star = '罗志祥';
// let star = '小猪';
//2. 块级作用域 全局, 函数, eval
// if else while for
// {
// let girl = '周扬青';
// }
// console.log(girl);
//3. 不存在变量提升
// console.log(song);
// let song = '恋爱达人';
//4. 不影响作用域链
{
let school = '清华';
function fn(){
console.log(school);
}
fn();
}
</script>
经典案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>点击 DIV 换色</title>
<link
crossorigin="anonymous"
href="https://cdn.bootcss.com/twitter-bootstrap/3.3.7/css/bootstrap.min.css"
rel="stylesheet"
/>
<style>
.item {
width: 100px;
height: 50px;
border: solid 1px rgb(42, 156, 156);
float: left;
margin-right: 10px;
}
</style>
</head>
<body>
<div class="container">
<h2 class="page-header">点击切换颜色</h2>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
<script>
//获取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'
}
}
</script>
</body>
</html>
const
const 关键字用来声明常量, const声明有以下特点
1) 声明必须赋初始值
2) 标识符一般为大写
3) 不允许重复声明
4) 值不允许修改
5) 块级作用域
注意:对象属性修改和数组元素变化不会触发const错误
应用场景:声明对象类型使用const,非对象类型声明选择 let
<script>
//声明常量
const SCHOOL = '清华';
//1. 一定要赋初始值
// const A;
//2. 一般常量使用大写(潜规则)
// const a = 100;
//3. 常量的值不能修改
// SCHOOL = 'QINGHUA';
//4. 块儿级作用域
// {
// const PLAYER = 'UZI';
// }
// console.log(PLAYER);
//5. 对于数组和对象的元素修改, 不算做对常量的修改, 不会报错
const TEAM = ['UZI','MXLG','Ming','Letme'];
// TEAM.push('Meiko');
</script>
变量的解构赋值
ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构赋值。
注意:频繁使用对象方法、数组元素,就可以使用解构赋值形式
<script>
//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();
</script>
模板字符串
模板字符串(template string)是增强版的字符串,用反引号(`)标识 ,
特点:
1) 字符串中可以出现换行符
2) 可以使用 ${xxx} 形式输出变量
注意:当遇到字符串与变量拼接的情况可以使用模板字符串
<script>
//1. 声明
// let str = `我也是一个字符串哦!`;
// console.log(str, typeof str);
//2. 内容中可以直接出现换行符
let str = `<ul>
<li>沈腾</li>
<li>玛丽</li>
<li>魏翔</li>
<li>艾伦</li>
</ul>`;
//3. 变量拼接
let lovest = '魏翔';
let out = `${lovest}是我心目中最搞笑的演员!!`;
console.log(out);
</script>
简化对象写法
ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法。这样的书写更加简洁。
<script> let name = '新东方'; let change = function(){ console.log('我们可以改变你!!'); } const school = { name, change, improve(){ console.log("我们可以提高你的技能"); } } console.log(school); </script>
箭头函数
ES6 允许使用 「 箭头 」(=>)定义函数。
注意点:
1) 如果形参只有一个,则小括号可以省略
2) 函数体如果只有一条语句,则花括号可以省略,函数的返回值为该条语句的执行结果
3) 箭头函数this指向声明时所在作用域下this 的值
4) 箭头函数不能作为构造函数实例化
5) 不能使用arguments
注意:箭头函数不会更改this指向,用来指定回调函数会非常合适
<script>
//声明一个函数
// let fn = function(){ }
// let fn = (a,b) => {
// return a + b;
// }
//调用函数
// let result = fn(1, 2);
// console.log(result);
//1. this 是静态的. this 始终指向函数声明时所在作用域下的 this 的值
function getName(){
console.log(this.name);
}
let getName2 = () => {
console.log(this.name);
}
//设置 window 对象的 name 属性
window.name = '新东方';
const school = {
name: "XINDONGFANG"
}
//直接调用
// 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));
</script>
经典案例
<script>
//需求-1 点击 div 2s 后颜色变成『粉色』
//获取元素
let ad = document.getElementById('ad');
//绑定事件
ad.addEventListener("click", function(){
//保存 this 的值
// let _this = this;
//定时器
setTimeout(() => {
//修改背景颜色 this
// console.log(this);
// _this.style.background = 'pink';
this.style.background = 'pink';
}, 2000);
});
//需求-2 从数组中返回偶数的元素
const arr = [1,6,9,10,100,25];
// const result = arr.filter(function(item){
// if(item % 2 === 0){
// return true;
// }else{
// return false;
// }
// });
const result = arr.filter(item => item % 2 === 0);
console.log(result);
// 箭头函数适合与 this 无关的回调. 定时器, 数组的方法回调
// 箭头函数不适合与 this 有关的回调. 事件回调, 对象的方法
</script>
参数默认值
<script>
//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: 'baidu.com',
username: 'root',
password: 'root',
port: 3306
})
</script>
rest参数
ES6引入rest参数,用于获取 函数的实参,用来代替 arguments。
注意:rest参数非常适合不定个数参数函数的场景
<script>
// 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);
</script>
扩展运算符
扩展运算符(spread)也是三个点 (...)。
它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列,对数组进行解包。
<script>
// 『...』 扩展运算符能将『数组』转换为逗号分隔的『参数序列』
//声明一个数组 ...
const tfboys = ['易烊千玺','王源','王俊凯'];
// => '易烊千玺','王源','王俊凯'
// 声明一个函数
function chunwan(){
console.log(arguments);
}
chunwan(...tfboys);// chunwan('易烊千玺','王源','王俊凯')
</script>
经典案例
<script>
//1. 数组的合并 情圣 误杀 唐探
// const kuaizi = ['王太利','肖央'];
// const fenghuang = ['曾毅','玲花'];
// // const zuixuanxiaopingguo = kuaizi.concat(fenghuang);
// const zuixuanxiaopingguo = [...kuaizi, ...fenghuang];
// console.log(zuixuanxiaopingguo);
//2. 数组的克隆
// const sanzhihua = ['E','G','M'];
// const sanyecao = [...sanzhihua];// ['E','G','M']
// console.log(sanyecao);
//3. 将伪数组转为真正的数组
const divs = document.querySelectorAll('div');
const divArr = [...divs];
console.log(divArr);// arguments
</script>
迭代器
遍历器(Iterator)就是一种机制。它是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署 Iterator 接口,就可以完成遍历操作。
1) ES6创造了一种新的遍历命令 for...of循环, Iterator接口主要供 for...of消费
2) 原生具备 iterator接口的数据 (可用 for of遍历 )
a) Array
b) Arguments
c) Set
d) Map
e) String
f) TypedArray
g) NodeList
3) 工作原理
a) 创建一个指针对象,指向当前数据结构的起始位置
b) 第一次调用对象的 next方法,指针自动指向数据结构的第一个成员
c) 接下来不断调用 next方法,指针一直往后移动,直到指向最后一个成员
d) 每调用 next方法返回一个包含 value和 done属性的对象
注: 需要自定义遍历数据的时候,要想到迭代器。
案例可在我的另一篇文章《ES6_Symbol》的Symbol.iterator模块查看。
生成器
生成器函数是 ES6提供的一种异步编程解决方案,语法行为与传统函数完全不同。
代码说明:
1) * 的位置没有限制
2) 生成器函数返回的结果是迭代器对象,调用迭代器对象的 next方法可以得到yield语句后的值
3) yield相当于函数的暂停标记,也可以认为是函数的分隔符,每调用一次 next方法,执行一段代码
4) next方法可以传递实参,作为 yield语句的返回值
生成器函数
<script> //生成器其实就是一个特殊的函数 //异步编程 纯回调函数 node fs ajax mongodb //函数代码的分隔符 function* gen() { console.log(111); yield '一只没有耳朵'; console.log(222); yield '一只没有尾部'; console.log(333); yield '真奇怪'; console.log(444); } // let iterator = gen(); // iterator.next(); // console.log(iterator.next()); // iterator.next(); // console.log(iterator.next()); // iterator.next(); // console.log(iterator.next()); // iterator.next(); // console.log(iterator.next()); //遍历 for (let v of gen()) { console.log(v); } </script>

生成器函数参数
<script> function* gen(arg) { console.log(arg); let one = yield 111; console.log(one); let two = yield 222; console.log(two); let three = yield 333; console.log(three); } //执行获取迭代器对象 let iterator = gen('AAA'); console.log(iterator.next()); //next方法可以传入实参 console.log(iterator.next('BBB')); console.log(iterator.next('CCC')); console.log(iterator.next('DDD')); </script>

生成器函数实例
<script> //模拟获取 用户数据 订单数据 商品数据 function getUsers() { setTimeout(() => { let data = '用户数据'; //调用 next 方法, 并且将数据传入 iterator.next(data); }, 1000); } function getOrders() { setTimeout(() => { let data = '订单数据'; iterator.next(data); }, 1000) } function getGoods() { setTimeout(() => { let data = '商品数据'; iterator.next(data); }, 1000) } function* gen() { let users = yield getUsers(); console.log(users); let orders = yield getOrders(); console.log(orders); let goods = yield getGoods(); console.log(goods); } //调用生成器函数 let iterator = gen(); iterator.next(); </script>

Set
ES6 提供了新的数据结构 Set(集合) 。它类似于数组,但成员的值都是唯一的 ,集合实现了 iterator接口,所以可以使用『扩展运算符』和『 for…of…』进行遍历,集合的属性和方法:
1) size返回集合的元素个数
2) add增加一个新元素,返回当前集合
3) delete删除元素,返回 boolean 值
4) has检测集合中是否包含某个元素,返回 boolean值
5) clear清空集合,返回 undefined
<script> //声明一个 set let s = new Set(); let s2 = new Set(['大事儿','小事儿','好事儿','坏事儿','小事儿']); //元素个数 // console.log(s2.size); //添加新的元素 // s2.add('喜事儿'); //删除元素 // s2.delete('坏事儿'); //检测 // console.log(s2.has('糟心事')); //清空 // s2.clear(); // console.log(s2); for(let v of s2){ console.log(v); } </script>
经典案例
<script> let arr = [1,2,3,4,5,4,3,2,1]; //1. 数组去重 // let result = [...new Set(arr)]; // console.log(result); //2. 交集 let arr2 = [4,5,6,5,6]; // let result = [...new Set(arr)].filter(item => { // let s2 = new Set(arr2);// 4 5 6 // if(s2.has(item)){ // return true; // }else{ // return false; // } // }); // let result = [...new Set(arr)].filter(item => new Set(arr2).has(item)); // console.log(result); //3. 并集 // let union = [...new Set([...arr, ...arr2])]; // console.log(union); //4. 差集 let diff = [...new Set(arr)].filter(item => !(new Set(arr2).has(item))); console.log(diff); </script>
Map
ES6 提供了 Map 数据结构。
它类似于对象,也是键值对的集合。
但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。
Map也实现了iterator接口,所以可以使用『扩展运算符』和『 for…of…』进行遍历。
Map的属性和方法:
1) size 返回 Map的元素个数
2) set 增加一个新元素,返回当前 Map
3) get 返回键名对象的键值
4) has 检测 Map中是否包含某个元素,返回 boolean值
5) clear 清空集合,返回 undefined
<script> //声明 Map let m = new Map(); //添加元素 m.set('name','少林达摩院'); m.set('change', function(){ console.log("我们可以改变你!!"); }); let key = { school : 'SHAOLING' }; m.set(key, ['北京','上海','深圳']); //size // console.log(m.size); //删除 // m.delete('name'); //获取 // console.log(m.get('change')); // console.log(m.get(key)); //清空 // m.clear(); //遍历 for(let v of m){ console.log(v); } // console.log(m); </script>
class类
ES6 提供了更接近传统语言的写法,引入了 Class(类)这个概念,作为对象的模板。
通过 class关键字,可以定义类。
基本上, ES6 的 class可以看作只是一个语法糖,它的绝大部分功能, ES5 都可以做到,新的 class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。
知识点:
1) class声明类
2) constructor定义构造函数初始化
3) extends继承父类
4) super调用父级构造方法
5) static定义静态方法和属性
6) 父类方法可以重写
类声明
<script> //手机 function Phone(brand, price){ this.brand = brand; this.price = price; } //添加方法 Phone.prototype.call = function(){ console.log("我可以打电话!!"); } //实例化对象 let Huawei = new Phone('华为', 5999); Huawei.call(); console.log(Huawei); //class class Shouji{ //构造方法 名字不能修改 constructor(brand, price){ this.brand = brand; this.price = price; } //方法必须使用该语法, 不能使用 ES5 的对象完整形式 call(){ console.log("我可以打电话!!"); } } let onePlus = new Shouji("1+", 1999); console.log(onePlus); </script>
静态成员
<script> // function Phone(){ // } // Phone.name = '手机'; // Phone.change = function(){ // console.log("我可以改变世界"); // } // Phone.prototype.size = '5.5inch'; // let nokia = new Phone(); // console.log(nokia.name); // // nokia.change(); // console.log(nokia.size); class Phone { //静态属性 static name = '手机'; static change() { console.log("我可以改变世界"); } } let nokia = new Phone(); console.log(nokia.name); // undefined console.log(Phone.name); // 手机 </script>
构造函数继承及对父类方法重写
<script> class Phone { //构造方法 constructor(brand, price) { this.brand = brand; this.price = price; } //父类的成员属性 call() { console.log("我可以打电话!!"); } } class SmartPhone extends Phone { //构造方法 constructor(brand, price, color, size) { super(brand, price); // Phone.call(this, brand, price) this.color = color; this.size = size; } photo() { console.log("拍照"); } playGame() { console.log("玩游戏"); } call() { console.log('我可以进行视频通话'); } } const xiaomi = new SmartPhone('小米', 799, '黑色', '4.7inch'); console.log(xiaomi); xiaomi.call(); xiaomi.photo(); xiaomi.playGame(); </script>
class的set-get
<script> // get 和 set class Phone{ get price(){ console.log("价格属性被读取了"); return 'iloveyou'; } set price(newVal){ console.log('价格属性被修改了'); } } //实例化对象 let s = new Phone(); // console.log(s.price); </script>
数值扩展
1.Number.EPSILON 是 JavaScript 表示的最小精度
2.二进制和八进制:ES6 提供了二进制和八进制数值的新的写法,分别用前缀 0b和 0o表示。
3.Number.isFinite 检测一个数值是否为有限数
4.Number.isNaN 检测一个数值是否为 NaN
5.Number.parseInt Number.parseFloat字符串转整数
6.Number.isInteger 判断一个数是否为整数
7.Math.trunc 将数字的小数部分抹掉
<script> //0. Number.EPSILON 是 JavaScript 表示的最小精度 //EPSILON 属性的值接近于 2.2204460492503130808472633361816E-16 // function equal(a, b){ // if(Math.abs(a-b) < Number.EPSILON){ // return true; // }else{ // return false; // } // } // console.log(0.1 + 0.2 === 0.3); // console.log(equal(0.1 + 0.2, 0.3)) //1. 二进制和八进制 // let b = 0b1010; // let o = 0o777; // let d = 100; // let x = 0xff; // console.log(x); //2. Number.isFinite 检测一个数值是否为有限数 // console.log(Number.isFinite(100)); // console.log(Number.isFinite(100/0)); // console.log(Number.isFinite(Infinity)); //3. Number.isNaN 检测一个数值是否为 NaN // console.log(Number.isNaN(123)); //4. Number.parseInt Number.parseFloat字符串转整数 // console.log(Number.parseInt('5211314love')); // console.log(Number.parseFloat('3.1415926神奇')); //5. Number.isInteger 判断一个数是否为整数 // console.log(Number.isInteger(5)); // console.log(Number.isInteger(2.5)); //6. Math.trunc 将数字的小数部分抹掉 // console.log(Math.trunc(3.5)); //7. Math.sign 判断一个数到底为正数 负数 还是零 console.log(Math.sign(100)); console.log(Math.sign(0)); console.log(Math.sign(-20000)); </script>
对象方法扩展
ES6新增了一些 Object对象的方法
1) Object.is 比较两个值是否严格相等,与『 ===』行为基本一致(+0 与 NaN)
2) Object.assign 对象的合并,将源对象的所有可枚举属性,复制到目标对象
3) __proto__、 setPrototypeOf、 setPrototypeOf可以直接设置对象的原型
<script> //1. Object.is 判断两个值是否完全相等 // console.log(Object.is(120, 120));// === // console.log(Object.is(NaN, NaN));// === // console.log(NaN === NaN);// === //2. Object.assign 对象的合并 // const config1 = { // host: 'localhost', // port: 3306, // name: 'root', // pass: 'root', // test: 'test' // }; // const config2 = { // host: 'http://atguigu.com', // port: 33060, // name: 'atguigu.com', // pass: 'iloveyou', // test2: 'test2' // } // console.log(Object.assign(config1, config2)); //3. Object.setPrototypeOf 设置原型对象 Object.getPrototypeof const school = { name: '少林达摩院' } const cities = { xiaoqu: ['北京','上海','深圳'] } Object.setPrototypeOf(school, cities); console.log(Object.getPrototypeOf(school)); console.log(school); </script>
模块化
模块化是指将一个大的程序文件,拆分成许多小的文件,然后将小文件组合起来。
模块化的优势:
1) 防止命名冲突
2) 代码复用
3) 高维护性
ES6之前的模块化规范有
1) CommonJS => NodeJS、 Browserify
2) AMD => requireJS
3) CMD => seaJS
模块功能主要由两个命令构成:export和 import。
export命令用于规定模块的对外接口
import命令用于输入其他模块提供的功能
m1.js
//分别暴露
export let school = '少林达摩院';
export function teach() {
console.log("我们可以教给你绝世神功");
}
m2.js
//统一暴露
let school = '少林达摩院';
function findJob(){
console.log("我们可以帮助你学会化缘!!");
}
export {school, findJob};
m3.js
//默认暴露
export default {
school: '少林达摩院',
change: function(){
console.log("我们可以改变你!!");
}
}
app.js
//入口文件
//模块引入
import * as m1 from "./m1.js";
import * as m2 from "./m2.js";
import * as m3 from "./m3.js";
// console.log(m1);
// console.log(m2);
// console.log(m3);
// m1.teach();
// m2.findJob();
// m3.default.change();
//修改背景颜色为粉色
import $ from 'jquery';// const $ = require("jquery");
$('body').css('background','pink');
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>ES6 模块化</title> </head> <body> <script type="module"> //1. 通用的导入方式 //引入 m1.js 模块内容 // import * as m1 from "./src/js/m1.js"; // //引入 m2.js 模块内容 // import * as m2 from "./src/js/m2.js"; // //引入 m3.js // import * as m3 from "./src/js/m3.js"; //2. 解构赋值形式 // import {school, teach} from "./src/js/m1.js"; // import {school as guigu, findJob} from "./src/js/m2.js"; // import {default as m3} from "./src/js/m3.js"; //3. 简便形式 针对默认暴露 // import m3 from "./src/js/m3.js"; // console.log(m3); </script> <script src="./src/js/app.js" type="module"></script> </body> </html>

浙公网安备 33010602011771号