1.1 let关键字
1、声明变量
let a; let b,c; let d = 100; let e = 200 ,f = 'love you' , g = [];
2、特性
(1)变量不能重复声明
//报错 let star = '星星'; let star = '小星星';//他可以再次赋值,star = '小星星';是不会报错的 //无影响,不报错,会覆盖掉 var star = '星星'; var star = '小星星';
(2)块级作用域
es5的作用域:全局,函数,eval
es6引入块级作用域
//报错 { let star = '星星'; } console.log(star); //会输出 { var star = '星星'; }
(3)不存在变量提升
//let,会报错 console.log(song); let song = '如一'; //var,输出undefined console.log(song); var song = '如一';
(4)不影响作用域链
{ let star = '星星'; function fn(){ console.log(star); } fn(); }//正常输出‘星星’
1.2 const关键字
1、const定义常量,常量是值不能修改的量
2、声明常量
const STAR = '星星'; console.log(STAR); STAR = '小星星';//报错
3、注意事项
(1)一定要赋初始值,将其初始化
(2)一般常量使用大写
(3)常量的值不能修改
(4)块级作用域
(5)对于数组和对象的元素修改,不算对常量的修改,不会报错
const STAR = ['星星','小星星','大星星','闪']; STAR.push('亮'); console.log(STAR);
1.3 变量的解构赋值
1、介绍:ES6允许按照一定模式从数组和对象中提取值,对变量进行赋值,称为解构赋值
2、数组的解构
const STAR = ['狄仁杰','李俶','陆绎','叶冲']; let [drj,lc,ly,yc] = STAR; console.log(drj);//狄仁杰 console.log(lc);//李俶 console.log(ly);//陆绎 console.log(yc);//叶冲
3、对象的解构
const lc = { name: '李俶', age: 20, ze: function(){ console.log("一代君王"); } }; let {name, age, ze} = lc; console.log(name);//李俶 console.log(age);//20 console.log(ze);//ƒ (){console.log("一代君王");} ze ();//一代君王
1.4 模板字符串
1、ES6引入新的声明字符串的方式:
之前是:'',""
ES6新增:``(反引号,键盘上“·”和“~”的键)
2、声明
let str = `我是字符串`; console.log(str,typeof str);//我是字符串 string
3、特性
(1)内容中可以直接出现换行符("",''不可以会报错)
(2)变量拼接("",''是用+相连)
//内容中可以直接出现换行符 let str = `<ul> <li>快乐</li> <li>开心</li> <li>激动</li> </ul>` //变量拼接 let star1 = '李俶'; let star2 = '陆绎'; let out = `${star1}是一代君王,${star2}是锦衣卫`; console.log(out);//李俶是一代君王,陆绎是锦衣卫
1.5 简化对象写法
ES6允许在大括号里面,直接写入变量和函数,作为对象的属性和方法
let name = '回忆录'; let memory = function() { console.log('回忆往事'); } const change = { name, memory, miss(){ console.log('回忆年少点滴'); } } console.log(change);//{name: '回忆录', memory: ƒ, miss: ƒ}
1.6 箭头函数
(1)声明特点:
①this是静态的,this始终指向函数声明时所在作用域下的this的值
②不能作为构造函数实例化对象
③不能使用arguments变量
④箭头函数简写
-
当形参有且只有一个时,省略小括号
-
当代码体只有一条语句的时候,省略花括号,此时return必须省略
//声明函数 let fn = (a,b) => { return a+b; } //调用函数 fn(1,2);
(2)应用场景
-
箭头函数适合与this无关的回调,定时器,数组的方法回调
-
箭头函数不适合与this有关的回调,事件回调,对象的方法
1.7 函数参数的默认值设置
ES6允许给函数参数赋值初始值
1、形参初始值
如果赋值就用赋的值,若是没有赋值,就用形参默认值,一般默认值位置偏后
2、与解构赋值结合
function connect({host='127.0.0.1',username,password,port}){ console.log(host); //localhost console.log(username); //root console.log(password); //root console.log(port); //3306 } connect({ host: 'localhost', username: 'root', password: 'root', port: 3306 })
1.8 rest参数
ES6引入rest参数,用于获取函数的实参,用于代替arguments
-
rest参数前面有三个.(...)
-
rest参数必须要放到参数最后
//ES5(结果是对象) function date(){ console.log(arguments); } date('张无忌','赵敏','周芷若'); //ES6(结果是数组) function date(...args){ console.log(args); } date('张无忌','赵敏','周芷若');
1.9 扩展运算符
1、扩展运算法院符号(...),扩展运算符能将数组转换为逗号分隔的参数序列
const tfboys = ['易烊千玺','王俊凯','王源']; function wutai(){ console.log(arguments); } wutai(...tfboys);//'易烊千玺', '王俊凯', '王源'
2、应用
//数组的合并 const jyzx = ['陆绎','袁今夏']; const dtrr = ['李俶','沈珍珠']; // const rjl = jyzx.concat(dtrr); const rjl = [...jyzx,...dtrr]; console.log(rjl);//['陆绎', '袁今夏', '李俶', '沈珍珠'] //数组的克隆(浅拷贝) const jyzx = ['陆绎','袁今夏']; const rjl = [...jyzx]; console.log(rjl);//['陆绎', '袁今夏'] //将伪数组转为真正的数组 const divs = document.querySelectorAll("div"); const divArr = [...divs]; console.log(divArr);//[div, div, div]
1.10 Symbol
1、Symbol基本使用
(1)概念
Symbol是一种原始的数据类型,标识独一无二的值,是一种类似于字符串的数据类型
(2)特点
-
Symbol的值是唯一的,用来解决命名冲突的问题
-
Symbol值不能与其他数据进行运算
-
Symbol定义的对象属性不能使用for...in循环遍历,但是可以使用Reflect.ownKeys来获取对象的所有键名
//创建Symbol let s1 = Symbol(); let s2 = Symbol('你很漂亮'); let s3 = Symbol('你很漂亮'); let s4 = Symbol.for('你很漂亮'); let s5 = Symbol.for('你很漂亮'); console.log(s2 === s3);//false,里面的值起到了提示作用,我是一个标志,不是值 console.log(s4 === s5);//true,里面是值 console.log(s1,typeof s1);//Symbol() 'symbol' console.log(s4,typeof s4);//Symbol(你很漂亮) 'symbol'
(3)数据类型(usonb)
u:undefined
s:string,symbol
o:object
n:null,number
b:boolean
(4)Symbol的使用:向对象中添加方法(与up,down相关)
//方法1 let game = { name:'江南百景图', up:function(){ console.log('我要上升'); }, down:function(){ console.log('我要下降'); } }; let methods = { up:Symbol(), down:Symbol() }; game[methods.up] = function(){ console.log("我要飞的更高"); }; game[methods.down] = function(){ console.log("我要降落"); }; console.log(game);//{name: '江南百景图', up: ƒ, down: ƒ, Symbol(): ƒ, Symbol(): ƒ} //方法2 let game = { name:'江南百景图', [Symbol('up')]:function(){ console.log('我要上升'); }, [Symbol('down')]:function(){ console.log('我要下降'); } }; console.log(game);//{name: '江南百景图', Symbol(up): ƒ, Symbol(down): ƒ}
2、 Symbol内置值
内置值 | 说明 |
---|---|
Symbol.hasInstance | 当其他对象使用instanceof运算符,判断是否为该对象的实例时,会调用这个方法 |
Symbol.isConcatSpreadable | 对象的Symbol.isConcatSpreadable属性等于的是一个布尔值,表示该对象属于Array.prototype.concat()时,是否可以展开 |
Symbol.unscopables | 该对象指定了使用with关键字时,哪些属性会被with环境排除 |
Symbol.match | 当执行str.match(myObject)时,如果该属性存在,会调用他,返回该方法的返回值 |
Symbol.replace | 当该对象被str.replace(myObject)方法调用时,会返回该方法的返回值 |
Symbol.search | 当该对象被str.search(myObject)方法调用时,会返回该方法的返回值 |
Symbol.split | 当该对象被str.split(myObject)方法调用时,会返回该方法的返回值 |
Symbol.iterator | 对象进行for...of循环时,会调用Symbol.iterator方法,返回该对象的默认遍历器 |
Symbol.toPrimitive | 该对象被转为原始类型的值时,会调用这个方法,返回该对象对应的原始类型值 |
Symbol.toStringTag | 在该对象上面调用toString方法时,返回该方法的返回值 |
Symbol.species | 创建衍生对象时,会使用该属性 |
1.11 迭代器
1、ES6创造了一种新的遍历命令for...of循环,Iterator接口主要供for...of消费
2、原生具备iterator接口的数据:Array、Arguments、Set、Map、String、TypedArray、NodeList
3、for..of和for..in区别
for..of返回的是数组中的值,for..in返回的是数组中的索引号
//for..of和for..in var xiyou = ['唐僧','孙悟空','猪八戒','沙僧']; for(let i of xiyou){ console.log(i);//唐僧 孙悟空 猪八戒 沙僧 } for(let i in xiyou){ console.log(i);//0 1 2 3 }
4、利用迭代器的例子
const xy = { name: "西游记", stus:[ '唐僧', '孙悟空', '猪八戒', '沙僧' ], [Symbol.iterator](){ let _this = this; let index = 0; return { next: function(){ if(index<_this.stus.length){ const result = {value:_this.stus[index],done:false}; index++; return result; } else{ return {value:undefined,done:true} } } }; } } //遍历对象 for(let i of xy){ console.log(i); }//唐僧 孙悟空 猪八戒 沙僧
1.12 生成器
1、生成器函数声明与调用
(1)生成器是一个特殊的函数,用于异步编程
(2)yield是函数代码的分隔符,将代码分成几部分,有n个yield就有n+1个部分
function * gen(){ //特殊1:有*号 console.log("你好1"); yield '12345'; //特殊2:可以用yield console.log("你好2"); yield '上山打老虎'; console.log("你好3"); yield '老虎没打着'; console.log("你好4"); } let iterator = gen(); iterator.next();//你好1 //特殊3:使用迭代器的next输出 iterator.next();//你好2 iterator.next();//你好3 iterator.next();//你好4
2、生成器函数的参数传递
function * gen(arg){ console.log(arg);//当第一个next出现有返回值,您好 let one = yield '12345'; console.log(one);//当第二个next出现有返回值,222 let two = yield '上山打老虎'; console.log(two);//当第三个next出现有返回值,333 let three = yield '老虎没打着'; console.log(three);//当第四个next出现有返回值,444 } //执行获取迭代器对象 let iterator = gen('您好'); //next方法可以传入实参 console.log(iterator.next());//{value: '12345', done: false} console.log(iterator.next('222'));//{value: '上山打老虎', done: false} console.log(iterator.next('333'));//{value: '老虎没打着', done: false} console.log(iterator.next('444'));//{value: undefined, done: true}
1.13 Promise
1、介绍
Promise是ES6引入的异步编程的新解决方案,语法上Promise是一个构造函数,用来封装异步操作并可以获取其他成功或者失败的结果。
-
Promise构造函数:Promise(excutor){}
-
Promise.prototype.then方法
-
Promise.prototype.catch方法
const p = new Promise(function(resolve,reject){ //resolve成功,reject失败 setTimeout(function(){ // let data = '数据库的数据'; let err = '数据读取失败'; // resolve(data); reject(err); },1000); }); p.then(function(value) { //成功用value console.log(value); },function(reason){ //失败用reason console.error(reason); })
2、实例——Promise封装读取文件
//引入fs模块 const fs = require('fs'); //使用promise封装 const p = new Promise(function(resolve,reject){ fs.readFile('./resource/cc.md',(err,data) =>{ if(err) reject(err); resolve(data); }); }); p.then(function(value){ console.log(value.toString()); },function(reason){ console.log("读取失败"); })
3、实例——Promise封装AJAX请求
const p = new Promise((resolve,reject) => { //创建对象 const xhr = new XMLHttpRequest(); //初始化 xhr.open("GET",' https://api.apiopen.top/getJoke'); //发送 xhr.send(); //绑定事件,处理响应结果 xhr.onreadystatechange = function(){ if(xhr.readyState === 4){ //判断响应状态码 200-299 if(xhr.status >= 200 &&xhr.status < 300){ //成功 resolve(xhr.response); }else{ //失败 reject(xhr.status); } } } }); p.then(function(value){ console.log(value); },function(reason){ console.error(reason); });
4、Promise.prototype.then方法
-
then方法的返回结果是Promise对象,对象状态由回调函数的执行结果决定
-
如果回调函数返回的结果是非promise类型的属性,状态为成功,返回值为对象的成功值;若是promise类型的属性,状态看结果而定返回值是对象的值;若是抛出错误(throw)则状态时reject,结果是throw抛出的结果
-
then中第一个函数为成功函数,第二个函数为失败函数
-
链式调用
p.then(value => {},reason => {}).then(value => {},reason => {})
5、Promise.prototype.catch方法
-
用来指定Promise对象失败的回调
-
只有一个回调函数,为失败回调函数
const p = new Promise((resolve,reject) => { setTimeout(() => { //设置失败,并设置值 reject("出错了"); },1000) }); //方法1 /* p.then(function(value){},function(reason){ console.error(reason); }) */ //方法2 p.catch(function(reason){ console.warn(reason); });
1.14 Set
1、介绍
-
ES6提供了新的数据结构Set(集合),类似于数组,但是成员的值是唯一的,集合实现了iterator接口,所以可以使用“扩展运算符”和“for/of”进行遍历
-
会将元素去重
2、属性和方法
属性方法 | 说明 |
---|---|
s.size | 返回集合的元素个数 |
s.add() | 增加一个新元素,返回当前集合 |
s.delete() | 删除元素,返回boolean值 |
s.has() | 检测集合中是否包含某个元素,返回boolean值 |
s.clear() | 清空集合 |
3、代码实现
//声明set let s1 = new Set(); let s2 = new Set(['大大','小小','多多','少少']); console.log(s1,typeof s1);//Set(0) {size: 0} 'object' console.log(s2);//Set(4) {'大大', '小小', '多多', '少少'} //元素个数 console.log(s2.size);//4 //添加元素 s2.add('快快'); console.log(s2);//Set(5) {'大大', '小小', '多多', '少少', '快快'} console.log(s2.add('快快'));//Set(5) {'大大', '小小', '多多', '少少', '快快'} //删除元素 s2.delete('小小'); console.log(s2);//Set(4) {'大大', '多多', '少少', '快快'} console.log(s2.delete('小小'));//true //检测 console.log(s2.has('大大'));//true //清空 s2.clear(); console.log(s2);//Set(0) {size: 0}
4、集合常见操作
let arr = [1,2,3,4,5,4,3,2,1]; let arr2 = [4,5,6,5,6]; //数组去重 let result = [...new Set(arr)]; console.log(result);//[1, 2, 3, 4, 5] //交集 //方法1 let result = [...new Set(arr)].filter(item => { let s2 = new Set(arr2); if(s2.has(item)){ return true; } else{ return false; } }); console.log(result);//[4, 5] //方法2 let result = [...new Set(arr)].filter(item => new Set(arr2).has(item)); console.log(result);//[4, 5] //并集 let union = [...new Set([...arr,...arr2])]; console.log(union); //差集 let diff = [...new Set(arr)].filter(item => !(new Set(arr2).has(item))); console.log(diff);// [1, 2, 3]
1.15 Map
1、介绍
ES6提供了Map数据结构,类似于对象,也是键值对的集合。但是键的范围不限于字符串,各种类型的值(包括对象)都可以当做键。Map实现了iterator接口,所以可以使用“扩展运算符”和“for/of”进行遍历。
2、属性和方法
属性方法 | 说明 |
---|---|
m.size | 返回Map的元素个数 |
m.set() | 增加一个新元素,返回当前Map |
m.get() | 返回键名对象的键值 |
m.has() | 检测Map中是否包含某个元素,返回boolean值 |
m.clear() | 清空集合,返回undefined |
3、代码实现
//声明map let m = new Map(); //添加元素 m.set('name','happy'); m.set('change',function(){ console.log('我们要快乐'); }); let key = { xy: 'kuanle' }; m.set(key,['早上','中午','晚上']); console.log(m); //元素个数 console.log(m.size);//3 //删除 m.delete('name'); console.log(m); //获取 console.log(m.get(key)); //清空 m.clear(); console.log(m); //遍历 for(let i of m){ console.log(i);//结果是数组 }
1.16 class类
1、class介绍(与ES5对比)
//ES5 function Phone(brand, price){ this.brand = brand; this.price = price; } //添加方法 Phone.prototype.call = function(){ console.log("我是用来打电话的"); } //实例化对象 let Xiaomi = new Phone('小米',2000); Xiaomi.call();//我是用来打电话的 console.log(Xiaomi);//Phone {brand: '小米', price: 2000} //ES6 class Phone{ //构造方法 名字不能修改 constructor(brand,price){ this.brand = brand; this.price = price; } //方式使用该语法 call(){ console.log("我是用来打电话的"); } } let Xiaomi = new Phone('小米',2000); Xiaomi.call();//我是用来打电话的 console.log(Xiaomi);//Phone {brand: '小米', price: 2000}
2、class静态成员
静态属性属于类不属于实例对象
class Phone{ //静态属性,属于类不属于实例对象 static name = '手机'; static call(){ console.log("我可以打电话"); } } let mi = new Phone(); console.log(mi.name);//undefined console.log(Phone.name);//手机
3、class的类继承
注意:子类不能调用父类的同名方法,可以进行重写,在子类中直接进行写方法即可。
//ES5构造函数继承 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.playGame = function(){ console.log("我可以玩游戏"); } //实例化对象 let chuizi = new SmartPhone('锤子',2000,'白色','5.5inch'); console.log(chuizi);
//class类继承 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("我可以拍照"); } playGame(){ console.log("我可以玩游戏"); } } const mi = new SmartPhone('小米',2500,'黑色','4.7inch'); console.log(mi);
4、class中get和set设置
-
get通常对动态属性进行封装,set可以添加较多的控制和判断,并且set必须有参数
-
get是获得一个值,set是设置一个值
class Phone{ get price() { console.log("价格属性被读取了"); return '好便宜'; } set price(newVal) {//set必须有一个参数 console.log("价格属性被修改"); } } //实例化对象 let s = new Phone(); console.log(s.price);//价格属性被读取了 好便宜 s.price = 'free';//价格属性被修改
1.17 数据扩展
1、Number.EPSILON是JavaScript表示的最小精度,EPSILON属性的值接近于2.220446049250313e-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);//false console.log(equal(0.1 + 0.2, 0.3));//true
2、二进制和八进制(二进制:0b;八进制:0o;十六进制:0x)
3、Number.isFinite():检测一个数值是否为有限数
4、Number.isNaN():检测一个数值是否为NaN
5、Number.parseInt():字符串转化为整数
Number.parseFloat():字符串转化为浮点数
6、Number.isInteger():判断一个数是否为整数
7、Math.trunc():将数字的小数部分抹掉
8、Math.sign():判断一个数到底是正数、负数还是0(正数返回1,负数返回-1,0返回0)
1.18 对象扩展
1、Object.is():判断两个值是否完全相等
2、Object.assign():对象的合并
3、Object.setPrototypeOf():设置原型对象
Object.getPrototypeOf():获取对象
1.19 模块化
1、概念
模块化是指将一个大的程序文件,拆分成许多小的文件,然后将小的文件组合起来。
2、模块化的好处
(1)防止命名冲突
(2)代码复用
(3)高维护性
3、模块化语法
模块功能主要由两个命令构成:export和import
export命令:用于规定模块的对外接口
import命令:用于输入其他模块提供的功能
4、ES6模块化暴露数据语法汇总
(1)分别暴露
(2)统一暴露
(3)默认暴露
//js(m1) /* 分别暴露 */ export let school = 'cc'; export function teach(){ console.log("我们可以交给你知识"); } //js(m2) /* 统一暴露 */ let school = 'cc'; function teach(){ console.log("我们可以交给你知识"); } export{school,teach}; //js(m3) /* 默认暴露 */ export default { school: 'CC', change: function(){ console.log("改变自己"); } } //html <script type="module"> //引入js(m1)模块 import * as m1 from "./js/m1.js"; console.log(m1); //引入js(m2)模块 import * as m2 from "./js/m2.js"; console.log(m2); //引入js(m3)模块 import * as m3 from "./js/m3.js"; console.log(m3); </script>
5、ES6引入模块数据语法汇总
(1)通用的导入方式
(2)解构赋值形式
(3)简便形式:针对默认暴露,直接写变量
//通用的导入方式 import * as m1 from "./js/m1.js"; //解构赋值形式 //分别暴露 import {school,teach} from "./js/m1.js"; //统一暴露 import {school as school1,teach as teach1} from "./js/m2.js";//使用别名 //默认暴露 import {default as m3} from "./js/m3.js";//default必须起别名 //简便形式 import m3 from "./js/m3.js";//直接写变量
6、浏览器使用ES6模块化方式
(1)方式1
<script type="module">代码写在这里</script>
(2)方式2
创建一个js文件,这是js代码的入口文件,写入模块引入,在html中写入以下代码
<script src="./js/模块引入文件.js" type="module"></script>
7、ES6-babel对ES6模块化代码转换
步骤:
-
安装工具:babel-cli、babel-preset-env、browserify(webpack)
-
npx babel day3/js -d day3/dist/js --presets=babel-preset-env
-
打包:npx browserify day3/dist/js/模块引入文件.js -o day3/dist/bundle.js
-
在html中引入:<script src="./dist/bundle.js"></script>
8、ES6模块化引入NPM包
import 变量名 from '模块名字'
//修改背景颜色为粉色 import $ from 'jquery';//const $ = require("jquery") $('body').css('background','pink');