1、什么是 ECMAScript
ECMAScript 是由 Ecma 国际通过 ECMA-262 标准化的脚本程序设计语言。
从第 6 版开始,发生了里程碑的改动,并保持着每年迭代一个版本的习惯。
ES6=2015年,ES7=2016年,ES8=2017年,ES9=2018年,ES10=2019年,ES11=2020年以此类推。
1.1 为什么要学习 ES6
⚫
ES6
的版本变动内容最多,具有里程碑意义
⚫
ES6
加入许多新的语法特性,编程实现更简单、高效
2、ECMASript 6 新特性
2.1.let 关键字
let
关键字用来声明变量,使用
let
声明的变量有几个特点:
1)
不允许重复声明
2)
块儿级作用域
3)
不存在变量提升
4)
不影响作用域链
应用场景:以后声明变量使用
let
就对了
<script>
//声明变量
let a;
let b, c, d;
let e = 100;
let f = 521, g = 'iloveyou', h = [];
//1. 变量不能重复声明
//let star = '罗志祥';
//let star = '小猪';
//console.log("Uncaught SyntaxError: Identifier 'star' has already been declared");
//2. 块儿级作用域 全局, 函数, eval
//类似块级作用于的还有:if else while for
{
let girl = '周扬青';
console.log(girl);//可以正确输出
}
//console.log(girl);
//console.log("Uncaught ReferenceError: girl is not defined at");
//3. 不存在变量提升
// console.log(song);
// let song = '爱唱歌';
// console.log("Uncaught ReferenceError: Cannot a***ess 'song' before initialization");
//4. 不影响作用域链
{
let school = '清华大学';
function fn() {
console.log(school);
}
fn();
}
</script>
2.2. const 关键字
const
关键字用来声明常量,
const
声明有以下特点:
1)
声明必须赋初始值
2)
标识符一般为大写
3)
不允许重复声明
4)
值不允许修改
5)
块儿级作用域
注意
:
对象属性修改和数组元素变化不会出发
const
错误
应用场景:声明对象类型使用
const
,非对象类型声明选择
let
<script>
//声明常量
const SCHOOL = '清华大学';
//1. 一定要赋初始值
//const A;
//console.log("Uncaught SyntaxError: Missing initializer in const declaration");
//2. 一般常量使用大写(潜规则)
const a = 100;
//3. 常量的值不能修改
//SCHOOL = '北京大学';
//console.log("Uncaught TypeError: Assignment to constant variable");
//4. 块儿级作用域
// {
// const PLAYER = '乔丹';
// }
// console.log(PLAYER);
// console.log("Uncaught ReferenceError: PLAYER is not defined at");
//5. 对于数组和对象的元素修改, 不算做对常量的修改, 不会报错
const BAT = ['百度', '阿里巴巴', '腾讯'];
BAT.push('字节跳动');
console.log(BAT);//输出:['百度', '阿里巴巴', '腾讯', '字节跳动']
</script>
2.3.变量的解构赋值
ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构赋值。
<script>
//ES6 允许按照一定模式从数组和对象中提取值,对变量进行赋值,这被称为解构赋值。
//1. 数组的结构
const SCHOOL = ['清华大学', '北京大学'];
let [qinghua, beida] = SCHOOL;
console.log(qinghua);//输出清华大学
console.log(beida);//输出北京大学
//2. 对象的解构
const student = {
name: "小明",
age: 18,
like: function () {
console.log("我喜欢打篮球");
}
}
let { name, age, like } = student;
console.log(name);//输出小明
console.log(age);//输出18
console.log(like);//输出:ƒ () {console.log("我喜欢打篮球");}
like();//输出:我喜欢打篮球
</script>
注意:频繁使用对象方法、数组元素,就可以使用解构赋值形式
2.4.模板字符串
模板字符串(
template string
)是增强版的字符串,用反引号(`
)标识,特点:
1)
字符串中可以出现换行符
2)
可以使用
${xxx}
形式输出变量
<script>
// ES6 引入新的声明字符串的方式 『``』
//1. 声明
let str = `这是一个字符串`;
console.log(str, typeof str);//输出:这是一个字符串 string
//2. 内容中可以直接出现换行符
let SCHOOL = `<ul>
<li>清华大学</li>
<li>北京大学</li>
</ul>`;
//3.变量拼接
let boy = `马云`;
let word = `${boy}说让天下没有难做的生意!`;
console.log(word);//输出:马云说让天下没有难做的生意!
</script>
注意:当遇到字符串与变量拼接的情况使用模板字符串
2.5.简化对象写法
ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法。这样的书写更加简洁。
<script>
//ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法。
//这样的书写更加简洁
let name = '马云';
let word = function () {
console.log('让天下没有难做的生意');
}
const obj = {
name,
word,
say() {
console.log("幸福是奋斗出来的!");
}
}
console.log(name);//输出:马云
console.log(word);//输出:ƒ () { console.log('让天下没有难做的生意'); }
console.log(obj);//输出:{name: '马云', word: ƒ, say: ƒ}
</script>
注意:对象简写形式简化了代码,所以以后用简写就对了
2.6.箭头函数
ES6
允许使用「箭头」(
=>
)定义函数。
箭头函数的注意点
:
1)
如果形参只有一个,则小括号可以省略
2) 函数体如果只有一条语句,则花括号可以省略,函数的返回值为该条语句的执行结果
3)
箭头函数
this
指向声明时所在作用域下
this
的值
4)
箭头函数不能作为构造函数实例化
5)
不能使用
arguments
<script>
// ES6 允许使用「箭头」(=>)定义函数。
//声明一个函数
let fn = (a, b) => {
return a + b;
}
//调用函数
let result = fn(3, 5);
console.log(result);//输出:8
//1. this 是静态的. this 始终指向函数声明时所在作用域下的 this 的值
function getName() {
console.log(this.name);
}
let getName2 = () => {
console.log(this.name);
}
//设置 window 对象的 name 属性
window.name = '清华大学';
const school = {
name: "北京大学"
}
//直接调用
getName();//输出:清华大学(作用域是 window)
getName2();//输出:清华大学(作用域是 window)
//call 方法调用
getName.call(school);//输出:北京大学
getName2.call(school);//输出:清华大学(作用域是 window)
//2. 不能作为构造实例化对象
// let Person = (name, age) => {
// this.name = name;
// this.age = age;
// }
// let me = new Person('张三', 18);
// console.log(me);//输出错误信息:Person is not a constructor at
//3. 不能使用 arguments 变量
// let fn = () => {
// console.log(arguments);
// }
// fn(1, 2, 3);//输出错误信息:Uncaught SyntaxError: Identifier 'fn' has already been declared
//4. 箭头函数的简写
//1) 省略小括号, 当形参有且只有一个的时候
let add = n => {
return n + n;
}
console.log(add(6));//输出:12
//2) 省略花括号, 当代码体只有一条语句的时候, 此时 return 必须省略
// 而且语句的执行结果就是函数的返回值
let pow = n => n * n;
console.log(pow(9));//输出:81
</script>
注意:箭头函数不会更改 this 指向,用来指定回调函数会非常合适
箭头函数适合与 this 无关的回调,比如:定时器、数组的方法回调
箭头函数不适合与 this 有关的回调有:事件回调、对象的方法
2.7. rest 参数
ES6
引入
rest
参数,用于获取函数的实参,用来代替
arguments
<body>
<div>我是div1</div>
<div>我是div2</div>
<div>我是div3</div>
<script>
// ES6 引入 rest 参数,用于获取函数的实参,用来代替 arguments
// rest 参数
function getUserName(...args) {
console.log(args);
}
getUserName('刘亦菲', '关之琳', '刘雯雯');//输出:['刘亦菲', '关之琳', '刘雯雯']
// rest 参数必须要放到参数最后
function fn(a, b, ...args) {
console.log(a);
console.log(b);
console.log(args);
}
fn(1, 2, 3, 4, 5, 6);//输出:1、2、 [3, 4, 5, 6]
//1. 数组的合并
const university = ["清华大学", "北京大学"];
const foreign = ["哈佛大学", "牛津大学"];
const concat1 = university.concat(foreign);
console.log("concat1=" + concat1);//输出:concat1=清华大学,北京大学,哈佛大学,牛津大学
const concat2 = [...university, ...foreign];
console.log("concat2=" + concat2);//输出:concat2=清华大学,北京大学,哈佛大学,牛津大学
//2. 数组的克隆
const student = ["小明", "小花", "小聪"];
const copy1 = [...student];
console.log("copy1=" + copy1);//输出:copy1=小明,小花,小聪
//3. 将伪数组转为真正的数组
const divs = document.querySelectorAll('div');//注意在文档顶部有3个div
const divArr = [...divs];
console.log(divArr);//输出:[div, div, div]
</script>
</body>
注意:
rest
参数适合不定个数参数函数的场景
2.8. spread 扩展运算符
扩展运算符(
spread
)也是三个点(
...
)。它好比
rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列,对数组进行解包。
<script>
// 『...』 扩展运算符能将『数组』转换为逗号分隔的『参数序列』
//声明一个数组 ...
const F4 = ['刘德华', '黎明', '张学友', '郭富城'];
// 声明一个函数
function tianwang() {
console.log(arguments);
}
tianwang(...F4);
//输出:Arguments(4) ['刘德华', '黎明', '张学友', '郭富城', callee: ƒ, Symbol(Symbol.iterator): ƒ]
</script>
2.9.Symbol
ES6
引入了一种新的原始数据类型
Symbol,表示独一无二的值。它是JavaScript
语言的第七种数据类型,是一种类似于字符串的数据类型。
Symbol
特点
1) Symbol
的值是唯一的,用来解决命名冲突的问题
2) Symbol
值不能与其他数据进行运算
3) Symbol
定义 的 对象属 性 不能 使 用
for…in 循 环遍 历 ,但 是可 以 使 用 Reflect.ownKeys
来获取对象的所有键名。
<script>
//创建 symbol
let s1 = Symbol();
console.log(s1, typeof s1);//输出:Symbol() 'symbol'
let s2 = Symbol("清华大学");
let s3 = Symbol.for("广东省深圳市");
//不能与其他数据进行运算
//let result1 = s1 + 100;
//console.log(result1);//输出:Uncaught TypeError: Cannot convert a Symbol value to a number
//let result2 = s2 + "教授";
//console.log(result2);//输出:Uncaught TypeError: Cannot convert a Symbol value to a string
let youxi = {
name: "王者荣耀",
[Symbol('zhongdan')]: function () {
console.log("我可以中单")
},
[Symbol('daye')]: function () {
console.log('我可以打野');
}
}
console.log(youxi)
</script>
注
:
遇到唯一性的场景时要想到
Symbol
2.10. 迭代器
遍历器(
Iterator)就是一种机制。它是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署
Iterator
接口,就可以完成遍历操作。
1) ES6
创造了一种新的遍历命令
for...of
循环,
Iterator
接口主要供
for...of
消费
2)
原生具备
iterator
接口的数据
(
可用
for of
遍历
)
a) Array
b) Arguments
c) Set
d) Map
e) String
f) TypedArray
g) NodeList
3)
工作原理
a)
创建一个指针对象,指向当前数据结构的起始位置
b)
第一次调用对象的
next
方法,指针自动指向数据结构的第一个成员
c)
接下来不断调用
next
方法,指针一直往后移动,直到指向最后一个成员
d)
每调用
next
方法返回一个包含
value
和
done
属性的对象
注
:
需要自定义遍历数据的时候,要想到迭代器。
<script>
let F4 = ["刘德华", "郭富城", "黎明", "张学友"];
//使用 for...of 遍历数组
for (let v of F4) {
console.log(v);//循环输出:刘德华、郭富城、黎明、张学友
}
let iterator = F4[Symbol.iterator]();
//调用对象的next方法
console.log(iterator.next());//输出:{value: '刘德华', done: false}
console.log(iterator.next());//输出:{value: '郭富城', done: false}
console.log(iterator.next());//输出:{value: '黎明', done: false}
console.log(iterator.next());//输出:{value: '张学友', done: false}
console.log(iterator.next());//输出:{value: undefined, done: true}
//自定义遍历数据
const NBA = {
name: "美国篮球协会",
player: ["乔丹", "麦迪", "姚明"],
[Symbol.iterator]() {
//索引变量
let index = 0;
let _this = this;
return {
next: function () {
if (index < _this.player.length) {
const result = {
value: _this.player[index], done: false
};
//下标自增
index++;
return result;
} else {
return { value: undefined, done: true };
}
}
};
}
}
//遍历这个 NBA 对象
for (let v of NBA) {
console.log(v);//输出:乔丹、麦迪、姚明
}
</script>
2.11. 生成器
生成器函数是
ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同。生成器其实就是一个特殊的函数。
<script>
//生成器其实就是一个特殊的函数
//异步编程 纯回调函数
//函数代码的分隔符
function* NBA() {
yield "乔丹";
yield "麦迪";
yield "姚明";
}
let iterator = NBA();
console.log(iterator.next());//输出:{value: '乔丹', done: false}
console.log(iterator.next());//输出:{value: '麦迪', done: false}
console.log(iterator.next());//输出:{value: '姚明', done: false}
console.log(iterator.next());//输出:{value: undefined, done: true}
//遍历
for (let v of NBA()) {
console.log(v);//输出:乔丹、麦迪、姚明
}
//生成器函数参数
function* university(arg) {
console.log("arg=" + arg);
let one = yield "清华大学";
console.log("one=" + one);
let two = yield "北京大学";
console.log("two=" + two);
let three = yield "哈佛大学";
console.log("three=" + three);
}
//执行获取迭代器对象
let iter = university("上海交大");
console.log("iter.next1=" + iter.next());
//next方法可以传入实参
console.log("iter.next2=" + iter.next("医科大"));
console.log("iter.next3=" + iter.next("中山大学"));
console.log("iter.next4=" + iter.next("复旦大学"));
//依次输出:
/*
arg=上海交大
iter.next1=[object Object]
one=医科大
iter.next2=[object Object]
two=中山大学
iter.next3=[object Object]
three=复旦大学
iter.next4=[object Object]
*/
//生成器函数实例
//异步编程、文件操作、网络操作(ajax、Request、数据库操作)
//模拟获取:用户数据、订单数据、商品数据
function getUserInfo() {
setTimeout(
() => {
let data = "用户数据";
console.log(data);
//调用 next 方法,并且将数据传入
info.next(data);
}, 1000)
}
function getOrderInfo() {
setTimeout(
() => {
let data = "订单数据";
console.log(data);
info.next(data);
}, 1000)
}
function getGoodsInfo() {
setTimeout(
() => {
let data = "商品数据";
console.log(data);
info.next(data);
}, 1000)
}
function* getMallInfo() {
yield getUserInfo();
yield getOrderInfo();
yield getGoodsInfo();
}
//调用生成器函数
let info = getMallInfo();
info.next();//依次输出:用户数据、订单数据、商品数据
</script>
代码说明:
1) *
的位置没有限制
2)
生成器函数返回的结果是迭代器对象,调用迭代器对象的
next 方法可以得到 yield
语句后的值
3) yield
相当于函数的暂停标记,也可以认为是函数的分隔符,每调用一次 next 方法,执行一段代码
4) next
方法可以传递实参,作为
yield
语句的返回值
2.12. Promise(重点掌握)
Promise
是
ES6
引入的异步编程的新解决方案。语法上
Promise 是一个构造函数,用来封装异步操作并可以获取其成功或失败的结果。
1) Promise
构造函数
: Promise (excutor) {}
2) Promise.prototype.then
方法
3) Promise.prototype.catch
方法
2.12.1 Promise基本语法
<script>
// promise 基本语法
//实例化 Promise 对象
const promise = new Promise(function (resolve, reject) {
/* 正常读取数据*/
setTimeout(function () {
let data = '数据库中的用户数据';
resolve(data);
}, 1000);
/*
setTimeout(function () {
let err = '数据读取失败';
reject(err);
});
*/
});
//调用 promise 对象的 then 方法
promise.then(function (value) {
console.log(value);
}, function (reason) {
console.error(reason);
})
</script>
2.12.2 Promise封装AJAX
<script>
const p = new Promise((resolve, reject) => {
//1. 创建对象
const xhr = new XMLHttpRequest();
//2. 初始化
xhr.open("GET", "输入具体的 URL 地址,比如 http://www.baidu.***/");
//3. 发送
xhr.send();
//4. 绑定事件, 处理响应结果
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);
});
</script>
2.12.3 Promise then方法
<script>
//创建 promise 对象
const p2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('用户数据');
// reject('出错啦');
}, 1000)
});
//调用 then 方法 then方法的返回结果是 Promise 对象, 对象状态由回调函数的执行结果决定
//1. 如果回调函数中返回的结果是 非 promise 类型的属性, 状态为成功, 返回值为对象的成功的值
// const result = p2.then(value => {
// console.log(value);
// //1. 非 promise 类型的属性
// // return 'iloveyou';
// //2. 是 promise 对象
// // return new Promise((resolve, reject)=>{
// // // resolve('ok');
// // reject('error');
// // });
// //3. 抛出错误
// // throw new Error('出错啦!');
// throw '出错啦!';
// }, reason=>{
// console.warn(reason);
// });
//链式调用
p2.then(value => {
}).then(value => {
});
</script>
2.12.3 Promise catch方法
<script>
const p3 = new Promise((resolve, reject) => {
setTimeout(() => {
//设置 p 对象的状态为失败, 并设置失败的值
reject("出错啦!");
}, 1000)
});
// p3.then(function(value){}, function(reason){
// console.error(reason);
// });
p3.catch(function (reason) {
console.warn(reason);
});
</script>
2.13. Set
ES6
提供了新的数据结构
Set(集合)。它类似于数组,但成员的值都是唯一的,集合实现了
iterator
接口,所以可以使用『扩展运算符』和『
for…of…』进行遍历,集合的属性和方法:
1) size 返回集合的元素个数
2) add 增加一个新元素,返回当前集合
3) delete
删除元素,返回
boolean
值
4) has 检测集合中是否包含某个元素,返回
boolean
值
5) clear 清空集合,返回
undefined
<script>
//创建一个空集合
let emptySet = new Set();
//创建一个非空集合
let wangzhe = new Set(["射手", "法师", "打野", "上单", "辅助"]);
//返回集合的元素个数
console.log(wangzhe.size);//输出:5
//遍历集合
for (let v of wangzhe) {
console.log(v);//输出:射手、法师、打野、上单、辅助
}
//添加新元素
console.log(wangzhe.add("野怪"));//输出:Set(6) {'射手', '法师', '打野', '上单', '辅助', '野怪'}
//删除元素
console.log(wangzhe.delete("野怪"));//输出:true
//检测是否存在某个值
console.log(wangzhe.has("野怪"));//输出:false
//清空集合
console.log(wangzhe.clear());//输出:undefined
//set 集合的去重、并、交、差集合
let arr1 = ["北京", "上海", "广州", "深圳", "上海"];
//数组去重
let repeat = [...new Set(arr1)];
console.log("repeat=" + repeat);//输出:repeat=北京,上海,广州,深圳
//交集
let arr2 = ["广州", "深圳", "武汉"];
let intersection = [...new Set(arr1)].filter(item => new Set(arr2).has(item));
console.log("intersection=" + intersection);//输出:intersection=广州,深圳
//并集
let union = [...new Set([...arr1, ...arr2])];
console.log("union=" + union);//输出:union=北京,上海,广州,深圳,武汉
//差集
let diff = [...new Set(arr1)].filter(item => !(new Set(arr2).has(item)));
console.log("diff=" + diff);//输出:diff=北京,上海
</script>
2.14. Map
ES6
提供了
Map 数据结构。它类似于对象,也是键值对的集合。但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。
Map 也实现了iterator
接口,所以可以使用『扩展运算符』和『
for…of…
』进行遍历。
Map 的属性和方法:
1) size 返回
Map
的元素个数
2) set 增加一个新元素,返回当前
Map
3) get 返回键名对象的键值
4) has 检测
Map
中是否包含某个元素,返回
boolean
值
5) clear 清空集合,返回
undefined
<script>
//声明一个 map
let map = new Map();
//添加元素
map.set("name", "马云");
map.set("word", function () {
console.log("让天下没有难做的生意!");
});
let school = {
name: "浙江师范大学"
};
map.set(school, ["北京大学", "清华大学"]);
//map集合数据长度
console.log("map.size=" + map.size);//输出:map.size=3
//删除
console.log(map.delete("name"));//输出:true
//获取map数据
console.log("word=" + map.get("word"));//输出:word=function () {console.log("让天下没有难做的生意!");}
console.log("school=" + map.get("school"));//输出:school=undefined
//遍历
for (let m of map) {
console.log(m);
}
/*
输出:
['word', ƒ]
[{…}, Array(2)]
*/
//清空 map
console.log(map.clear());//输出:undefined
</script>
2.15. class 类
ES6
提供了更接近传统语言的写法,引入了
Class(类)这个概念,作为对象的模板。通过
class
关键字,可以定义类。基本上,
ES6
的
class 可以看作只是一个语法糖,它的绝大部分功能,
ES5
都可以做到,新的
class 写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。
知识点:
1) class
声明类
2) constructor
定义构造函数初始化
3) extends
继承父类
4) super
调用父级构造方法
5) static
定义静态方法和属性
6)
父类方法可以重写
<script>
class Phone {
//构造方法
constructor(brand, price) {
this.brand = brand;
this.price = price;
}
//方法必须使用该语法,不能使用 ES5 的对象完整形式
call() {
console.log("我是一部手机");
}
}
let Huawei = new Phone("华为折叠手机", 8999);
console.log(Huawei);//输出:Phone {brand: '华为折叠手机', price: 8999}
//class 的 get、set
class Game {
get name() {
console.log("游戏的名字属性被读取了");
return "王者荣耀";
}
set name(newName) {
console.log("游戏的名字属性被修改了");
}
}
//实例化对象
let play = new Game();
console.log(play.name);//输出:游戏的名字属性被读取了、 王者荣耀
play.name = "打野";//游戏的名字属性被修改了
//类的静态成员
class University {
static name = "清华大学";
static word() {
console.log("自强不息,厚德载物");
}
student() {
console.log("好好学习,天天向上");
}
}
let Tom = new University();
console.log("Tom.name=" + Tom.name);//输出:Tom.name=undefined
console.log("Tom.word=" + Tom.word);//输出:Tom.word=undefined
console.log("Tom.student=" + Tom.student);//输出:Tom.student=student() {console.log("好好学习,天天向上");}
console.log("University.name=" + University.name);//输出:University.name=清华大学
console.log("University.word=" + University.word);//输出:University.word=word() {console.log("自强不息,厚德载物");}
//结论:类的静态成员只能被该类访问
//类的继承
class Person {
constructor(age, sex) {
this.age = age;
this.sex = sex;
}
//父类的成员属性
call() {
console.log("我的人类共有的特征");
}
}
//子类继承
class OtherPeople extends Person {
constructor(age, sex, name) {
super(age, sex);
this.name = name;
}
//唱歌
sing() {
console.log("我会唱歌");
}
codding() {
console.log("我会编程");
}
}
const XiaoMing = new OtherPeople(18, "男", "我叫小明");
XiaoMing.call();//输出:我的人类共有的特征
XiaoMing.sing();//输出:我会唱歌
XiaoMing.codding();//输出:我会编程
</script>
2.16. 数值扩展
2.16.1. 二进制和八进制
ES6
提供了二进制和八进制数值的新的写法,分别用前缀
0b
和
0o
表示。
2.16.2. Number.isFinite() 与 Number.isNaN()
Number.isFinite()
用来检查一个数值是否为有限的
Number.isNaN()
用来检查一个值是否为
NaN
2.16.3. Number.parseInt() 与 Number.parseFloat()
ES6
将全局方法
parseInt
和
parseFloat
,移植到
Number
对象上面,使用不变。
2.16.4. Math.trunc
用于去除一个数的小数部分,返回整数部分。
2.16.5. Number.isInteger
Number.isInteger()
用来判断一个数值是否为整数
<script>
//1、Number.EPSILON 是 JavaScript 表示的最小精度
//EPSILON 属性的值接近于 2.2204460492503130808472633361816E-16
function equal(a, b) {
if (Math.abs(a, b) < Number.EPSILON) {
return true;
} else {
return false;
}
}
console.log(1 + 2 == 3);//输出:true
console.log(1 + 2 === 3);//输出:true
console.log(0.1 + 0.2 == 0.3);//输出:false
console.log(0.1 + 0.2 === 0.3);//输出:false
console.log(equal(0.1 + 0.2, 0.3));//输出:false
//2、Number.isFinite 检测一个数值是否为有限数
console.log("-------------------------------------");
console.log(Number.isFinite(100));//输出:true
console.log(Number.isFinite(100 / 0));//输出:false
console.log(Number.isFinite(Infinity));//输出:false
//3. Number.isNaN 检测一个数值是否为 NaN
console.log("-------------------------------------");
console.log(Number.isNaN(123));//输出:false
console.log(Number.isNaN(NaN));//输出:true
//4. Number.parseInt Number.parseFloat字符串转整数
console.log("-------------------------------------");
console.log(Number.parseInt('123砍三刀'));//输出:123
console.log(Number.parseFloat('3.1415926圆周率'));//输出:3.1415926
//5. Number.isInteger 判断一个数是否为整数
console.log("-------------------------------------");
console.log(Number.isInteger(666));//输出:true
console.log(Number.isInteger(8.88));//输出:false
console.log(Number.isInteger("一刀999"));//输出:false
//6. Math.trunc 将数字的小数部分抹掉
console.log("-------------------------------------");
console.log(Math.trunc(1.25));//输出:1
//7. Math.sign 判断一个数到底为正数 负数 还是零
console.log("-------------------------------------");
console.log(Math.sign(0));//输出:0
console.log(Math.sign(12306));//输出:1
console.log(Math.sign(-2.98));//输出:-1
</script>
2.17. 对象扩展
ES6
新增了一些
Object
对象的方法
1) Object.is
比较两个值是否严格相等,与『
===
』行为基本一致(
+0
与
NaN
)
2) Object.assign
对象的合并,将源对象的所有可枚举属性,复制到目标对象
3) __proto__
、
setPrototypeOf
、
setPrototypeOf
可以直接设置对象的原型
<script>
//1. Object.is 判断两个值是否完全相等
console.log(Object.is(666, 666));//输出:true
console.log(Object.is(NaN, NaN));//输出:true
console.log(NaN === NaN);//输出:false
//2. Object.assign 对象的合并
const dbConfigDev = {
host: 'http://127.0.0.1',
port: 3306,
name: 'dev',
pass: 'dev',
dbName: 'dev数据库',
remark: "这是备注,开发环境数据库"
};
const dbConfigTest = {
host: 'http://127.0.0.2',
port: 8848,
name: 'test',
pass: 'test',
dbName: 'test数据库',
info: "请开启防火墙"
}
console.log(Object.assign(dbConfigDev, dbConfigTest));
//输出:{host: 'http://127.0.0.2', port: 8848, name: 'test', pass: 'test', dbName: 'test数据库', info: "请开启防火墙",remark: "这是备注,开发环境数据库"}
//3. Object.setPrototypeOf 设置原型对象 Object.getPrototypeof
const school = {
name: '清华大学'
}
const cities = {
xiaoqu: ['北京', '上海', '深圳']
}
Object.setPrototypeOf(school, cities);
console.log(Object.getPrototypeOf(school));//输出:{xiaoqu: Array(3)}['北京', '上海', '深圳']
console.log(school);//输出:{name: '清华大学'}
</script>
2.18. 模块化
模块化是指将一个大的程序文件,拆分成许多小的文件,然后将小文件组合起来。
2.18.1. 模块化的好处
模块化的优势有以下几点:
1)
防止命名冲突
2)
代码复用
3)
高维护性
2.18.2. 模块化规范产品
ES6
之前的模块化规范有:
1) ***monJS => NodeJS
、
Browserify
2) AMD => requireJS
3) CMD => seaJS
2.18.3. ES6 模块化语法
模块功能主要由两个命令构成:
export
和
import
。
⚫
export
命令用于规定模块的对外接口
⚫
import
命令用于输入其他模块提供的功能
第 3 章 ECMASript 7 新特性
3.1.Array.prototype.includes
Includes
方法用来检测数组中是否包含某个元素,返回布尔类型值
3.2.指数操作符
在 ES7 中引入指数运算符「**」,用来实现幂运算,功能与 Math.pow 结果相同
<script>
// includes indexOf
// const mingzhu = ['西游记','红楼梦','三国演义','水浒传'];
//判断
// console.log(mingzhu.includes('西游记'));
// console.log(mingzhu.includes('金瓶梅'));
// **
console.log(2 ** 10);//
console.log(Math.pow(2, 10));
</script>
第 4 章 ECMASript 8 新特性
4.1.async 和 await
async 和 await 两种语法结合可以让异步代码像同步代码一样
4.1.1.async 函数
1. async
函数的返回值为
promise
对象,
2. promise
对象的结果由
async
函数执行的返回值决定
<script>
//async 函数
async function fn(){
// 返回一个字符串
// return '清华大学';
// 返回的结果不是一个 Promise 类型的对象, 返回的结果就是成功 Promise 对象
// return;
//抛出错误, 返回的结果是一个失败的 Promise
// throw new Error('出错啦!');
//返回的结果如果是一个 Promise 对象
return new Promise((resolve, reject)=>{
resolve('成功的数据');
// reject("失败的错误");
});
}
const result = fn();
//调用 then 方法
result.then(value => {
console.log(value);
}, reason => {
console.warn(reason);
})
</script>
4.1.2.await 表达式
1. await 必须写在 async 函数中
2. await 右侧的表达式一般为 promise 对象
3. await
返回的是
promise
成功的值
4. await
的
promise
失败了
,
就会抛出异常
,
需要通过
try...catch
捕获处理
<script>
//创建 promise 对象
const p = new Promise((resolve, reject) => {
// resolve("用户数据");
reject("失败啦!");
})
// await 要放在 async 函数中.
async function main() {
try {
let result = await p;
//
console.log(result);
} catch (e) {
console.log(e);
}
}
//调用函数
main();
</script>
4.2.Object.values 和 Object.entries
1. Object.values()
方法返回一个给定对象的所有可枚举属性值的数组
2. Object.entries()
方法返回一个给定对象自身可遍历属性
[key,value]
的数组
4.3.Object.getOwnPropertyDescriptors
该方法返回指定对象所有自身属性的描述对象
4.4 async与await封装AJAX请求
<script>
// 发送 AJAX 请求, 返回的结果是 Promise 对象
function sendAJAX(url) {
return new Promise((resolve, reject) => {
//1. 创建对象
const x = new XMLHttpRequest();
//2. 初始化
x.open('GET', url);
//3. 发送
x.send();
//4. 事件绑定
x.onreadystatechange = function () {
if (x.readyState === 4) {
if (x.status >= 200 && x.status < 300) {
//成功啦
resolve(x.response);
}else{
//如果失败
reject(x.status);
}
}
}
})
}
//promise then 方法测试
// sendAJAX("https://api.apiopen.top/getJoke").then(value=>{
// console.log(value);
// }, reason=>{})
// async 与 await 测试 axios
async function main(){
//发送 AJAX 请求
let result = await sendAJAX("https://api.apiopen.top/getJoke");
//再次测试
let tianqi = await sendAJAX('https://www.tianqiapi.***/api/?version=v1&city=%E5%8C%97%E4%BA%AC&appid=23941491&appsecret=TXoD5e8P')
console.log(tianqi);
}
main();
</script>
4.5 ES8 对象方法扩展
<script>
//声明对象
const school = {
name:"清华大学",
cities:['北京','上海','深圳'],
xueke: ['前端','Java','大数据','运维']
};
//获取对象所有的键
// console.log(Object.keys(school));
//获取对象所有的值
// console.log(Object.values(school));
//entries
// console.log(Object.entries(school));
//创建 Map
// const m = new Map(Object.entries(school));
// console.log(m.get('cities'));
//对象属性的描述对象
// console.log(Object.getOwnPropertyDescriptors(school));
// const obj = Object.create(null, {
// name: {
// //设置值
// value: '清华大学',
// //属性特性
// writable: true,
// configurable: true,
// enumerable: true
// }
// });
</script>
第 5 章 ECMASript 9 新特性
5.1.Rest/Spread 属性
Rest
参数与
spread
扩展运算符在
ES6
中已经引入,不过
ES6 中只针对于数组,在
ES9
中为对象提供了像数组一样的
rest
参数和扩展运算符。
function connect({host, port, ...user}) {
console.log(host);
console.log(port);
console.log(user);
}
connect({
host: '127.0.0.1',
port: 3306,
username: 'root',
password: 'root',
type: 'master'
});
5.2.正则表达式命名捕获组
ES9
允许命名捕获组使用符号『
?<name>
』
,
这样获取捕获结果可读性更强
let str = '<a href="http://www.baidu.***">百度</a>';
const reg = /<a href="(?<url>.*)">(?<text>.*)<\/a>/;
const result = reg.exec(str);
console.log(result.groups.url);
console.log(result.groups.text);
5.3.正则表达式反向断言
ES9
支持反向断言,通过对匹配结果前面的内容进行判断,对匹配进行筛选。
//声明字符串
let str = 'JS5211314 你知道么 555 啦啦啦';
//正向断言
const reg = /\d+(?=啦)/;
const result = reg.exec(str);
//反向断言
const reg = /(?<=么)\d+/;
const result = reg.exec(str);
console.log(result);
5.4.正则表达式 dotAll 模式
正则表达式中点
.
匹配除回车外的任何单字符,标记『
s』改变这种行为,允许行终止符出现
let str = `
<ul>
<li>
<a>肖生克的救赎</a>
<p>上映日期: 1994-09-10</p>
</li>
<li>
<a>阿甘正传</a>
<p>上映日期: 1994-07-06</p>
</li>
</ul>`;
//声明正则
const reg = /<li>.*?<a>(.*?)<\/a>.*?<p>(.*?)<\/p>/gs;
//执行匹配
const result = reg.exec(str);
let result;
let data = [];
while(result = reg.exec(str)){
data.push({title: result[1], time: result[2]});
}
//输出结果
console.log(data);
第 6 章 ECMASript 10 新特性
6.1.Object.fromEntries
<script>
//二维数组
// const result = Object.fromEntries([
// ['name','北京大学'],
// ['xueke', 'Java,大数据,前端,云计算']
// ]);
//Map
// const m = new Map();
// m.set('name','BEIJING');
// const result = Object.fromEntries(m);
//Object.entries ES8
const arr = Object.entries({
name: "北京大学"
})
console.log(arr);
</script>
6.2.trimStart
和
trimEnd
<script>
// trim
let str = ' iloveyou ';
console.log(str);
console.log(str.trimStart());
console.log(str.trimEnd());
</script>
6.3.Array.prototype.flat
与
flatMap
<script>
//flat 平
//将多维数组转化为低位数组
// const arr = [1,2,3,4,[5,6]];
// const arr = [1,2,3,4,[5,6,[7,8,9]]];
//参数为深度 是一个数字
// console.log(arr.flat(2));
//flatMap
const arr = [1,2,3,4];
const result = arr.flatMap(item => [item * 10]);
console.log(result);
</script>
6.4.Symbol.prototype.description
<script>
//创建 Symbol
let s = Symbol('清华大学');
console.log(s.description);
</script>
第 7 章 ECMASript 11 新特性
7.1.String.prototype.matchAll
<script>
let str = `<ul>
<li>
<a>肖生克的救赎</a>
<p>上映日期: 1994-09-10</p>
</li>
<li>
<a>阿甘正传</a>
<p>上映日期: 1994-07-06</p>
</li>
</ul>`;
//声明正则
const reg = /<li>.*?<a>(.*?)<\/a>.*?<p>(.*?)<\/p>/sg
//调用方法
const result = str.matchAll(reg);
// for(let v of result){
// console.log(v);
// }
const arr = [...result];
console.log(arr);
</script>
7.2.
类的私有属性
<script>
class Person{
//公有属性
name;
//私有属性
#age;
#weight;
//构造方法
constructor(name, age, weight){
this.name = name;
this.#age = age;
this.#weight = weight;
}
intro(){
console.log(this.name);
console.log(this.#age);
console.log(this.#weight);
}
}
//实例化
const girl = new Person('小梅', 18, '45kg');
// console.log(girl.name);
// console.log(girl.#age);
// console.log(girl.#weight);
girl.intro();
</script>
7.3.Promise.allSettled
<script>
//声明两个promise对象
const p1 = new Promise((resolve, reject)=>{
setTimeout(()=>{
resolve('商品数据 - 1');
},1000)
});
const p2 = new Promise((resolve, reject)=>{
setTimeout(()=>{
resolve('商品数据 - 2');
// reject('出错啦!');
},1000)
});
//调用 allsettled 方法
// const result = Promise.allSettled([p1, p2]);
// const res = Promise.all([p1, p2]);
console.log(res);
</script>
7.4.
可选链操作符
<script>
function main(config){
// const dbHost = config && config.db && config.db.host;
const dbHost = config?.db?.host;
console.log(dbHost);
}
main({
db: {
host:'192.168.1.100',
username: 'root'
},
cache: {
host: '192.168.1.200',
username:'admin'
}
})
</script>
7.5.
动态
import
导入
<body>
<button id="btn">点击</button>
<script src="./js/app.js" type="module"></script>
</body>
7.6.globalThis
对象
<script>
console.log(globalThis);
</script>