let关键字
变量不能重复声明
块级作用域
不存在变量提升
不影响作用域链
const常量
一定要赋初始值
一般常量用大写
常量值不能被修改
块级作用域
对于数组和对象元素的修改,不算对常量的修改,不会报错
解构赋值
es6允许按照一定模式从数组和对象中提取值,对变量进行赋值,称为解构赋值
模板字符串
好处:内容中可以直接出现换行符,变量拼接{$()}
简化对象写法
原先的写法
<script>
const School = {
name :name,
age: age,
change:change,
improve:function(a,b){
console.log(a,b);
}
}
improve(1,2)
</script>
现在的写法
<script>
const School = {
name,
age,
change,
improve(a,b) {
console.log(a,b);
}
}
improve(1, 2)
</script>
箭头函数
<script>
// let fn = function(){
// }
let fn = ()=>{
}
</script>
this是静态的,this始终指向函数声明时所在作用域下的this的指向
不能作为构造函数 实例化对象
不能使用arguments 变量
箭头函数简写:
省略小括号:当形参只有一个时候
省略花括号:当代码体只有一条语句的时候,此时return必须省略
注:适合与this无关的回调(定时器、数组的方法回调)
不适合与this有关的回调(事件回调、对象的方法)
es6允许给函数赋初始值
形参初始,具有默认值的参数,一般位置要靠后
与解构赋值结合
es6中rest参数
function date(){
console.log(arguments);
}
date('周芷若','任盈盈','东方不败')
function date(...args){
console.log(args);
}
date('周芷若','任盈盈','东方不败')
rest参数要放到参数最后
扩展运算符
...扩展运算符能将数组转换为逗号分隔的参数序列
应用:
数组和并
数组克隆
将伪数组转为真正的数组
es6中引入一种新的,独一无二的数据类型 Symbol 类似于字符串类型
Symbol的值是唯一的,用来解决命名冲突的问题
Symbol值不能参与其他数据类型进行运算
Symbol定义的对象属性不能使用for...in循环遍历,但可以用Reflect.ownKeys来获取对象的所有键名
JS数据类型
口诀:usonb
u: undefined
s: symbol string
o: object
n: null number
b: boolean
迭代器(Iterator)一种接口
任何数据,只要部署Iterator接口,就能完成遍历操作,ES6创造一种新的遍历命令for...of 循环,Iterator用 for...of
其中:Array Arguments Set Map String TypeArray Nodelist 原生具备Iterator接口数据
工作原理:
创建一个指针对象,指向当前数据解构的起始位置
每一次调用对象的next方法,指针自动指向数据解构的第一个成员
接下来,不断调用next方法,指针一直往后移,直到指向最后一个成员
每次调用next方法,返回一个包含value和done的属性对象
自定义遍历数组
例子
//对对象的遍历
const school = {
name: "666班",
status: [
'lht',
'jj',
'hhh'
],
[Symbol.iterator](){
let index = 0; //设置索引
let _this = this //改变this指向
return {
next: function () {
if (index < _this.status.length) {
const result = {
//next中的两个属性
value: _this.status[index], done: false
};
index++;
return result;
} else {
return { value: undefined, done: true }
}
}
}
}
}
for (let v of school) {
console.log(v);
}
生成器
就是一个特殊函数
异步编程 纯回调函数 node fs ajax mongodb
function * gen() {
yield '天王盖地虎'; //yield就是函数代码的分隔符
yield '宝塔镇河妖';
yield '镇宅驱邪'
}
let iterator = gen();
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
for(let v of gen()){
console.log(v);
}
生成器函数也可以传参,next传入的参数会作上一个yield语句返回的结果
异步编程(文件操作,网络操作,数据库操作)
// 回调地狱
// setTimeout(()=>{
// console.log(111);
// setTimeout(()=>{
// console.log(222);
// setTimeout(()=>{
// console.log(333);
// },3000)
// },2000)
// },1000)
// 解决回调地狱
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 对象用于表示一个异步操作的最终完成(或失败)及其结果值。
//实例化Promise对象
const p = new Promise (function(resolve,reject){
setTimeout(function(){
// let data = '数据库中的数据';
// resolve(data)
let err = '数据读取失败';
reject(err)
},1000)
});
//调用promise对象中的then方法
p.then(function(){
console.log(value);
},function(reason){
console.error(reason);
})
Promise.prototype.then
//创建promise对象
const p = new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve('用户数据')
},1000)
});
//调用then方法 then方法返回的结果是Promise对象,对象状态由回调函数的执行结果决定
//1、如果回调函数中返回的结果是非promise类型的属性,状态伪成功,返回的值为对象成功的值
const result = p.then(value=>{
console.log(value);
//1、非promise类型的属性
return 'lht 666'
//2、是promise类型的属性
return new Promise((resolve,reject)=>{
resolve('ok')
reject('error')
})
//3、抛出错误
throw new Error('出错了!')
throw '出错了'
},reason=>{
console.warn(reason);
})
//链式调用 改变回调地狱
p.then(value=>{
},reason=>{
}).then(value=>{
},reason=>{
})
console.log(result);
catch方法
const p = new Promise((resolve,reject)=>{
setTimeout(() => {
//设置p对象为失败状态,并设置失败的值
reject("出错!")
}, 1000);
})
p.then(function(value){},function(reason){
console.error(reason);
})
p.catch(function(reason){
console.warn(reason);
})
set
es6提供了新的数据结构Set(集合)。类似于数组,但成员的值都是唯一的,
集合实现了iterator接口,所以可以使用 扩展运算符 和for.. of... 进行遍历
集合的属性和方法:
size 返回集合的元素个数
add 增加一个新元素,返回当前集合
delete 删除元素,返回bollean
has 检测集合中是否包含某个元素,返回boolean值
let s = new Set()
console.log(s,typeof s);
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);
}
let arr = [1,2,3,3,5,6,1,2]
//数组去重
// let result = [...new Set(arr)];
// console.log(result);
//交集
let arr2 = [1,4,5,3]
// let result2 = [... new Set(arr)].filter(item=>{
// let s2 = new Set(arr2)
// if(s2.has(item)){
// return true
// }else{
// return false
// }
// })
let result2 = [... new Set(arr)].filter(item=>new Set(arr2).has(item))
console.log(result2);
//并集
let union = [...new Set([...arr, ...arr2])]
console.log(union);
//差集
let result3 = [... new Set(arr)].filter(item=>!(new Set(arr2).has(item)))
console.log(result3);
Map
es6提供了Map数据结构,它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。Map也实现了iterator接口,所以使用 扩展运算符 和 for...of... 进行遍历。
Map的属性和方法:
size 返回Map的元素个数
set 增加一个新元素,返回当前Map
get 返回键名对象的键值
has 检测Map中是否包含某个元素,返回boolean值
clear 清空集合,返回undefined
//声明Map
let m = new Map()
//添加元素
m.set('name','lht')
m.set('hobby','badminton')
console.log(m);
m.set('change',function(){
console.log("我喜欢吃溜肉段");
});
let key = {
school:'HGC'
};
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);
Class 类
es6提供了更接近传统语言的写法,引入了 CLass(类)这个概念,作为对象的模板。 通过class关键字,可以定义类,es6的class可以看作只是一个语法糖,它的绝大部分功能,es5都能做到,新的class写法只是让对象原型的写法更加清晰,更加面向对象编程语法而已
class 声明类
constructor 定义构造函数初始化
extends 继承父类
super 调用父级的构造方法
static 定义静态方法和属性
父类方法可以重写
//手机
//ES5
function Phone(brand, price) {
this.brand = brand
this.price = price
}
//添加方法
Phone.prototype.call = function () {
console.log("我可以打电话");
}
//实力化对象
let Xiaomi = new Phone("小米",1999)
Xiaomi.call()
console.log(Xiaomi);
// ES6
class Shouji{
//构造方法,名字不能修改
constructor(brand,price){
this.brand = brand;
this.price = price
}
//方法必须使用该语法,不能使用es5的对象完整形式
call(){
console.log("我也可以打电话");
}
}
let vivo = new Shouji("vivo",3999)
console.log(vivo);
静态成员
// function Phone (){
// }
// //函数对象 属性和方法
// Phone.name = "手机";
// Phone.change = function(){
// console.log("我可以改变");
// }
// //实例对象 属性和方法
// let iphone = new Phone();
// // console.log(iphone.name); //undefined
// // console.log(iphone.change()); // iphone.change is not a function
// //所以函数对象属性和方法与实例对象上的属性和方法是不相同的 对于函数对象这种属性我们称为静态成员
// //实例对象的属性和方法 和 构造函数原型对象上的属性是相通的
// Phone.prototype.size = "5.5inch"
// console.log(iphone.size);
class Phone{
//静态属性
static name = "手机";
static change (){
console.log("我能打电话");
}
}
let iphone = new Phone()
console.log(iphone.name); //undefined
console.log(Phone.name); //手机
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("我可以玩游戏");
}
const xiaomi = new SmartPhone('小米',1999,'白色','6.6inch')
console.log(xiaomi);
es6中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 xiaomi = new SmartPhone('小米',1999,"白色",'6.6inch');
console.log(xiaomi);
子类对父类方法的重写
直接调用方法,更改就可以
class中get和set
//get 和 set
class Phone{
get price(){
console.log("价格属性被读取");
return '666';
}
set price(value){
console.log('价格属性被修改');
}
}
//实例化对象
let s = new Phone ();
console.log(s.price);
s.price = 'free'
数值扩展
二进制和八进制
Number.isFinite 检测一个数字是否为有限数
Number.isNaN 检测一个数值是否为NaN
Number.parseInt Number.parseFloat 字符串转整数
Number.isInteger 判断一个数是否为整数
Number.EPSILON 是JavaScript表示最小精度 其属性接近于 2.2204460492503130808472633361816E-16
对象方法扩展
Object.is 判断两个值是否完全相等
Object.assign 对象和并
Object.setPrototypeOf 设置原型对象
Object.getPrototypeof 获取原型对象
模块化
模块化是指将一个大的程序文件,拆分成许多小的文件,然后按照小文件组合起来
模块化的好处:
防止命名冲突
代码复用
高维护性
模块化规范产品
es6之前的模块化规范有:
CommonJS = > NodeJS Browserify
AMD => requireJS
CMD => seaJS
es6模块化语法
模块化主要由两个命令构成: export 和 import
export 命令用于规定模块的对外接口
import 命令用于输入其他模块提供的功能
//1、通用的导入方式
//引入 m1.js 模块内容
import * as m1 from "./m1.js";
//引入 m2.js 模块内容
// import * as m2 from "./m2.js"
//引入 m3.js 模块内容
// import * as m3 from "./m3.js"
console.log(m1);
// console.log(m2);
// console.log(m3);
//2、解构赋值形式
import {school,change} from"./m1.js"
import {school as Hgc,change} from"./m2.js"
import {default as moren} from"./m3.js"
//3、简便形式 针对默认暴露
import moren from "./m3.js"
console.log(moren);
//分别暴露
export let school = "HGC";
export function change(){
console.log("我要改名");
}
//统一暴露
let school = "HGC";
function change(){
console.log("我要改名");
}
export{school,change}
//默认暴露
export default {
school: 'HGC',
change: function () {
console.log("我要改名");
}
}