4、ES6邂逅
3.1、什么是ECMA
ECMA(European Computer Manufacturers Association)中文名为欧洲计算机制造商协会,这个组织的目标是评估、开发和认可电信和计算机标准。1
994年后该组织改名为Ecma国际。
3.2、什么是ECMAScript
ECMAScript 是由Ecma国际通过ECMA-262标准化的脚本程序设计语言。
3.3、什么是ECMA-262
Ecma国际制定了许多标准,而ECMA-262只是其中的一个,所有标准列表查看
http://www.ecma-international.org/publications/standards/Standard.htm
3.4、ECMA262历史
ECMA-262(ECMAScript)历史版本查看网址
第1版 | 1997年 | 制定了语言的基本语法 |
---|---|---|
第2版 | 1998年 | 较小改动 |
第3版 | 1999年 | 引入正则、异常处理、格式化输出等。IE开始支持 |
第4版 | 2007年 | 过于激进,未发布 |
第5版 | 2009年 | 引入严格模式、JSON,扩展对象、数组、原型、字符串、日期方法 |
第6版 | 2015年 | 模块化、面向对象语法、Promise、箭头函数、let、const、数组解构赋值等等 |
第7版 | 2016年 | 幂运算符、数组扩展、Async/await关键字 |
第8版 | 2017年 | Async/await、字符串扩展 |
第9版 | 2018年 | 对象解构赋值、正则扩展 |
第10版 | 2019年 | 扩展对象、数组方法 |
ES.next | 动态指向下一个版本 |
注:从ES6开始,每年发布一个版本,版本号比年份最后一位大1
3.5、谁在维护ECMA262
TC39(Technical Committee 39)是推进 ECMAScript 发展的委员会。其会员都是公司(其中主要是浏览器厂商,有苹果、谷歌、微软、因特尔等)。TC39 定期召开会议,会议由会员公司的代表与特邀专家出席
3.6、为什么要学习ES6
ES6的版本变动内容最多,具有里程碑意义
ES6加入许多新的语法特性,编程实现更简单、高效
ES6是前端发展趋势,就业必备技能
3.8、ES6兼容性
https://compat-table.github.io/compat-table/es6/ 可查看兼容性
3.9、ES6的Let关键字
let关键字用来声明变量,使用let声明的变量有几个特点:
- 不允许重复声明
- 块儿级作用域
- 不存在变量提升
应用场景:以后声明变量使用let就对了
代码实战
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>let</title>
</head>
<body>
<script>
//let 声明变量
let a; //字母数字下划线, 首字母不能为数字, 严格区分大小写, 不能使用关键字 驼峰
let b = 100;
let c,d,e;
let f=100,g=200,h=300;
//let 声明特点
//1. 不允许重复声明
// let star = '罗志祥';
// let star = '小猪';
//2. 块儿级作用域 if(){} else {} for(){} {} function(){}
// if(true){
// let girlFriend = '周扬青';
// }
// console.log(girlFriend);
//3. 不存在变量提升
// console.log(song);
// let song = '狐狸精';
//4. 不影响作用域链
// function fn(){
// let dance = '精武门';
// function b(){
// console.log(dance);
// }
// b();
// }
// fn();
</script>
</body>
</html>
3.1、let实践案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>点击 DIV 换色</title>
<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>
//获取元素对象
let items = document.querySelectorAll('.item');
//用this实现
// for(var i=0;i<items.length;i++){
// //绑定事件
// items[i].onclick = function(){
// //
// this.style.background = 'pink';
// }
// }
//遍历并绑定事件
// for(let i=0;i<items.length;i++){
// //绑定事件
// items[i].onclick = function(){
// //
// items[i].style.background = 'pink';
// }
// }
// ES5 模拟实现
for(var i=0;i<items.length;i++){
(function(i){
//绑定事件
items[i].onclick = function(){
//
items[i].style.background = 'pink';
}
})(i)
}
</script>
</body>
</html>
3.4、ES6的const关键字
const 关键字用来声明常量,const声明有以下特点
-
声明一定要赋初始值
-
不允许重复声明
-
值不允许修改
-
块儿级作用域
注意:对象属性修改和数组元素变化不会出发const错误
应用场景:声明对象类型使用const,非对象类型声明选择let
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>const 定义常量</title>
</head>
<body>
<script>
//const 用来声明一个常量(值不变) let a
//0. 格式
// const a = 100;
//1. 声明的时候一定要赋初始值
const PLAYER = 'UZI';
//2. 常量的名称一般为 『大写』 潜规则
const RESOLVED = 'resolved';
//3. 不能修改常量的值
// PLAYER = '小狗';
//4. 不允许重复声明
// const PLAYER = 'abc';
//5. 块儿级作用域
// {
// const A = 100;
// }
// console.log(A);
//6. 关于数组和对象的元素的修改
// const TEAM = ['UZI','MLXG','LETME'];
// TEAM.push('XIYE');
// console.log(TEAM);
// const BIN = {
// name: 'BIN'
// }
// BIN.name = '阿斌';
// console.log(BIN);
</script>
</body>
</html>
3.5、ES6变量的结构赋值
ES6允许按照一定模式从数组和对象中提取值,对变量进行赋值,这被称为解构赋值。
注意:频繁使用对象方法、数组元素,就可以使用解构赋值形式
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>变量的解构赋值</title>
</head>
<body>
<script>
//解构赋值
// const arr = ['宋小宝','刘能','赵四','小沈阳'];
// let [song, liu, zhao, xiao] = arr;
// console.log(song, liu, zhao, xiao);
//对象解构赋值
const star = {
name: '于谦',
tags: ['抽烟','喝酒','烫头'],
say: function(){
console.log('我可以说相声');
}
};
let {name, tags:[chou,he,tang], say} = star;
// console.log(name);
// console.log(tags);
// console.log(say);
console.log(chou)
console.log(he)
console.log(tang)
</script>
</body>
</html>
3.6、模板字符串
模板字符串(template string)是增强版的字符串,用反引号(`)标识,
特点:
- 字符串中可以出现换行符
- 可以使用 ${xxx} 形式输出变量
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>模板字符串</title>
</head>
<body>
<script>
//1. 直接使用换行符
let str = `<ul>
<li>沈腾</li>
<li>马丽</li>
<li>艾伦</li>
<li>魏翔</li>
</ul>`;
//2. 字符串中进行变量拼接
let star = '魏翔';
let str2 = `我特别喜欢 ${star}, 搞笑风格诡异`;
console.log(str2);
</script>
</body>
</html>
3.7、简化对象写法
ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法。这样的书写更加简洁。
注意:对象简写形式简化了代码,所以以后用简写就对了
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>简化对象写法</title>
</head>
<body>
<script>
let name = '茂昌';
let pos = '邯郸';
let change = function(){
console.log('改变');
}
//简写前
const renOne = {
name:name,
pos:pos,
change:change,
improve:function(){
console.log('提升');
}
}
//简写后
const renTwo = {
name,
pos,
change,
improve(){
console.log('提升');
}
}
console.log(renOne)
console.log(renTwo)
</script>
</body>
</html>
3.8、箭头函数
ES6 允许使用「箭头」(=>)定义函数。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>箭头函数</title>
</head>
<body>
<script>
// ES6 允许使用「箭头」(=>)定义函数。
//1. 声明格式
// let add = (a,b,c) => {
// let result = a + b + c;
// return result;
// };
//2. 函数调用
// console.log(add(1,2,3));
// console.log(add.call({}, 1,2,3));
// console.log(add.apply({}, [1,2,3]));
// 箭头函数特点
// 1. this 的值是静态的. (指向声明时所在作用域下this的值)
// let getName2 = () => {
// console.log(this);
// }
// getName2.call({}); 外层作用域下的this值
// 2. 不能作为构造函数使用
// const Person = () => {}
// let me = new Person();
// 3. 不能使用 arguments
// const fn = () => {
// console.log(arguments);
// }
// fn(1,3,5,8,10);
// 4. 箭头函数简写
// 一 不写小括号, 当形参有且只有一个的时候
// 二 不写花括号, 当代码体只有一条语句的时候, 并且语句的执行结果为函数返回值的 (如果不写花括号的话, return 也不能写)
// let pow = num => num * num * num;
let rand = (m,n) => Math.ceil(Math.random() * (n-m+1)) + m-1;
// console.log(pow(9));
console.log(rand(1,100));
</script>
</body>
</html>
箭头函数的注意点:
-
箭头函数this指向声明时所在作用域下 this 的值
-
箭头函数不能作为构造函数实例化
-
箭头函数内没有arguments
-
如果形参只有一个,则小括号可以省略
-
函数体如果只有一条语句,则花括号可以省略,函数的返回值为该条语句的执行结果
3.9、箭头函数的最佳实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>箭头函数实践</title>
<style>
div {
width: 200px;
height: 200px;
background: #58a;
}
</style>
</head>
<body>
<div id="ad"></div>
<script>
//需求-1 点击 div 2s 后颜色变成「粉色」
const ad = document.getElementById('ad');
//绑定事件
ad.onclick = function(){
//保存 this 的值 that self _this
// let that = this
// setTimeout(function(){
// that.style.background = 'pink';
// }, 2000);
setTimeout(() => {
this.style.background = 'pink';
}, 2000)
}
//需求-2 从数组中返回偶数的元素
const arr = [1,2,31,2,321,41,24,12,51,24,12,43,145,1,51,5,43,5,43,6,436];
//遍历 filter 过滤
// 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的值是相关的, 则不能使用箭头函数
//1. 事件的回调
// ad.onclick = () => {
// console.log(this);
// }
//2. 对象的方法
// let f = () => {
// console.log(this);
// };
// var obj = {
// run: function(){
// console.log(this);
// },
// run2: f
// }
// // obj.run();
// obj.run2();
//如果回调与 this 是无关的
//1. 定时器
//2. 数组方法回调 filter forEach map
</script>
</body>
</html>
3.1、函数参数默认值
注意: 参数直接设置默认值 具有默认值的参数, 位置一般要靠后(潜规则)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>函数参数默认值</title>
</head>
<body>
<script>
//ES6 允许给函数参数赋值初始值
//1. 参数直接设置默认值 具有默认值的参数, 位置一般要靠后(潜规则) ---很重要
function add(a,b=10,c){
console.log(a + b + c);
}
// add(1,2,4);
// add(1,2);
//2. 与解构赋值结合使用 结构赋值的形式先后顺序不影响
function connect({host="127.0.0.1", port, pass, dbname}){
console.log(host);
console.log(port);
console.log(pass);
console.log(dbname);
}
connect({
port: 27017,
pass: 'root',
dbname: 'project'
});
</script>
</body>
</html>
3.2、rest参数
主要是用来替代arguments获取实参的
注意事项,出现a,b,…args写到最后,
什么时候用rest参数:出现不定个数参数的函数比如求最大值最小值,你也不知道传递多少个参数进来,那我们就用rest参数来接收
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>rest参数</title>
</head>
<body>
<script>
//arguments
function main(...args){
//1. 使用 arguments 获取实参
console.log(arguments); //对象
//2. rest 参数
console.log(args); //数组
}
main(1,5,10,20,25);// 1,5,10,20,25 => ...[1,5,10,20,25] => 1,5,10,20,25
//2. 如果有多个参数,rest参数必须放到最后
// function fn(a,b,...args){
// console.log(a);
// console.log(b);
// console.log(args);
// }
// fn(1,2,3,4,5,6,7);
</script>
</body>
</html>
3.3、spread扩展运算符
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>扩展运算符 ****</title>
</head>
<body>
<script>
//数组的展开
const arr = ['王源','易烊千玺','王俊凯'];
function fn(){
console.log(arguments);
}
fn(...arr);// ...arr => ...['王源','易烊千玺','王俊凯'] => '王源','易烊千玺','王俊凯'
//fn('王源','易烊千玺','王俊凯');
//对象的展开 ...skillOne => q:'天音波'
// const skillOne = {
// q: '天音波',
// f:'闪现'
// };
// const skillTwo = {
// w: '金钟罩'
// };
// const skillThree = {
// e: '天雷破'
// };
// const skillFour = {
// r: '猛龙摆尾',
// q: 'xxx'
// };
//把对象的属性加入到一个新对象中
//const mangseng = {...skillOne, ...skillTwo, ...skillThree, ...skillFour};
// console.log(mangseng);
</script>
</body>
</html>
3.4、spread扩展运算符应用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>扩展运算符应用</title>
</head>
<body>
<div></div>
<div></div>
<div></div>
<script>
//1. 数组的合并
// const kuaizi = ['肖央','王太利'];
// const chuanqi = ['曾毅','玲花'];
// const zuhe = [...kuaizi, ...chuanqi];
// console.log(zuhe);
//2. 新数组克隆
// const jinhua = ['e','g','m'];//
// const s = [...jinhua,'x','y','z'];
// console.log(s);
//3. 将伪数组转为真正的数组
const divs = document.querySelectorAll('div');
//
const result = [...divs];
console.log(result);
</script>
</body>
</html>
3.5、symbol
ES6中的数据类型总共有七中
1、boolean(布尔型)2、null(空类型)3、undefined(未赋值类型)
4、number(数值类型)5、string(字符串类型)6、symbol(独一无二类型)7、object(对象类型)。
ES6 引入了一种新的原始数据类型Symbol,表示独一无二的值。它是 JavaScript 语言的第七种数据类型,是一种类似于字符串的数据类型。
Symbol特点
- Symbol的值是唯一的,用来解决命名冲突的问题
- Symbol值不能与其他数据进行运算
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>symbol</title>
</head>
<body>
<script>
//ES6 引入了一种新的原始数据类型 Symbol,表示独一无二的值
//1. 创建 Symbol
let s1 = Symbol();
console.log(s1, typeof s1);
//2. 创建 Symbol
// let s2 = Symbol('品牌');
// let s3 = Symbol('品牌');
// console.log(s2 === s3);
//3. 创建 Symbol ----函数对象
let s4 = Symbol.for('200826');
let s5 = Symbol.for('200826');
console.log(s4 === s5);
// symbol 不能与其他类型数据进行运算
// const result = s1 + 123;
</script>
</body>
</html>
3.6、symbol的使用场景
注意:Symbol类型唯一合理的用法是用变量存储 symbol的值,然后使用存储的值创建对象属性
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Symbol 创建对象属性</title>
</head>
<body>
<script>
//向对象中添加方法 up down
let method = {
up: Symbol(),
down: Symbol()
}
let str = 'run';
//未知的对象,直接添加方法会有风险,因为可能已经存在了对应的方法
//直接添加会造成属性的冲突和覆盖
let game = {
name:'俄罗斯方块' ,
up: function(){
},
//内部添加方法
[str]: function(){
},
//内部添加方法用up
[method.up]: function(){
console.log('UP UP UP');
}
};
// console.log(game);
game[method.up]();
//添加 up 方法
// game[method.up] = function(){
// console.log('向上移动');
// }
// game[method.up]();
</script>
</body>
</html>
3.7、Symbol内置属性
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Symbol内置属性</title>
</head>
<body>
<script>
// Symbol.replace
let obj = {
[Symbol.replace]: function(){
console.log('我被replace方法调用了');
}
}
//声明字符串
let str = 'i love you';
//调用 replace 方法
let result = str.replace(obj, 'xxx');
</script>
</body>
</html>
被动调用的、我没有进行手动的触发
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 | 创建衍生对象时,会使用该属性 |
3.8、迭代器
迭代器(Iterator)是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署 Iterator 接口,就可以完成遍历操作。
- ES6创造了一种新的遍历命令for…of循环,Iterator接口主要供for…of消费
- 原生具备iterator接口的数据(可用for of遍历)
- Array
- Arguments
- Set
- Map
- String
- TypedArray
- NodeList
- 工作原理
- 创建一个指针对象,指向当前数据结构的起始位置
- 第一次调用对象的next方法,指针自动指向数据结构的第一个成员
- 接下来不断调用next方法,指针一直往后移动,直到指向最后一个成员
- 每调用next方法返回一个包含value和done属性的对象
注意: 需要自定义遍历数据的时候,要想到迭代器。
ctrl+shift+i 打开控制台
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>迭代器</title>
</head>
<body>
<script>
const arr = ['刘德华','黎明','郭富城','张学友'];
//for...of 遍历
for(let v of arr) {
console.log(v);
}
//得到 iterator
const iterator = arr[Symbol.iterator]();
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
// {value: '', done: true}
// for(let i in arr){
// console.log(i);
// }
</script>
</body>
</html>
for of 和for in的区别 前置拿到的是值,后者拿到的是下标
3.9、迭代器自定义遍历数据
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>自定义遍历数据</title>
</head>
<body>
<script>
const team = {
name: '终极一班',
members: [
'xiaoming',
'xiaoning',
'xiaotian',
'knight'
],
//添加 Symbol.iterator
[Symbol.iterator]: function(){
let index = 0;
return {
next: () => {
//声明对象
const result = {value: this.members[index], done: false};
//判断下标 修改 『done』 属性的值
if(index >= this.members.length){
result.done = true;
}
//下标自增
index++;
//返回结果
return result;
}
}
}
}
//需求
for(let v of team){
console.log(v);
}
//可以
for(let v of team.members){}
//可以--为啥要费劲的去实现这个需求 -->面向对象编程思想--满足
team.members.forEach();
</script>
</body>
</html>
4.1、set集合
ES6 提供了新的数据结构 Set(集合)。它类似于数组,但成员的值都是唯一的,集合实现了iterator接口,可以使用『扩展运算符』和『for…of…』进行遍历,
集合的属性和方法:
- size 返回集合的元素个数
- add 增加一个新元素,返回当前集合
- delete 删除元素,返回boolean 值
- has 检测集合中是否包含某个元素,返回boolean值
- clear 清空集合,返回undefined
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>集合</title>
</head>
<body>
<script>
//声明集合
// const s = new Set();
const s2 = new Set([1,5,9,13,17,1,5]);
//1. 元素个数
// console.log(s2.size);
//2. 添加
// s2.add(21);
//3. 删除
// s2.delete(5);
//4. 检测集合中是否包含某个元素 has 有
// console.log(s2.has(90));
//5. clear 清空
// s2.clear();
// console.log(s2);
//6. for...of 遍历
// for(let v of s2){
// console.log(v);
// }
</script>
</body>
</html>
4.2、set集合实战
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>实践</title>
</head>
<body>
<script>
//1. 数组去重
const arr = ['大事儿','小事儿','好事儿','坏事儿','小事儿'];
//集合
// const s = new Set(arr);
// const result = [...s];
// console.log(result);
//2. 交集
const arr1 = [1,2,3,4,5,1,2];
const arr2 = [3,4,5,4,5,6];
// const result = [...new Set(arr1)].filter(item => {
// return (new Set(arr2)).has(item);
// });
// console.log(result);
//3. 并集
// const result = [...new Set([...new Set(arr1),...new Set(arr2)])];
//4. 差集
const result = [...new Set(arr1)].filter(item => {
return !(new Set(arr2)).has(item);
});
console.log(result);
</script>
</body>
</html>
4.3、Map集合
ES6 提供了 Map 数据结构。它类似于对象,也是键值对的集合。但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。Map也实现了iterator接口,所以可以使用『扩展运算符』和『for…of…』进行遍历。
Map的属性和方法:
- size 返回Map的元素个数
- set 增加一个新元素,返回当前Map
- get 返回键名对象的键值
- has 检测Map中是否包含某个元素,返回boolean值
- clear 清空集合,返回undefined
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Map</title>
</head>
<body>
<script>
//缓存--->比如搜索栏存第一次的推荐搜索数据
//声明 Map m.name = 'xiaohua';
const m = new Map();
//添加元素
let key = {};
m.set('mei', '小橙子');
m.set(key, 'atguigu');
//获取元素
// console.log(m.get('mei'));
// console.log(m.get(key));
//删除元素
// m.delete('mei');
//检测
// console.log(m.has('meix'));
//元素个数
// console.log(m.size);
//清空
// m.clear();
// console.log(m);
</script>
</body>
</html>
4.4、class介绍与类创建
ES6 提供了更接近传统语言的写法,引入了 Class(类)这个概念,作为对象的模板。通过class关键字,可以定义类。基本上,ES6 的class可以看作只是一个语法糖,它的绝大部分功能,ES5 都可以做到,新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>对象声明</title>
</head>
<body>
<script>
//创建对象的方式 new Object {} 工厂函数 构造函数 Object.create
// function Phone(brand, price){
// this.brand = brand;
// this.price = price;
// }
// //添加方法
// Phone.prototype.call = function(someone){
// console.log(`我可以给 ${someone} 打电话`);
// }
// Phone.prototype.sendMessage = function(someone){
// console.log(`我可以给 ${someone} 发送短信`);
// }
// //实例化对象
// const nokia = new Phone('诺基亚', 223);
//语法
class Phone {
//构造方法--名字必须为这个
constructor(brand, price){
this.brand = brand;
this.price = price;
}
//方法
call(someone){
console.log(`我可以给 ${someone} 打电话`);
}
sendMessage(someone){
console.log(`我可以给 ${someone} 发送短信`);
}
}
const jinli = new Phone('金立', 599);
console.log(jinli);
//1.构造方法不是必须的
class A{
//2. 构造方法只能有一个
constructor(){}
constructor(){}
}
let a = new A();
console.log(a);
</script>
</body>
</html>
4.5、对象的静态属性和方法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>静态成员</title>
</head>
<body>
<script>
//
// function Phone(brand){
// //为实例对象添加属性
// this.brand = brand;
// }
// //为函数对象添加属性
// Phone.name = '手机';//又称之为 静态成员
// Phone.change = function(){
// console.log('改变了世界');
// }
// //
// let nokia = new Phone('诺基亚');
// console.log(nokia);
// console.dir(Phone);
class Phone{
//static 静态的
static name = '手机';
static change(){
console.log("我改变了世界");
}
}
console.log(Phone.name);
Phone.change();
</script>
</body>
</html>
4.6、ES5中如何实现继承
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>对象继承</title>
</head>
<body>
<script>
//父类
function Phone(brand, price){
this.brand = brand;
this.price = price;
}
//添加原型方法
Phone.prototype.call = function(someone){
console.log(`我可以给 ${someone} 打电话`);
}
//添加原型方法
Phone.prototype.sendMessage = function(someone){
console.log(`我可以给 ${someone} 发送短信`);
}
//小手机
function SmartPhone(brand, price, storage, pixel){
//调用父类的函数 属性的初始化
Phone.call(this, brand, price);
//初始化
this.storage = storage;
this.pixel = pixel;
}
//子类的prototype应该等于父类的示例
SmartPhone.prototype = new Phone;
//添加子类自己的构造方法
SmartPhone.prototype.constructor = SmartPhone;
//添加子类特有的方法
SmartPhone.prototype.playGame = function(){
console.log('我可以用来玩游戏');
}
SmartPhone.prototype.takePhoto = function(){
console.log('可以拍照');
}
//实例化
const mate4 = new SmartPhone('华为', 7000, '256G','2000w');
console.log(mate4);
</script>
</body>
</html>
4.7、ES6实现对象继承
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>对象继承</title>
</head>
<body>
<script>
class Phone {
//构造方法
constructor(brand, price){
this.brand = brand;
this.price = price;
}
//方法
call(someone){
console.log(`我可以给 ${someone} 打电话`);
}
sendMessage(someone){
console.log(`我可以给 ${someone} 发送短信`);
}
}
//子类 extends 继承 多态
class SmartPhone extends Phone{
//构造方法
constructor(brand, price, storage, pixel){
//调用父类的构造方法 属性初始化
super(brand, price);//super 超级
this.storage = storage;
this.pixel = pixel;
}
//子类对象的方法
playGame(){
console.log('我可以用来玩游戏');
}
takePhoto(){
console.log('可以拍照');
}
}
//实例化对象
const onePlus = new SmartPhone('小米10', 4299, '128G','一个亿');
console.log(onePlus);
// onePlus.call('孙俪');
</script>
</body>
</html>
4.8、ES6对象的get 和 set方法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>get 和 set </title>
</head>
<body>
<script>
class Phone{
get price(){
// console.log('我被获取了');
return 2999;
}
set price(v){
this.jiage = v;
}
static get size(){
return '5.5inch';
}
static set size(value){
this.chicun = value;
}
}
let chuizi = new Phone();
//属性的获取
// console.log(chuizi.price);
//属性的设置
// chuizi.price = 1599;
//属性的获取
// let res = Phone.size;
// console.log(res);
//静态属性的设置
Phone.size = '6inch';
console.dir(Phone);
</script>
</body>
</html>
4.9、ES6的数值扩展
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>数值扩展</title>
</head>
<body>
<script>
//1. 二进制和八进制 4 (16) 8(256) 16(65536)
// let n = 0b1111;//
// let n2 = 0o666;
// let n3 = 1024;// 顶 赞
// let n4 = 0xff;
// console.log(n4);
//2. Number.isFinite 检测一个数值是否为有限数
// console.log(Number.isFinite(10));
// console.log(Number.isFinite(Math.PI));
// console.log(Number.isFinite(1/0));
//3. Number.isNaN 检测一个数值是否为 NaN isNaN
// console.log(Number.isNaN(NaN));
//4. Number.parseInt 字符串转整数
// console.log(Number.parseInt('5211314love'));
// console.log(Number('5211314love'));
//5. Math.trunc 将数字的小数部分抹掉
// console.log(Math.trunc(3.1415926));
//6. Number.isInteger 判断一个数是否为整数 is 是否 integer 整型
// console.log(Number.isInteger(3.2));
// console.log(Number.isInteger(3));
//7. 幂运算 (ES7) Math.pow()
console.log(3 ** 10);
</script>
</body>
</html>
4.1、ES6的对象拓展
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>对象扩展</title>
</head>
<body>
<script>
//1. 判断两个值是否完全相等 === Object.is
// let n = 100;
// let n2 = 200;
// console.log(Object.is(n, n2));
// console.log(Object.is(NaN, NaN));// NaN === NaN
//2. Object.assign 对象的合并
// const A = {
// name: 'lsy'
// }
// const B = {
// pos: ["北京",'上海','深圳'],
// name: '后茂昌'
// }
// const C = {
// name: 'hmc'
// }
// const res = Object.assign(A, B, C);
// console.log(res === A);
// console.log(A);
//3. 直接修改 __proto__ 设置原型
// const A = {
// name: '父级'
// }
// const B = {
// test: '测试'
// }
// B.__proto__ = A;
// console.log(B);
</script>
</body>
</html>
4.2、ES6数据的浅拷贝
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>浅拷贝</title>
</head>
<body>
<script>
//拷贝 就是 复制 对象和数组
//1. 直接复制
// let arr = [1,2,3,4];
// const newArr = arr;
// //测试
// newArr[0] = 521;
// console.log(arr);
// console.log(newArr);
//2. 数组
let arr = [{name:'atguigu'},2,3,4];
// 1> concat
// let newArr = [].concat(arr);
// newArr[0].name = '尚硅谷';
// console.log(arr)
// console.log(newArr)
// 2> slice
// let newArr = arr.slice(0);
// newArr[0].name = '尚硅谷';
// console.log(arr)
// console.log(newArr)
// 3> 扩展运算符
// let newArr = [...arr];
// newArr[0].name = '尚硅谷';
// console.log(arr)
// console.log(newArr)
//3. 对象
//使用 assign 方法创建对象 (assign 对象的合并)
const school = {
name: "尚硅谷",
pos: ['北京','上海','深圳']
}
const newSchool = Object.assign({}, school);
// newSchool.name = 'atguigu';
newSchool.pos[0] = 'beijing';
console.log(school);
console.log(newSchool);
</script>
</body>
</html>
4.3、深拷贝-JSON
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>深拷贝-JSON</title>
</head>
<body>
<script>
//JSON 实现深拷贝
// * stringify 将 JS 对象转化为 JSON 格式的字符串
// * parse 将 JSON 格式的字符串转化为 JS 对象
//缺陷: 不能复制方法
const school = {
name: '朱岗子',
pos: ['北京','上海','深圳'],
founder: {
name: 'lsy'
},
change: function(){
console.log('改变');
}
}
//将 对象转为 JSON 格式的字符串
let str = JSON.stringify(school);
//将对象转为JS对象
let newSchool = JSON.parse(str);
//测试
newSchool.pos[0] = 'beijing';
console.log(school);
console.log(newSchool);
// console.log(str);
// console.log(typeof str);
</script>
</body>
</html>
4.4、递归深拷贝的原理
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>递归实现深拷贝 - 思路</title>
</head>
<body>
<script>
const school = {
name: '尚硅谷',
pos: ['北京','上海','深圳'],
founder:
{
name: '刚哥'
},
change: function(){
console.log('改变');
}
}
//创建数据容器
const newSchool = {};
//name
newSchool.name = school.name;
//pos
newSchool.pos = school.pos;
newSchool.pos = [];
newSchool.pos[0] = school.pos[0];
newSchool.pos[1] = school.pos[1];
newSchool.pos[2] = school.pos[2];
//founder
newSchool.founder = {};
newSchool.founder.name = school.founder.name;
//方法
newSchool.change = school.change.bind(newSchool);
newSchool.pos[0] = 'beijing';
console.log(school);
console.log(newSchool);
</script>
</body>
</html>
4.5、封装实现递归深拷贝
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>递归深拷贝实现</title>
</head>
<body>
<script>
//封装一个函数
function deepClone(data){
//创建一个容器 typeof
// console.log(typeof data);
let container;
//判断
let type = getDataType(data);// Object Array
if(type === 'Object'){
container = {};
}
if(type === 'Array'){
container = [];
}
//遍历数据 for...in
for(let i in data){
//获取键值的类型
let type = getDataType(data[i]);// Array
//判断
if(type === 'Array' || type==='Object'){
//???? 递归调用 deepClone 即可
container[i] = deepClone(data[i]);
}else{
//如果键值为非引用类型数据 则『直接复制』
container[i] = data[i];
}
}
//container
return container;
}
//待克隆的数据
const school = {
name: '尚硅谷',
pos: ['北京','上海','深圳'],
founder: {
name: '刚哥'
},
change: function(){
console.log('改变');
}
}
//调用函数完成深拷贝
const newSchool = deepClone(school);
newSchool.pos[0] = 'beijing';
console.log(school);
console.log(newSchool);
//封装一个函数 用来获取数据的类型
function getDataType(data){
return Object.prototype.toString.call(data).slice(8, -1);
}
</script>
</body>
</html>
4.6、ES11的可选链操作符号
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>可选链操作符</title>
</head>
<body>
<script>
//?.
function main(config){
// const dbHost=config&&config.db&&config.db.host;
const dbHost=config?.db?.host; //避免做层层判断
console.log(dbHost);
}
main({
db:{
host:'127.0.0.1',
username:"root"
},
caches:{
host:'127.0.0.1',
username:"admin"
}
}
)
</script>
</body>
</html>
世之奇伟瑰丽,非常之观,常在于险远,只有难才能不断突破进步