一、ES6中新增的let与var的区别: 1.用let声明变量的时候不可以重复声明,但是var可以。 1 2 3 4 5 let a=0 ;let a=1 ; var b=0 ;var b=1 ;
2.新增了块级作用域,可以只在代码块中起作用,外部访问不到。其他的还有全局作用域、函数作用域、eval与var保持一致。 1 2 3 4 { let a=6 ; } console .log (a);
3.let不存在变量提升的特性,这点与var不同。 4.不影响作用域链。 二、Const常量 1.定义常量的时候一定要赋初始值 2.常量的变量名一般都要大写(习惯) 3.常量,顾名思义,它的值是不可更改的 4.与新增的let一样,也是块级作用域 5.如果定义数组或者对象为常量,对其元素进行修改则不会报错 原因:因为修改其中的元素并不会导致该数组或对象的地址发生改变,所以不会报错。
1 2 3 4 5 const TEAM = [1 ,2 ,3 ];TEAM .push (4 ); TEAM = 1 ;
三、数组和对象的解构赋值 ES6允许按照一定模式从数组和对象中提取值,对变量进行赋值,就称为解构赋值。
1.数组的解构赋值 按照顺序进行一一对应进行赋值。
1 2 3 4 5 6 const F4 = ['小杰' ,'小民' ,'小蔡' ,'小红' ];let [li,wang,cai,yu] = F4 ;console .log (li); console .log (wang); console .log (cai); console .log (yu);
2.对象的解构赋值 按照属性名进行赋值。
1 2 3 4 5 6 7 8 9 10 11 12 13 const LI = { name :'小杰' , age : 22 , apex : function ( ){ console .log ('我是APEX猎杀' ); } }; let {name, age, apex} = LI ;console .log (name); console .log (age); console .log (apex); apex ();
四、新增的字符串字面量:`` 1.新的字符串声明方式 1 2 let str1 = `我是新增的字符串字面量` ;console .log (str1, typeof str1);
2.内容中可以出现换行符,其他的不支持 1 2 3 4 5 6 let str2=`<ul> <li>小红</li> <li>小杰</li> <li>小蔡</li> <li>小民</li> </ul>` ;
3.变量拼接 在ES6之前的字符串拼接方法 1 2 3 var he = 'hello' ;var name = he + '小蔡' ;console .log (name);
ES6新增拼接方法 1 2 3 let gun1 = `R301` ;let gun2 = `${gun1} R99` ;console .log (gun2);
五、简化对象写法 1.ES6之前的写法 1 2 3 4 5 6 7 8 let name = '小红' ;let fn = function ( ){ console .log (123 ); } const SCHOOL = { name : name, fn : fn }
2.ES6的简化写法 1 2 3 4 5 6 7 8 9 let name = '小红' ;let fn = function ( ){ console .log (123 ); } const SCHOOL = { name, fn }
六、箭头函数 1.ES6允许使用箭头(=>)来定义函数 1 2 3 let fn = ( ) => { console .log (123 ) }
2.箭头函数中的this是静态的,始终指向函数声明时所在作用域下的this的值 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 function x1 ( ){ console .log (this .name ); } let x2 = ( ) => { console .log (this .name ); } window .name = 'window' ;const OBJ = { name : 'this' } x1 (); x2 (); x1.call (OBJ ); x2.call (OBJ );
3.箭头函数不能作为构造函数实例化对象 1 2 3 4 5 6 let Person = (name, age ) => { this .name = name, this .age = age } let me =new Pesron ('xiaohong' ,22 );console .log (me);
4.不能使用arguments变量 1 2 3 4 let fn = ( ) => { console .log (arguments ); } fn (1 ,2 ,3 )
5.箭头函数可以缩写 (1).省略小括号,当形参有且只有一个的时候 1 2 3 4 let add = n => { return n+ n; } console .log (add (9 ));
(2).省略花括号,代码里只有一条语句的时候,return也必须省略 1 2 let pow = (n ) => n*n;console .log (pow (8 ));
6.箭头函数的一些应用场景 (1).点击id为ad的块,让其2s后变为粉色 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 let ad = document .getElementById (ad);ad.addEventListener ('click' , function ( ){ let that = this ; setTimeout (function ( ){ that.style .background = 'pink' }, 2000 ); }) ad.addEventListener ('click' , function ( ){ setTimeout (() => { this .style .background = 'pink' }, 2000 ); })
(2).从数组中返回偶数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 const ARR = [1 ,2 ,3 ,4 ];const RESULT = ARR .filter (function (item ){ if (item % 2 === 0 ){ return true ; } else { return false ; } }); console .log (RESULT ); const RESULT = ARR .filter (item => { if (item % 2 === 0 ){ return true ; } else { return false ; } }) const RESULT = ARR .filter (item => item % 2 === 0 );console .log (RESULT );
箭头函数适合与this无关的回调,定时器,数组的方法回调 不适合与this有关的回调,事件回调,对象的方法
七、ES6允许给函数参数赋初始值 1.给形参赋初始值 1 2 3 4 5 function add (a,b,c=10 ){ return a+b+c; } let result = add (1 ,2 );console .log (result);
2.可以与解构赋值结合使用 1 2 3 4 5 6 7 8 9 10 11 function connect ({host="127.0.0.1" , username, password, port} ){ console .log (host); console .log (username); console .log (password); console .log (port); } connect ({ username : 'root' , password : 'root' , port : 3306 })
八、rest参数(用来替代无法在箭头函数中使用的arguments参数) 两者区别 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 function data ( ){ console .log (arguments ); } data (1 ,2 ,3 ); function data2 (...args ){ console .log (args); } data2 (3 ,4 ,5 );function fn (a,b,...arg ){ console .log (a); console .log (b); console .log (arg); } fn (1 ,2 ,3 ,4 ,5 );
九、扩展运算符…(能将数组转化为逗号分割开的参数序列) 1.数组的拼接 1 2 3 4 const APEX = ['狗子' ,'G7人' ,'命脉' ];const LOL = ['亚索' ,'劫' ];const HB = [...APEX , ...LOL ];console .log (HB );
2.数组的克隆 1 2 3 4 const A = [666 ,777 ];const CA = [...A];console .log (CA );
3.将伪数组转换为真正的数组 1 2 3 <div > </div > <div > </div > <div > </div >
1 2 3 const DIVS = document .querySelectorAll ('div' );const DIVARR = [...DIVS ];console .log (DIVARR );
十、ES6引入了一种新的原始数据类型Symbol,表示独一无二的值,是JS中第七种数据类型 1.Symbol的特点 (1).Symbol的值是唯一的,用来解决命名冲突问题 (2).Symbol的值不能与其他数据进行运算 (3).Symbol给对象定义的属性不能使用for in进行遍历
2.创建Symbol 1 2 3 4 5 6 7 8 9 10 11 12 13 let s = Symbol ();console .log (s, typeof s); let s2 = Symbol ('小红' );let s3 = Symbol ('小红' );console .log (s2, typeof s2); console .log (s2 === s3); let s4 = Symbol .for ('小红' );let s5 = Symbol .for ('小红' );console .log (s4 === s5); console .log (s4, typeof s4);
3.使用场景 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 let game = { up : 213 } let methods = { up : Symbol (), down : Symbol () }; game[methods.up ] = function ( ){ console .log ('我可以改变形状' ); } game[methods.down ] = function ( ){ console .log ('我可以快速下降' ); } console .log (game);let youxi = { name : 'bf' , [Symbol ('say' )]: function ( ){ console .log ('我可以说话' ); }, [Symbol ('sing' )]: function ( ){ console .log ('我可以唱歌' ); } } console .log (youxi);
4.Symbol的内置值(可以当作属性使用) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 class Person { static [Symbol .hasInstance ] (){ console .log ('我被用来检测类型了' ); return true ; } } let o = {};console .log (o instanceof Person );const ARR = [1 ,2 ,3 ];const ARR2 = [4 ,5 ,6 ];ARR2 [Symbol .isConcatSpreadable ] = false ; console .log (ARR .concat (ARR2 ));
十一、迭代器(Iterator) 1.什么是迭代器 (1)迭代器是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署了Iterator接口(其实就是一个对象的属性),就可以完成遍历操作。 (2)ES6创造了一种新的遍历命令for…of循环,Iterator接口主要供for…of使用。 (3)原生具备Iterator接口的数据: Array, Arguments, Set, Map, String, TypedArray, NodeList
2.for of 和 for in 1 2 3 4 5 6 7 8 9 const AR = ['M4' ,'AK' ,'MP7' ];for (let v of AR ){ console .log (v); } for (let w in AR ){ console .log (w); }
所以由此可知,使用for in的时候,w中保存的是下标,使用for of中,v保存的是值 迭代器的原理: 1.先创建一个指针对象,指向当前数据结构的起始位置。 2.第一次调用对象的next方法,指针自动指向数据结构的第一个成员。 3.接下来不断调用next方法,指针一直往后移动,直到指向最后一个成员。 4.每调用next方法返回一个包含value和done属性的对象。 5.value就是值,done表示是否遍历完成,若为ture则表示已经全部遍历完了。
3.迭代器的应用:自定义迭代器 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 const CLASS = { name : '15' , stus : [1 ,2 ,3 ,4 ], [Symbol .iterator ](){ let index = 0 ; let that = this ; return { next : function ( ){ if (index < that.stus .length ){ const result = {value :that.stus [index],done :false } index++; return result; } else { return {value :undefined , done :true } } } } } } for (let x of CLASS ){ console .log (x); }
十二、生成器 生成器本身是一个函数,是ES6提供的一种异步编程解决方案
1.定义函数,在function和函数名之间加一个* 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 function * gen ( ){console .log (111 );yield '666' ;console .log (222 );yield 'lll' ;console .log (333 );yield 'hhhh' console .log (444 );} let iterator = gen ();iterator.next (); iterator.next (); iterator.next (); iterator.next (); for (let v of gen ()){ console .log (v); } function * x (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 iterator1 = x ('AAA' );console .log (iterator1.next ()); console .log (iterator1.next ('BBB' )); console .log (iterator1.next ('CCC' )); console .log (iterator1.next ('DDD' ));
2.生成器的函数实例:1s后控制台输出111,2s后输出222,3s后输出333 (1).使用回调函数,会造成回调地狱的现象 什么是回调地狱? 回调地狱会造成代码可复用性不强,可阅读性差,可维护性(迭代性差),扩展性差等等问题。
1 2 3 4 5 6 7 8 9 let timer = setTimeout (() => { console .log (111 ); setTimeout (() => { console .log (222 ); setTimeout (() => { console .log (333 ); }, 3000 ) }, 2000 ); }, 1000 );
(2).使用生成器,解决异步编程问题 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 function one ( ){ setTimeout (() => { console .log (111 ); iterator.next (); },1000 ); } function two ( ){ setTimeout (() => { console .log (222 ); iterator.next (); },2000 ); } function three ( ){ setTimeout (() => { console .log (333 ); iterator.next (); },3000 ); } function * gen ( ){ yield one (); yield two (); yield three (); } let iterator = gen ();iterator.next ();
十三、Promise 1.功能 (1)Promise是ES6引入的异步编程的新解决方案。 (2)语法上Promise是一个构造函数。 (3)用来封装异步操作并可以获取其成功或失败的结果。
2.声明一个Promise函数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 const p = new Promise (function (resolve, reject ){ setTimeout (function ( ){ let data = '数据库中用户的数据' ; let err = '数据读取失败' ; reject (err); }, 1000 ) }) p.then (function (value ){ console .log (value); }, function (reason ){ console .log (err); })
3.Promise.then 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 const p = new Promise ((resolve, reject )=> { setTimeout (()=> { resolve ('用户数据' ); }, 1000 ); }) const result = p.then (value => { console .log (value); return new Promise ((resolve, reject )=> { throw new Error ('出错啦' ); }) }, reason => { console .warn (reason); }) console .log (result);p.then (value => {}, reason => {}).then (value => {}, reason => {});
十四、集合与API 1.简介 (1)ES6提供了一种新的数据结构SET(集合)。类似于数组,但成员的值都是唯一的。 (2)集合实现了Iterator接口,所以可以使用扩展运算符和for of进行遍历。 (3)集合的属性和方法: size 返回集合的元素个数 add 增加一个新元素,返回当前集合 delete 删除特定元素,返回boolean值 has 检测集合中是否包含某个元素,返回boolean值
2.声明集合 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 let s = new Set ();let s2 = new Set ([1 ,2 ,3 ,4 ,5 ,3 ,2 ]);console .log (s2); console .log (s2.size ); s2.add (9 ); console .log (s2); console .log (s2.delete (9 )); console .log (s2); console .log (s2.has (1 )); console .log (s2.ha2 (10 )); console .log (s2); for (let v of s2){ console .log (v); }
3.集合实践 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 let arr = [1 ,2 ,3 ,5 ,6 ,8 ,8 ,4 ,5 ,1 ,2 ];let result = [...new Set (arr)];console .log (result); let arr2 = [4 ,5 ,6 ,6 ];let result = [...new Set (arr2)].filter (item => new Set (arr2).has (item));console .log (result); let union = [...new Set ([...arr, ...arr2])];console .log (union); let diff = [...new Set (arr)].filter (item => !(new Set (arr2).has (item)));console .log (diff);
十五、Map 1.Map简介 (1)ES6提供了Map数据结构。它类似于对象,也是键值对的集合。但是“键”的范围不限于字符串,各种类型的值都可以当作键。 (2)Map也实现了iterator接口,所以可以使用扩展运算符和for of。 (3)属性和方法: size 返回Map元素的个数 set 增加一个新元素,返回当前Map get 返回键名对象的键值 has 检测Map中是否包含某个元素,返回boolean值 clear 清空集合,返回undefined
2.声明一个Map 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 let m = new Map ();m.set ('name' ,'小红' ); let key = { school : 'GEO' } m.set (key, [1 ,2 ,3 ]); console .log (m); console .log (m.size ); m.delete ('name' ); console .log (m);console .log (m.get (key)); for (let v of m){ console .log (v); }
十六、Class 1.简介 (1)ES6提供了更接近传统语言的写法,引入了Class(类)这个概念。 (2)作为对象的模板,通过Class关键字,可以定义为类。 (3)它的绝大部分功能ES5都可以做到,新的写法只是让原型写法更加清晰。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 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 );
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class Phone { constrctor (brand, price ){ this .brand = brand; this .price = price; } call ( ){ console .log ('我可以打电话' ); } } let OnePlus = new Phone ('1+' , 1999 );console .log (OnePlus );
2.Class的静态成员 (1).ES5中 1 2 3 4 5 6 7 8 9 10 11 12 function ( ){} Phone .name = '手机' ;Phone .change = function ( ){ console .log ('666' ); } Phone .prototype .size = '6' ;let nokia = new Phone ();console .log (nokia.name ); console .log (nokia.size );
(2).Class的静态对象 1 2 3 4 5 6 7 8 9 10 Class Phone (){ static name = '手机' ; static change ( ){ console .log ('666' ); } } let nokia = new Phone ();console .log (nokia.name ); console .log (Phone .name );
十七、构造函数继承 1.ES5使用构造函数继承 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 function Phone (brand, price ){ this .brand = brand; this .price = price; } Phone .prototype .call = function ( ){ console .log ('我可以打电话' ); } function SmartPhone (brand, price, color, size ){ Phone .call (this , brand, price); this .color = color; this .size = size; } SmartPhone .prototype = new Phone ;SmartPhone .prototype .constructor = SmartPhone ;SmartPhone .prototype .photo = function ( ){ console .log ('我可以拍照' ); } SmartPhone .prototype .play = function ( ){ console .log ('我可以玩游戏' ); } const chuizi = new SmartPhone ('锤子' , 2499 , '黑色' , 5.5 )console .log (chuizi);
2.ES6使用类进行继承 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 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); this .color = color; this .size = size; } photo ( ){ console .log ('我可以拍照' ); } play ( ){ console .log ('我可以玩游戏' ); } call ( ){ console .log ('我可以进行视频通话' ); } } const xiaomi = new SmartPhone ('小米' , 799 , '黑色' , 8 );console .log (xiaomi);xiaomi.call ();
十八、Class中的get和set 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class Phone { get price (){ console .log ('价格属性被读取了' ); return '666' ; } set price (newVal ){ console .log ('价格属性被修改了' ); } } let s = new Phone ();console .log (s.price ); s.price = 'free' ;
十九、数值扩展 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 console .log (0.1 + 0.2 === 0.3 ); function equal (a,b ){ if (Math .abs (a-b) < Number .EPSILON ){ return true ; } else { return false ; } } console .log (equal (0.1 +0.2 ,0.3 )); let b =0b1010 ;console .log (b); let o =0o777 ;console .log (o); let x = 0xff ;console .log (x); console .log (Number .isFinite (100 )); console .log (Number .isFinite (100 /0 )); console .log (Number .isNaN (123 )); console .log (Number .parseInt ('531dawd' )); console .log (Number .parseFloat ('3.152135asd' )); console .log (Number .isInteger (5 )); console .log (Number .isInteger (2.5 )); console .log (Math .trunc (3.5 )); console .log (Math .sign (100 )); console .log (Math .sign (-10 )); console .log (Math .sign (0 )); console .log (Math .sign (-0 ));
二十、ES6对象方法扩展 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 console .log (Object .is (120 , 121 )); console .log (Object .is (NaN , NaN )); console .log (NaN === NaN ); const config1 = { host : 'localhost' , port : 3306 , name : 'root' , pass : 'root' , test : 'test' } const config2 = { host : 'http://atguigu.com' , port : 33060 , name : 'atguigu.com' , pass : '666' } console .log (Object .assign (config1, config2));const school = { name : '尚硅谷' } const cities = { xiaoqu : ['北京' ,'上海' ,'深圳' ] } Object .setPrototypeOf (school,cities);console .log (school);
二十一、模块化 1.模块化是将一个很大的程序文件,拆分成许多小的文件(即模块),然后再将小文件组合起来 (1).模块化的好处 Ⅰ.防止命名冲突 Ⅱ.提高代码复用性 Ⅲ.高维护性
(2).ES6模块化语法 Ⅰ.模块功能主要由两个命令组成:export和import Ⅱ.export命令用于规定模块的对外接口 Ⅲ.import命令用于输入其他模块提供的功能
2.模块使用方式 外部模块文件m1.js
1 2 3 4 5 export let school = '尚硅谷' ;export function teach ( ){ console .log ('我们可以教给你开发技能' ); }
外部模块文件m2.js
1 2 3 4 5 6 7 let school = '小红' ;function findjob ( ){ console .log ('我们可以帮你找工作' ); } export {school, findjob};
外部模块文件m3.js
1 2 3 4 5 6 7 export default { name : '晓杰' , change : function ( ){ console .log ('我们可以' ); } }
调用模块的主程序文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 import * as m1 from "./m1.js" ;console .log (m1);m1.teach (); import * as m2 from "./m2.js" ;console .log (m2);console .log (m2.school );import * as m3 from "./m3.js" ;console .log (m3);console .log (m3.default .name );2. 解构赋值形式导入import {school, teach} from "./m1.js" ;import {school as SC , findjob} from "./m2.js" ;import {default as m3} from "./m3.js" ;console .log (school);console .log (SC );console .log (teach);console .log (m3);3. 简便形式 针对默认暴露import m3 from "./m3.js" ;console .log (m3);