【ES6】ES6超详讲解(@_@;)
文章目录
- 一、初识ES6
- let和const
- 二、模板字符串与箭头函数
- 模板字符串
- 箭头函数
- this指向
- 不适合箭头函数的场景
- 三、解构赋值
- 什么是解构赋值
- 数组的解构赋值
- 数组解构赋值的默认值
- 类数组的解构赋值
- 函数参数的解构赋值
- 交换变量的值
- 对象的解构赋值
- 对象解构赋值的默认值
- 其他数据类型的解构赋值
- 字符串的解构赋值
- 数值和布尔值的解构赋值
- undefined 和 null 的解构赋值
- 四、对象字面量的增强与函数参数的默认值
- 对象字面量的增强
- 对象字面量
- 属性简洁表示
- 方法的简洁表示
- 方括号语法
- 函数参数的默认值
- 五、剩余参数与展开运算符
- 剩余参数
- 数组的展开运算符
- 对象的展开运算符
- 六、Set 和 Map 数据结构
- Set
- 方法
- Set 构造函数的参数
- 注意
- Map
- Map 和对象的区别
- Map实例的方法和属性
- 构造函数的参数
- 注意
- 七、遍历器与for…of循环
- Iterator
- for…of
- Iterator自动化
- 使用for…of
- 在for…of中得到数组的索引
- entries()得到的是索引 + 值组成的数组的可遍历对象
- 原生可遍历与非原生可遍历
- 原生可遍历
- 非原生可遍历
- 使用了iterator的地方
- 八、ES6新增方法
- 1. 字符串新增方法
- includes()
- padStart() 和 padEnd()
- trimStart() 和 trimEnd()
- replace() 和replace()
- 2. 数组新增方法
- includes()
- Array.from()
- find() 和 findIndex()
- 3. 对象新增方法
- Object.assign()
- Object.keys()、Object.values()、Object.entries()
- 九、Promise
- 1. Promise 的状态
- 2. then 方法
- 执行后的返回值
- 3. catch() 方法
- 4. finally() 方法
- 6. 构造函数方法
- Promise.resolve()
- Promise.reject()
- Promise.all()
- Promise.race()
- Promise.allSettled()
- 7. 注意
- resolve或reject函数执行后的代码
- Promise.all / race / allSettled的参数问题
- 八、Class类
- 1. 初始Class
- 两种定义形式
- 2. 属性与方法
- 实例属性和实例方法
- 私有属性和方法
- 3. 继承
- entends
- super
- 九、Module模块
- 1. Module的两种导出和导入方式
- export default和import
- export 和 import
- 2. 注意
- 模块顶层的this
- import 和 import()
- 导入导出复合写法
- 十、Babel与Webpack
- 1. Babel
- 准备
- 2. Webpack
- 使用
- 核心概念
- 3. plugins
- html-webpack-plugin
- 处理css文件
- 使用`file-loader`处理css中的本地图片
- 4. 使用webpack-dev-serve搭建开发环境
一、初识ES6
ES与JavaScript的关系
JavaScript(浏览器端) = ECMAScript(语法 + API) + DOM + BOM
对于不支持的浏览器,可以使用Bable转码
let和const
let代替var声明变量
const用来声明常量
注意:
- const声明的常量,允许在不重新赋值的情况下修改它的值
const person = {username : 'aaa'};
person = {}; // 报错
person.username = 'niubi'; // 可以成功修改
console.log(person);
- 在一个具体的业务场景中,如果不清楚用const还是let,就先写成const
和var的区别
重复声明:var一个变量可以重复声明,let和const则不能
变量提升:let和const不存在变量提升
暂时性死区
只要作用域内存在let、const,他们所声明的变量或常量就会自动 “绑定” 这个区域,不再受外部作用域的影响
let a = 2; function func () {console.log(a);let a = 1; } func(); // 报错let b = 1; function func() {console.log(b); } func(); // 成功打印
window对象的属性和方法
全局作用域中,var声明的变量、通过function声明的函数,会自动变为window对象的属性或方法,但let、const不会
块级作用域
var没有块级作用域,let、const有块级作用域
作用域:块级作用域,函数作用域,全局作用域
二、模板字符串与箭头函数
模板字符串
const person = {username: 'name',age: 20,sex: 'male'
};
const info1 = '我叫' + person.username + ',性别: ' + person.sex + ',今年' + person.age + '岁了';
console.log(info1);const info2 = `我叫${person.username},性别: ${person.sex},今年${person.age}岁了`;
console.log(info);
注意:
- 模板字符串中,所有空格、换行或缩进都会被保留在输出中
- 只要最终可以得出一个值的就可以通过
${}
注入到模板字符串中
箭头函数
省略了function关键字
(x, y) => {return x + y;
}; // 此时是一个匿名函数const add = (x, y) => {return x + y;
}
注意:
- 单个参数:可以将参数的括号省略掉
const add = x => {return x + 1;
};
- 单行函数体:可以同时省略
{}
和return
const add = (x, y) => {return x + y;
};
const add = (x, y) => x + y;
- 单行对象:如果箭头函数返回单行对象,可以在{}外面加上(),让浏览器不再认为那是函数体的花括号
const add = (x, y) => {return {value: x + y};
};const add = (x, y) => ({value: x + y
});
this指向
非箭头函数的this指向
- 全局作用域中的this指向
console.log(this); // window
- 一般函数中的this指向
this指向和函数在哪调用无关,只和谁在调用有关
// 1.
function add() {console.log(this);
}
add();
// 严格模式下,指向undefined
// 非严格模式下,undefined -> window// 2.
document.onclick = function () {console.log(this);
};
document.onclick(); // 指向document// 3.
function Person(username) {this.username = username;console.log(this);
}
const p = new Person('lisi');
箭头函数的this指向
箭头函数没有自己的this(通过作用域链查找)
不适合箭头函数的场景
- 作为构造函数
- 需要this指向调用对象的时候
- 需要使用arguments的时候
三、解构赋值
什么是解构赋值
解析某一数据的结构,将我们想要的东西提取出来,赋值给变量或常量
const arr = [1, 2, 3];
const a = arr[0];
const b = arr[1];
const c = arr[2];
console.log(a, b, c);
// 通过下标来访问元素比较麻烦
// 可通过如下方式简化const [a, b, c] = [1, 2, 3];
console.log(a, b, c);
数组的解构赋值
- 模式(解构)匹配
- 索引值相同的完成赋值
const [a, [, , b], c] = [1, [2, 4, 5], 3];
console.log(a, b, c); // 1, 5, 3
数组解构赋值的默认值
const [a, b] = []; // 等价于 const [a, b] = [undefined, undefined];
console.log(a, b); // undefined undefined// 给取到undefined元素一个默认值
const [a = 1, b = 2] = [];
console.log(a, b); // 1 2
默认值的生效条件
只有当一个数组成员严格等于 ===
undefined
时,对应的默认值才会生效
默认值表达式
如果默认值是表达式,默认值表达式是惰性求值的
// 如果用不到表达式,那么表达式就不会执行
const func = () => {console.log('执行了表达式');
};
const [a = func()] = [1];
console.log(a); // 1
类数组的解构赋值
function func() {const [a, b] = arguments;console.log(a, b); // 1 2
}
func(1, 2);
<p>123</p>
<p>456</p>
<script>const [p1, p2] = document.querySelectAll('p');console.log(p1, p2);
</script>
函数参数的解构赋值
const array = [1, 1];
const add = arr => arr[0] + arr[1];
// 用解构赋值之后
const add = ([a, b]) => a + b;
console.log(add(array)); // 2
交换变量的值
[x, y] = [y, x];
对象的解构赋值
- 模式匹配
- 属性名相同的完成赋值(和书写顺序无关)
const {age, username} = {username: 'lisi', age: 18};// 完整写法
const {age: age, username: username} = {username: 'lisi', age: 18};// 起别名
const {age: nage, username: nname} = {username: 'lisi', age: 18};
console.log(nage, nname); // 18 'lisi'
console.log(age, username); // 报错
对象解构赋值的默认值
对象的属性值严格等于undefined
时,对应的默认值才会生效
const {username = 'niubi', age = 0} = {username: 'lisi'};
- 默认值表达式
如果默认值是表达式,那么默认值表达式是惰性求值的
- 将一个已经声明的变量用于解构赋值
let x = 2;
({x} = {x: 1}); // 加上圆括号,防止{}被浏览器认为是代码块
- 可以取到继承的属性
const {a = 1} = {};
console.log(a); // 1const {toString} = {};
console.log(toString); // 不是undefined
// Object.prototype 可以取到继承的属性
console.log(Object.prototype);
其他数据类型的解构赋值
字符串的解构赋值
- 数组形式的解构赋值
const [a, b, , , c] = 'hello';
console.log(a,b,c);
- 对象形式的解构赋值
const {0: a, 1: b, length} = 'hello'; // 属性名就是索引值
数值和布尔值的解构赋值
将等号右边的值转为对象,只能获取到继承的东西
const {aa, toString} = 123;
console.log(aa, toString);
undefined 和 null 的解构赋值
由于undefined和null无法转为对象,所以对它们进行解构赋值都会报错
四、对象字面量的增强与函数参数的默认值
对象字面量的增强
对象字面量
// 对象字面量
const person = {age: 18,speak: function () {};
};
属性简洁表示
当键名和变量或常量名一样的时候,可以只写一个
const age = 18;
const person2 = {age: age
};const person3 = {age
};
方法的简洁表示
const person = {// speak: function () {}speak(){};
};
方括号语法
给对象添加属性
const prop = 'age';
const person = {};
person[prop] = 18;// 此时person对象如下
{age: 18}
// 方括号语法可以写在对象字面量中
const person = {[prop]: 18
};
方括号中可以放什么?
[值或通过计算可以得到值的(表达式)]
方括号语法和点语法的区别
点语法是方括号语法的特殊形式,当属性名或方法名是合法标识符时,可以使用点语法,其他情况使用方括号语法
函数参数的默认值
和解构赋值时设置默认值的方式类似
const multiply = (x, y) => {if (typeof y === 'undefined') {y = 1;}return x * y;
};// 设置参数默认值
const multiply2 = (x, y = 1) => {return x * y;
};
注意:
- 默认值生效条件:不传参,或明确传undefined为参数的情况下,默认值才会生效
- 默认值表达式:惰性求值
- 函数参数的默认值最好从参数列表的右边开始设置
经典用法
const loguser = ({username = 'zhangsan', age = 0, sex = 'male'} = {}) => console.log(username, age, sex);
logUser();
五、剩余参数与展开运算符
剩余参数
当不确定要传几个参数的时候就用剩余参数
[1, 2, 3] ---> 1, 2, 3
const add = (x, y, z, ...args) => {console.log(x, y, z, args);
};
实参与形参中的固定参数进行对应,剩余的就归剩余参数管(放入数组当中)
剩余参数永远是个数组,若没有取到值,那就是空数组
注意:
箭头函数的剩余参数
箭头函数的参数部分当只有一个剩余参数时,不能省略圆括号
const add = (...args) => {}
使用剩余参数代替arguments获取实际参数
由于箭头函数中没有arguments,所以要想获取参数数组,就可以用剩余参数
const add = (...args) => {console.log(args); }; add(1, 2);
剩余参数的位置
剩余参数只能是最后一个参数,之后不能再有其他参数,否则会报错
数组的展开运算符
将数组的形式展开为参数列表的形式
[1, 2, 3] ---> 1, 2, 3
eg. 求数组中的最小值
let min = Math.min(...[2, 1, 3]);
// 相当于 Math.min(2, 1, 3);
展开运算符应用
复制数组
let arr = [1, 2, 3, 4]; let arr2 = [...arr];
合并数组
let arr1 = [1, 2]; let arr2 = [3, 4]; let arr3 = [5]; let arr = [...arr1, ...arr2, ...arr3];
字符串转为数组
[...'hello'];
类数组对象转换为数组
[...arguments];
[...document.querySelectorAll('p')];
对象的展开运算符
对象不能直接展开,必须要在{}
中
const student = {name: 'xiaohong',sex: 'female'
};
const student1 = {...student};
也可以将对象的属性进行合并
注意:
空对象的展开
如果展开一个空对象,则没有任何效果
非对象的展开
如果展开的不是对象,则会自动将其转为对象,再将其属性罗列出来
如果展开字符串,它会自动转成一个类似数组的对象,因此返回的不是空对象
console.log({...'hello'}); // {0: 'h', 1: 'e', 2: 'l', 3: 'l', 4: 'o'}
不会展开对象中的对象属性
应用:
复制对象
用户参数和默认参数
const logUser = userParam => {const defaultParam = {username: 'ZhangSan',age: 0,sex: 'male'};const param = {...defaultParam, ...userParam}; // 将用户参数和默认参数进行合并console.log(param.username); };
六、Set 和 Map 数据结构
Set
Set 是一系列无序、没有重复值的数据集合
const s = new Set();
s.add(1);
s.add(2);
注意:
- Set中不能有重复成员
- Set 没有下标去标示每一个值,所以 Set 是无序的,也不能像数组那样通过下标访问
方法
add 方法
s.add(1).add(2); // 支持连续调用
has 方法
判断Set中是否含有某个成员
console.log(s.has(1)); // true
delete 方法
删除成员(删除不存在的成员不会报错)
clear
清空 Set
forEach
遍历set中的元素(按照成员添加进集合的顺序遍历)
s.forEach(function (value, key, set) { // set是当前set的引用console.log(value, key, set === s) }, document); // 第二个参数指定函数中的this指向// set 中value == key
size
Set 构造函数的参数
Set 构造函数可以传入数组、字符串、arguments、NodeList、Set等
注意
Set判断重复的方式
Set 对重复值的判断基本遵循严格相等
===
,但是对于NaN的判断与===
不同,Set 中NaN 等于 NaN什么时候使用Set
- 数组或字符串去重
- 不需要通过下标访问,只需要遍历时
- 为了使用Set提供的方法和属性时
Map
映射
Map 和对象都是键值对的集合
const m = new Map();
m.set('age', 18); // 添加元素
Map 和对象的区别
对象一般用字符串当作键,而 Map 的键可以是基本数据类型,引用数据类型
Map实例的方法和属性
set
const m = new Map(); m.set('age', 18).set(true, 'true').set('age', 20); console.log(m); // 使用set添加新成员,键如果已经存在,后添加的键值会覆盖已有的
get
通过键来获取值
console.log(m.get('age'));
has
delete
clear
forEach
size
和Set的方法用法类似
构造函数的参数
数组
只能传二维数组,并且必须体现出键和值
console.log(new Map([['name', 'lisi'], ['age', 18]]));
Set、Map
Set中也必须体现出键和值
const s = new Set([['name', 'lisi'], ['age', 18]]); console.log(new Map(s));
const m1 = new Map([['name', 'lisi'], ['age', 18]]); const m2 = new Map(m1);
注意
判断键名的方式
基本遵循严格相等
===
,是对于NaN的判断与===
不同,Map 中NaN 等于 NaN什么时候使用Map
如果只是需要 key -> value 的结构,或者需要字符串以外的值做键,使用Map更合适
七、遍历器与for…of循环
Iterator
Symbol.iterator(可遍历对象的生成方法) --> it (可遍历对象) --> it.next() --> it.next --> 直到done为 true
const it = [1, 2][Symbol.iterator]();
console.log(it.next()); // {value: 1, done: false}
console.log(it.next()); // {value: 2, done: false}
console.log(it.next()); // {value: undefined, done: true};
console.log(it.next()); // {value: undefined, done: true};
Iterator遍历器是一个统一的遍历方式,但使用过程较繁琐,一般情况下不会直接使用Iterator遍历
ES6提供了for…of使遍历更方便
for…of
Iterator自动化
const arr = [1, 2, 3];
const it = arr[Symbol.iterator]();
let next = it.next();
console.log(next);
while (!next.done) {console.log(next.value);next = it.next();console.log(next);
}
使用for…of
const arr = [1, 2, 3];
for(const item of arr) {console.log(item);
} // for…of循环只会遍历出那些done为false时,对应的value值
在for…of中得到数组的索引
const arr = [1, 2, 3];
for (const keys of arr.keys()) {console.log(keys);
}
entries()得到的是索引 + 值组成的数组的可遍历对象
for (const entries of arr.entries()) {console.log(entries);
}
原生可遍历与非原生可遍历
只要有 Symbol.iterator 方法,并且这个方法可以生成可遍历对象,就是可遍历的
只要可遍历,就可以使用for…of来统一遍历
原生可遍历
可以直接使用for…of遍历
- 数组
- 字符串
- Set
- Map
- arguments
- NodeList
非原生可遍历
默认情况下不能直接使用for…of来遍历
- 一般对象
const person = {sex: 'male', age: 18};
person[Symbol.iterator] = () => {let index = 0;return {next(){index++;if (index === 1) {return {value: person.sex,done: false};} else if (index === 2) {return {value: person.age,done: false};} else {return {done: true};}}}
}for (const item of person) {console.log(item);
}
使用了iterator的地方
数组的展开运算符(只要可遍历,就可以使用数组的展开运算符)
数组的解构赋值(只要可遍历,就可按数组方式进行解构赋值)
const [a, b] = [1, 2]; const [a, b] = [...[1, 2]]; const [a, b] = 'hi'; const [a, b] = [...'hi']; const [a, b] = new Set([3, 4]); const [a, b] = [...new Set([3, 4])];
Set和Map的构造函数
构造函数的参数必须是可遍历的
八、ES6新增方法
1. 字符串新增方法
includes()
判断字符串中是否含有某些字符
console.log('abc'.includes('a')); // true
console.log('abc'.includes('ab')); // true
console.log('abc'.includes('ac')); // false
穿第二个参数表示开始搜索的位置(默认是0)
console.log('abc'.includes('a', 0)); // true
console.log('abc'.includes('a', 1)); // false
padStart() 和 padEnd()
补全字符串长度
'm'.padStart(6,'ab'); // 'ababam'
'm'.padEnd(6, 'ab'); // 'mababa'
注意:
原字符串的长度等于或大于最大长度,不会消减原字符串,字符串不全不生效,返回原字符串
用来补全的字符串与原字符串长度之和超过了最大长度,截去超出位数的补全字符串,原字符串不动
console.log('abc',padStart(10, '0123456789'));
如果省略第二个参数,默认使用空格补全
trimStart() 和 trimEnd()
清除字符串的首或尾空格
对应和trimLeft() 和 trimRight() 一样
trim()首尾空格全部清除
replace() 和replace()
replace()用来替换第一个匹配的内容
replaceAll() 用来替换所有匹配的内容
'aabbcc'.replace('b', 'x'); // aaxbcc
'aabbcc'.replaceAll('b', 'x'); // aaxxcc
2. 数组新增方法
includes()
基本遵循严格相等,但认为NaN 等于 NaN
Array.from()
将其他数据类型转换为数组
可以转化为数组的有:
数组、字符串、Set、Map、nodeList、arguments均可转换为数组
拥有length属性的任意对象
第二个参数类似于map方法,对每个元素处理之后放入数组中
let arr = [1, 2, 3, 4];
const arr2 = arr.map((value) => {return value * 2;
});
console.log(arr2); // [2, 4, 6, 8] map方法会返回一个新数组
const arr = [1, 2, 3, 4];
const arr2 = Array.from(arr, value => value * 2);
console.log(arr);
console.log(arr2);
第三个参数用来修改内部的第二个参数内部的this指向
find() 和 findIndex()
find() 找到满足条件的一个立即返回
findIndex() 找到满足条件的一个,立即返回其索引
const arr = [1, 2, 3, 4, 9, 3, 4];
const num = arr.find((value) => {return value > 5;
});
console.log(num); // 9
第二个参数修改第一个参数中的this指向
3. 对象新增方法
Object.assign()
用来合并对象
const apple = {color: '红色',shape: '圆形',taste: '甜'
};
const pen = {color: '黑色',shape: '圆柱形',use: '写'
};
// 合并对象
console.log(Object.assign(apple, pen)); // {color: '黑色', shape: '圆柱形', taste: '甜', use: '写'}
console.log(apple); // {color: '黑色', shape: '圆柱形', taste: '甜', use: '写'}
console.log(pen); // {color: '黑色', shape: '圆柱形', use: '写'}
// 该方法直接合并到了第一个参数中,返回的就是合并后的对象
如果要返回一个新对象,可以用下面的方法
Object.assign({}, apple, pen);
注意:
基本数据类型作为源对象
与对象的展开类似,先转换成对象再合并
console.log(Object.assign({}, undefined));
Object.keys()、Object.values()、Object.entries()
const person = {name: 'lisi',age: 18
};console.log(Object.keys(person)); // ['name', 'age']
console.log(Object.values(person)); // ['lisi', 18]
console,log(Object.entries(person)); // 二维数组
返回的都是数组
使用for…of遍历对象
const person = {name: 'lisi',age: 18
};
for (const person1 of Object.entries(person)) {console.log(person1);
} // 不能保证顺序
九、Promise
Promise 是异步操作的一种解决方案
一般用来解决层层嵌套的回调函数的问题
解决的不是回调函数,而是回调地狱
const p = new Promise(() => {}); // pending 未完成
1. Promise 的状态
const p = new Promise((resolve, reject) => {resolve(); // pending -> fulfilled 已成功// reject(); // pending -> rejected 已失败
});
Promise 的状态一旦变化,就不会改变了
2. then 方法
p.then(() => {console.log('success');
}, () => {console.log('fail');
}); // 已成功 执行第一个函数,已失败,执行第二个函数
执行后的返回值
then 方法执行后返回一个新的Promise 对象
const p = new Promise((resolve, reject) => {resolve('resolve');
});
p.then(data => {console.log('succ1', data); // succ1 resolve
}, data2 => {console.log('err1', data2); // return undefined; // 默认返回undefined// 相当于return new Promise(resolve => {resolve(undefined);});
}).then(data3 => {console.log('succ2', data3); // succ2 undefined
}, (data4) => {console.log('err2', data4);
});
3. catch() 方法
catch() 本质上是then() 的特例,专门用来处理rejected 状态
const p = new Promise((resolve, reject) => {reject('fail');
});
p.then(null, data => {console.log(data);
});
个人理解:then() 和 chtch() 都是用来捕获Promise的执行状态的,then() 既可以捕获resolve,也可以捕获reject,而catch() 只能捕获reject,两者都是只要捕获成功就返回一个fulfilled状态的Promise,否则catch() 没反应,then() 会报错
catch() 可以捕获它前面的错误
一般建议:Promise 对象后面要跟catch 方法,这样可以处理Promise内部的错误
4. finally() 方法
也是then() 方法的特里,返回传过来的值(不分状态)
6. 构造函数方法
Promise.resolve()
是成功状态Promise的一种简写形式
new Promise(resolve => resolve('succ'));
// 相当于
Promise.resolve('succ');
- 可以传的参数
一般参数
Promise对象
当参数为Promise对象时,直接返回这个Promise对象,什么都不做
const p = new Promise(resolve => resolve('succ')); Promise.resolve(p).then(data => {console.log(data); });
当resolve函数接收的时Promise对象时,后面的then会根据传递的Promise对象的状态变化决定执行哪一个回调
const p = new Promise(resolve => resolve('succ')); const p2 = new Promise(resolve => resolve(p)).then(data => {console.log(data); }); // 个人理解,这其实相当于是Promise对象的复制
具有then方法的对象
const obj = {then() {console.log('obj--then');} }; Promise.resolve(obj); // 传入之后会执行obj中的then方法,并返回一个Promise对象,状态为pending // obj的then方法可以有resolve和reject两个参数,来决定状态
// 参数是其他值时,相当于时通过resolve传参
Promise.reject()
是失败状态Primise的一种简写形式
const p = new Promise((resolve, reject) => {reject('fail');
});
Promise.reject('fail');
- 参数
不管什么参数,都会原封不动的向后传递,作为后续方法的参数
Promise.all()
关注多个Promise对象的状态变化
传入多个Promise实例,包装成一个新的Promise实例返回
Promise.all() 的状态变化与所传入的Promise实例对象状态有关
所有状态都变成resolved,最终状态才会变成resolved
只要有一个变成rejected,最终的状态就会变成rejected
Promise.race()
它的状态取决于第一个完成的 Promise实例对象,如果第一个完成的成功了,那最终的就成功;如果第一个完成的失败了,那最终的就失败
Promise.allSettled()
Promise.allSettled() 的状态与传入的Promise状态无关,永远都是成功的
它只会忠实的记录下各个Promise的表现,分别以对象的形式表现
7. 注意
resolve或reject函数执行后的代码
后面的代码还可以继续执行
建议在调用这两个函数的时候加上return,不再执行它们后面的代码
const p = new Promise((resolve, reject) => {return resolve('resolve');
});
Promise.all / race / allSettled的参数问题
参数如果不是Promise数组,会将不是Promise的数组元素转变为Promise对象(成功状态)
任何可遍历的都可以作为参数
Promise.all / race / allSettled的错误处理
八、Class类
1. 初始Class
class Person {constructor(name, age) {this.name = name;this.age = age;}sayHello() {console.log(this.name, this.age);}
}
const p = new Person('姓名', 18);
console.log(p);
p.sayHello();// class 和 构造函数其实底层是一样的,只是在语法层面是class,但作用效果和构造函数一样
两种定义形式
// 声明形式
class Person {}// 表达式形式
const Person2 = class {}// 立即执行的类
new (class {constructor() {console.log('constructor');}
})();
2. 属性与方法
实例属性和实例方法
class Person {age = 18; // 实例属性sex = 'male';static version = '1.0'; // 静态属性(目前只是提案,有兼容性问题),可以考虑将它写成方法的形式static getVersion() {return '1.0';}getAge = function () { // 实例方法return this.age;}constructor(age, sex) { // 构造方法this.age = age;this.sex = sex;}static getAge() { // 静态方法console.log('666');}
}
私有属性和方法
一般情况下,类的属性和方法都是公开的,公有属性和方法可以被外界修改,造成意向不到的后果
- 模拟私有属性和方法
_
开头表示私有将私有属性和方法移除类
(function () {let name = '';class Person {constructor(username) {name = username;}getName() {return name;}}window.Person = Person;
})();
(function () {const p = new Person('lisi');console.log(p.name); // undefinedconsole.log(p.getName()); // lisi
})();
3. 继承
entends
super
在构造方法中使用
super 代表父类的原型对象Person.prototype
所以定义在父类实例上的方法或属性,无法通过super调用
通过super调用父类的方法时,方法内部的this指向当前子类的实例
在静态方法中使用
super 指向父类,而不是父类的原型对象
通过super调用父类的方法时,方法内部的this指向当前的子类,而不是子类的实例
注意:使用super的时候,必须显式指定是作为函数还是作为对象使用
九、Module模块
模块:一个一个的局部作用域的代码块
模块内部默认是严格模式
模块系统需要解决的问题:
- 模块化的问题
- 消除全局变量
- 管理加载顺序
1. Module的两种导出和导入方式
export default和import
导出方式
const age = 18;
export default age;
// export default 18;
// 也可导出对象等
一个模块没有导出,也可以将其导入
import './index.js';
被导入的代码都会执行一遍,也仅会执行一遍
一个模块只能有一个export default
导入
import age from './index.js';
// import './index.js';
export 和 import
导出方式
// export 声明或语句
export const age = 555;// const age = 5;
//export {age};
导入
import {age} from 'index.js';
多个导入导出,起别名
export {fn as func, className, age};
import {func, className as person, age} from './index.js';
整体导入
会导入所有导出,包括 export default 导出的
import * as obj from './index.js';
同时导入
// 一定是export default的在前
import age, {func, age, className} from './index.js';
2. 注意
模块顶层的this
模块顶层的this指向
undefined
可以利用这个做提示信息
// 在要作为模块的的js文件中,如果未被按照模块的方式加载,进行提示
if (typeof this !== "undefined") {throw new Error('请使用模块化加载');
}
import 和 import()
import 命令具有提升效果,会提升到整个模块的头部,率先执行
import 和 export 命令只能在模块的顶层,不能在代码块中执行
import() 可以按条件导入
if (PC) {import('pc.js').then().catch();
} else if (Mobile) {import('mobile.js').then().catch();
}
导入导出复合写法
export {age} from './module.js'; // 复合写法export的东西无法在当前模块中使用
// 等价于
import {age} from './module.js';
export {age} from './module.js';
相当于中转站(不推荐写)
十、Babel与Webpack
1. Babel
Babel是js的一个编译器,将新版本的代码转换成浏览器都兼容支持的ES5或ES3版本的代码,兼容性问题交给Babel来处理
Babel本身可以编译ES6的大部分语法,如let,const,箭头函数,类
但是对于ES6新增的API,如Set,Map,Promise等全局对象,以及一些定义在全局对象上的定义,如Object.assign / Array.from 都不能直接编译,需要借助其他模块
Babel一般需要配合Webpack来编译模块语法
准备
node.js:是一个平台或者工具,对应浏览器
npm:node包管理工具
npm init
package.json:记录安装的包
安装node.js
初始化项目
npm init -> package.json
安装Babel需要的包
// 切换安装源,把源从国外切换到国内 npm config set registry https://registry.npm.taobao.org
npm install --save-dev @babel/core @babel/cli
使用Babel编译ES6代码
- 执行编译命令,在
package.json
文件中添加执行babel的命令
"scripts": {"build": "babel src -d dist" // 使用babel命令将src目录中的文件编译并输出到dist目录中// babel src --out-dir dist
},
- babel的配置文件
npm install @babel/preset-env --save-dev
- 创建
.babelrc
文件
{"presets": ["@babel/preset-env"]
}
npm run build
2. Webpack
静态模块打包器,当webpack处理应用程序时,会将所有这些模块打包成一个或多个文件
模块:webpack可以处理js / css / 图片 / 图标字体等单位
静态:开发过程中存在于本地的 js/css 图片/ 图标字体等文件,就是静态的(从远程服务器获取到的就是动态的,webpack无法处理)
使用
初始化项目
npm init
安装Webpack需要的包
npm install --save-dev webpack-cli webpack
配置webpack
创建
webpack.config.js
文件const path = require('path'); // path是node自己提供的一个模块(导入)module.exports = { // 导出mode: 'development',entry: './src/index.js',output: {path: path.resolve(__dirname, 'dist'),filename: 'bundle.js'} };
"scripts": {"webpack": "webpack --config webpack.config.js" },
npm run webpack
核心概念
entry
单入口
entry: './src/index.js',
多入口
entry: {main: './src/index.js',search: './src/search.js' },
output
对应单入口
output: {path: path.resolve(__dirname, 'dist'),filename: 'bundle.js' }
对应多入口
output: {path: path.resolve(__dirname, 'dist'),filename: '[name].js' }
loader
loader让webpack能够去处理那些非js文件的模块(有的loader也可以处理js文件)
帮助webpack处理各种模块
babel-loader将babel和webpack连接了起来,先完成代码编译再进行模块打包
使用
npm install --save-dev babel-loader@8.1.0 @babel/core @babel/preset-env
.babelrc配置文件
{"presets": ["@babel/preset-env"] }
webpack.config.js文件中添加
module: {rules: [{test: /\.js$/, // 想在哪些文件上面使用babel-loaderexclude: /node_modules/,loader: 'babel-loader' // 使用 babel-loader} // 不同的loader放在不同的对象中] }
npm run webpack
这样的操作相当于把之前在命令行中的操作放到了webpack中,并不会编译新增API
加入@babel/polyfill
npm install --save-dev core-js@3.6.5
引入
core-js
,在代码开头加import 'core-js/stable';
npm run webpack
配置loader
3. plugins
插件用于执行范围更广的任务
html-webpack-plugin
安装插件
npm install --save-dev html-webpack-plugin
在配置文件
webpack.config.js
中将其引入// 导入插件 const HtmlWebpackPlugin = require('html-webpack-plugin'); // 在module.exports中加入 plugins: [new HtmlWebpackPlugin({ // 几个入口就创建几个实例template: './3.html', // 指定一个html作为模板,最终打包完成后的js文件放在模板中filename: 'index.html',chunks: ['index'], // 指明要引入哪一个js文件(entry那里的名字)minify: { // html-webpack-plugin的其他功能// 删除index.html 中的注释removeComments: true,// 删除index.html 中的空格collapseWhitespace: true,// 删除各种html标签属性值的双引号removeAttributeQuotes: true}}) ]
运行webpack打包
npm run webpack
处理css文件
需要安装
css-loader
// 帮助webpack去识别css文件 npm install --save-dev css-loader // 识别css npm install --save-dev style-loader // 处理css 将样式添加到了style标签中
module: {rules: [{test: /\.css$/,use: ['style-loader' ,'css-loader'] // 从右向左执行}], },
要想使css通过link
来引入,就用mini-css-extract-plugin
new MiniCssExtractPlugin({filename: 'css/[name].css'
})
module: {rules: [{test: /\.css$/,use: [MiniCssExtractPlugin.loader, 'css-loader']}]
}
使用file-loader
处理css中的本地图片
{test: /\.(png|jpg|gif)/,use: {loader: "file-loader",options: {name: 'img/[name].[ext]' // 图片复制到dist的img目录下并保持原名}}
},
使用html-withimg-loader
来处理html中的图片
解析HTML文件,和file-loader配合使用
使用url-loader
可以对js中的图片进行处理(将图片作为模块引入)
将一下比较小的图片进行base64编码
配合
file-loader
一起使用{test: /\.(jpg|png|gif)$/,use: {loader: 'url-loader',options: {name: 'img/[name].[ext]',esModule: false,limit: 3000 // 当图片小于3K的时候进行base64编码}} }
各个包的版本号
"css-loader": "^4.1.1",
"file-loader": "^6.0.0",
"html-webpack-plugin": "^4.3.0",
"mini-css-extract-plugin": "^0.9.0",
"style-loader": "^1.2.1",
"webpack": "^4.44.1",
"webpack-cli": "^3.3.12",
"html-withimg-loader": "^0.1.16",
"url-loader@4.1.0"
4. 使用webpack-dev-serve搭建开发环境
webpack-dev-server@3.11.0
【ES6】ES6超详讲解(@_@;)相关推荐
- python全景图像拼接_超详讲解图像拼接/全景图原理和应用 | 附源码
研究好玩又有用的技术第 008 期 在学习中发现快乐,在应用找到价值.这是我第八期分享图像技术应用的文章. 前七期欢迎阅读和分享: 概述 作者:Thalles Silva 编译:AI算法与图像处理 图 ...
- 超详讲解图像拼接/全景图原理和应用 | 附源码
点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 概述 图像拼接是计算机视觉中最成功的应用之一.如今,很难找到不包含 ...
- AtCoder Beginner Contest 244 B题(超详讲解)
目录 题目 状态 代码及讲解 结语 题目 Time Limit: 2 sec / Memory Limit: 1024 MB Score : 200 points Problem Statement ...
- 二叉树——根据 中序 和 层序 建树,超详讲解。
模板题传送 背景: 树和二叉树基本上都有先序.中序.后序.按层遍历等遍历顺序,给定中序和其它一种遍历的序列就可以确定一棵二叉树的结构. 假定一棵二叉树一个结点用一个字符描述,现在给出中序和按层遍历的字 ...
- 【JavaSE】异常 超详讲解(编程思想)
希望通过博客和大家相互交流,相互学习,如有错误,请评论区指正 文章目录 一.什么是异常? Java的异常体系 如何排查异常 二. 处理异常 try-catch基本语法 这个时候就要处理异常 如果我们用 ...
- 你该懂的,IP地址超详讲解
一.简介 IP地址分为IPV4 IPV6,我们这里所说的IP地址指的是IPV4的地址. IPV4( InternetProtocol Version 4 )互联协议版本4,有版本V4之前就有IPV1I ...
- 超全、超详的Spring Boot配置讲解笔记
超全.超详的Spring Boot配置讲解笔记 springboot默认加载配置 SpringBoot使用两种全局的配置文件,全局配置文件可以对一些默认配置进行修改. application.prop ...
- 【平衡小车制作】(一)硬件原理图讲解(超详解)
大家好,我是小政.之后的一系列文章我将介绍我玩平衡小车的过程以及遇到的一些问题,将这些内容记录下来分享给大家,也让大家少走一些弯路.接下来我将从硬件框架选择.软件编程.PID算法.PID调参.蓝牙 ...
- react的超详细讲解
create-react-app 项目目录 在HTML中使用react 1 2 3基础 React的注意事项 模拟的React 和 render React组件 函数组件 类组件 React 的数据源 ...
最新文章
- 人脸识别引爆下一代生物支付四军之战
- word图片自动换行不亮_知网查重时提交pdf检测结果竟然比Word高很多!
- 垃圾回收器之标记擦除法
- android 蒙版图片带拖动_黑橙修图:新手入门篇2-一句话带你认识图层蒙版
- Unity变量命名的6个重要提示
- python3.7运行报错_Python 3.7 环境下运行 scrapy crawl 报错 def write(self, data, async=False)?...
- 图书管理系统(借还图书)--Java实现(附源码)
- CCNA考试题库中英文翻译版及答案1
- sklearn.metrics.multilabel_confusion_matrix
- Mysql联表查询(学生表、教师表、成绩表、课程表)
- 用计算机弹小猪佩奇,【绘本时间】小猪佩奇之弹弹球
- vue run dev报错 缺少package.json文件、missing dev 命令 解决办法
- Hadoop 图像小文件查重方法
- oracle bpm 表单,Oracle BPM 安全认证
- LeetCode刷题总结01--哈希表问题
- n1盒子救砖_N1盒子不拆机救砖,10分钟从ArmBian刷回原厂固件(站内首发)
- Qt 设置Widget背景图片并实现透明度的三种方式
- chrome 谷歌浏览器升级 rem布局问题
- xps测试常见问题及解答(二)
- mysql安装mysql-5.7.35-1.el7.x86_64.rpm-bundle.tar,问题及其他ip访问mysql