ES6
let
//随意声明变量
let a;
let b, c, d;
let e = 100;
let f = 521, g = 'iloveyou', h = [];
🍎1. 变量不能重复声明
let star = '罗志祥';
let star = '小猪'; //报错 Uncaught SyntaxError: Identifier 'star' has already been declared
🍎2. 块儿级作用域 全局, 函数, eval
if else while for
{
let girl = '周扬青';
}
console.log(girl); //Uncaught ReferenceError: girl is not defined
🍎3. 不存在变量提升
console.log(song); //underfined
let song = '恋爱达人';
🍎4. 不影响作用域链
{
let school = '车车';
function fn() {
console.log(school); //车车
}
fn();
}
复制代码
const
//声明常量
const SCHOOL = '车车';
🍎1. 一定要赋初始值
const A; //Uncaught SyntaxError: Missing initializer in const declaration
🍎2. 一般常量使用大写(潜规则)
const a = 100;
🍎3. 常量的值不能修改
SCHOOL = 'ATGUIGU'; //Uncaught TypeError: Assignment to constant variable.不能给常量赋值
🍎4. 块儿级作用域 在{}内
{
const PLAYER = 'UZI';
}
console.log(PLAYER); //PLAYER is not defined
🍎5. 对于数组和对象的元素修改, 不算做对常量的修改, 不会报错
const TEAM = ['UZI', 'MXLG', 'Ming', 'Letme'];
TEAM.push('Meiko');
console.log(TEAM);//0: "UZI"1: "MXLG"2: "Ming"3: "Letme"4: "Meiko"
复制代码
解构赋值
ES6 允许按照一定模式从数组和对象中提取值,对变量进行赋值,这被称为解构赋值。
🍎1. 数组的结构 用的少
const F4 = ['小沈阳', '刘能', '赵四', '宋小宝'];
let [xiao, liu, zhao, song] = F4;
console.log(xiao);
console.log(liu);
console.log(zhao);
console.log(song);
复制代码
🍎2. 对象的解构 常用
const zhao = {
name: '赵本山',
age: '不详',
xiaopin: function () {
console.log("我可以演小品");
}
};
let { name, age, xiaopin } = zhao;
console.log(name); //赵本山
console.log(age); //不详
console.log(xiaopin); //f(){console.log("我可以演小品");}
xiaopin(); //我可以演小品
复制代码
🍎3.
let { xiaopin } = zhao;
xiaopin(); //zhao is not defined
复制代码
模板字符串
ES6 引入新的声明字符串的方式 『``』 '' ""
🍎1. 声明
let str = `我也是一个字符串哦!`;
console.log(str, typeof str); //我也是一个字符串哦! string
复制代码
🍎2. 内容中可以直接出现换行符
let str = `<ul>
<li>沈腾</li>
<li>玛丽</li>
<li>魏翔</li>
<li>艾伦</li>
</ul>`;
console.log(str); //原文打印 如果是'' ""则报错
复制代码
🍎3. 变量拼接⭐
let lovest = '魏翔';
let out = `${lovest}是我心目中最搞笑的演员!!`; //固定格式
console.log(out); //魏翔是我心目中最搞笑的演员!!
复制代码
简化对象写入写法
🍎变量和函数,作为对象的属性和方法。 这样的书写更加简洁
//声明两个变量
let name = '车车';
let change = function () {
console.log('我们可以改变你!!');
}
const school = {
name,
change,
improve() {
console.log("我们可以提高你的技能");
}
}
console.log(school);//{name:"车车",cahnge:f,improve:f}
复制代码
箭头函数
箭头函数适合与 this 无关的回调. 定时器, 数组的方法回调
箭头函数不适合与 this 有关的回调. DOM元素事件回调, 对象的方法
ES6 允许使用「箭头」(=>)定义函数。
声明一个函数
let fn = function () {
}
//两者比较写法
let fn = (a, b) => {
return a + b;
}
// // 调用函数
let result = fn(1, 2);
console.log(result); //3
复制代码
🍎1. this 是静态的. this 始终指向函数声明时所在作用域下的 this 的值
function getName() {
console.log(this.name);
}
let getName2 = () => {
console.log(this.name);
}
// //设置 window 对象的 name 属性
window.name = '车车';
const school = {
name: "ATGUIGU"
}
//直接调用 直接调用 指向window
getName();//⭐普通函数 车车
getName2();//⭐箭头函数 车车
//call 方法调用 改变函数内部值 可以改变普通函数this 改变不了箭头函数this
⭐普通函数
getName.call(school);// ATGUIGU
⭐箭头函数静态地
getName2.call(school);// 车车
复制代码
🍎2. 不能作为构造函数实例化对象 (普通函数可以构造函数实例化对象)
let Person = (name, age) => {
this.name = name;
this.age = age;
}
let me = new Person('xiao', 30);
console.log(me); //Person is not a constructor
复制代码
🍎3. 不能使用 arguments 变量 (arguments可以保存实参,箭头函数不可以)
箭头函数
let fn = () => {
console.log(arguments);
}
fn(1, 2, 3);//arguments is not defined
普通函数
let fn = function () {
console.log(arguments);
}
fn(1, 2, 3);//Arguments(3) 0: 1 1: 2 2: 3
复制代码
🍎4. 箭头函数的简写
//1) 省略小括号, 当形参有且只有一个的时候
let add = n => {
return n + n;
}
console.log(add(9));//18
//2) 省略花括号, 当代码体只有一条语句的时候, 此时 return 必须省略
// 而且语句的执行结果就是函数的返回值
let pow = n => n * n;
console.log(pow(8));//64
复制代码
案例
//需求-1 点击 div 2s 后颜色变成『粉色』
//获取元素
let ad = document.getElementById('ad');
//绑定事件
ad.addEventListener("click", function(){
//保存 this 的值
// let _this = this;
//定时器
setTimeout(() => {
//修改背景颜色 this
// console.log(this);不使用箭头函数指向window
// _this.style.background = 'pink';
this.style.background = 'pink';//箭头函数 则this指向ad
}, 2000);
});
//需求-2 从数组中返回偶数的元素
const arr = [1,6,9,10,100,25];
普通函数
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); //[6,10,100]
复制代码
函数参数默认值
//ES6 允许给函数参数赋值初始值
🍎1. 形参初始值 具有默认值的参数, 一般位置要靠后(潜规则)
function add(a, c = 10, b = 2) {
return a + b + c;
}
let result = add(1, 2);
console.log(result);//5
🍎2. 与解构赋值结合
function connect({ host = "127.0.0.1", username, password, port }) {
console.log(host) //atguigu.com
console.log(username) //root
console.log(password) //root
console.log(port) //3306
}
connect({
host: 'atguigu.com',
username: 'root',
password: 'root',
port: 3306
})
复制代码
rest参数 ...
引入 rest 参数,用于获取函数的实参,用来代替 arguments
// ES5 获取实参的方式
function date() {
console.log(arguments);⭐ //arguments ['白芷', '阿娇', '思慧']
}
date('白芷', '阿娇', '思慧');
复制代码
🍎rest 参数
function date(...args) {
console.log(args);//⭐['阿娇', '柏芝', '思慧']可以使用 filter some every map
}
date('阿娇', '柏芝', '思慧');
复制代码
🍎rest 参数必须要放到参数最后
function fn(a, b, ...args) {
console.log(a);//1
console.log(b);//2
console.log(args);//3,4,5,6
}
fn(1, 2, 3, 4, 5, 6);
复制代码
扩展运算符 ...
可以生成新的对象 如果修改 被复制对象不会被修改 类似深拷贝
扩展运算符能将『数组』转换为逗号分隔的『参数序列』
数组 规则:按顺序 多余参数可使用...arr来接收
//声明一个数组 ...
const tfboys = ['易烊千玺', '王源', '王俊凯'];// => '易烊千玺','王源','王俊凯'
对比相同功能arguments与...arr
// 声明一个函数
function chunwan() {
console.log(arguments);
}
chunwan(tfboys);// arguments(1) 0:('易烊千玺','王源','王俊凯')
chunwan(...tfboys);// arguments(3) 0:'易烊千玺',1:'王源',2:'王俊凯')
例:let [a,b,c]=tfboys
console.log(a,b,b)//'易烊千玺','王源','王俊凯'
复制代码
对象 属性名必须一致
//声明一个对象 ...
const tfboys = {name:'王元',sex:'女'}
const {name,sex}=tfboys
console.log(name,sex)//王元,女
复制代码
案例
🍎1. 数组的合并 情圣 误杀 唐探
const kuaizi = ['王太利', '肖央'];
const fenghuang = ['曾毅', '玲花'];
// const zuixuanxiaopingguo = kuaizi.concat(fenghuang);
const zuixuanxiaopingguo = [...kuaizi, ...fenghuang];
console.log(zuixuanxiaopingguo); //Array(4) 0: "王太利" 1: "肖央" 2: "曾毅" 3: "玲花"
复制代码
🍎2. 数组的克隆
const sanzhihua = ['E', 'G', 'M'];
const sanyecao = [...sanzhihua];
console.log(sanyecao); // Array(3)['E','G','M']
复制代码
🍎3. 将伪数组转为真正的数组
const divs = document.querySelectorAll('div');
console.log(divs); //NodeList(3) 0: div 1: div 2: div
const divArr = [...divs];
console.log(divArr);// Array(3)0: div 1: div 2: div
复制代码
Symbol
创建Symbol 值是唯一 解决命名冲突
let s = Symbol();
console.log(s, typeof s); //Symbol() 'symbol'
传入字符串
let s2 = Symbol('车车');
let s3 = Symbol('车车');
console.log(s2 === s3);//false
Symbol.for 创建
let s4 = Symbol.for('车车');
let s5 = Symbol.for('车车');
console.log(s4 === s5);//true
//不能与其他数据进行运算
let result = s + 100;
let result = s > 100;
let result = s + s;
//Uncaught TypeError: Cannot convert a Symbol value to a number
复制代码
案例 向对象中添加方法
向对象中添加方法 up down
let game = {
name: '俄罗斯方块',
up: function () { },
down: function () { }
};
//声明一个对象
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(): ƒ}
复制代码
let youxi = {
name: "狼人杀",
//封装方法
[Symbol('say')]: function () {
console.log("我可以发言")
},
//封装方法
[Symbol('zibao')]: function () {
console.log('我可以自爆');
}
}
console.log(youxi)//{name: '狼人杀', Symbol(say): ƒ, Symbol(zibao): ƒ}
复制代码
内置属性 特定场景下表现 好多个(如下举例 后面补充)
// 🍎自己控制类型检测
class Person {
static [Symbol.hasInstance](param) {
console.log(param);//Object[[Prototype]]: Object
console.log("我被用来检测类型了");//我被用来检测类型了
return false;
}
}
let o = {};
console.log(o instanceof Person);//false
// 🍎数组合并是否可以展开
const arr = [1, 2, 3];
const arr2 = [4, 5, 6];
arr2[Symbol.isConcatSpreadable] = false;
console.log(arr.concat(arr2));
复制代码
迭代器 拿到想拿到的数据
是一种接口,为各种不同数据结构提供统一访问机制.任何数据结构只要部署iterator接口,就for of 可以完成遍历操作.
iterator接口:对象里面属性
原理: 需要自定义遍历数据时候
1)创建指针对象,指向当前数据结构的起始位置
2)第一次调用对象next方法,指针自动指向数据结构地第一个成员.
3)不断调用next方法,指针一直往后移动,直到指向最后一个成员
4)每调用next方法返回一个包含value和done属性的对象.
//声明一个数组
const xiyou = ['唐僧', '孙悟空', '猪八戒', '沙僧'];
//使用 for...of 遍历数组 in键名 of 键值
for (let v of xiyou) {
console.log(v); //唐僧 孙悟空 猪八戒 沙僧
}
let iterator = xiyou[Symbol.iterator]();
// //调用对象的next方法
console.log(iterator.next());//done false value 唐僧
console.log(iterator.next());//...
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());//done false value 沙僧
//第五次打印 //value underfined done true
复制代码
案例
//声明一个对象
const banji = {
name: "终极一班",
stus: [
'xiaoming',
'xiaoning',
'xiaotian',
'knight'
],
[Symbol.iterator]() {
//索引变量
let index = 0;
//
let _this = this;
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 v of banji) {
console.log(v); //'xiaoming','xiaoning','xiaotian','knight'
}
复制代码
生成器 异步解决方案
生成器其实就是一个特殊的函数
异步编程 纯回调函数 node fs ajax mongodb
函数代码的分隔符yield
function* gen() {
// console.log(111);
yield '一只没有耳朵';
// console.log(222);
yield '一只没有尾部';
// console.log(333);
yield '真奇怪';
// console.log(444);
}
let iterator = gen();
// 迭代器对象next 输出结果和迭代器方式一样
console.log(iterator.next());//Object done: false value: "一只没有耳朵"
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
//遍历 全部输出 一只没有耳朵 一只没有尾部 真奇怪
for (let v of gen()) {
console.log(v);
}
复制代码
生成器函数参数
function* gen(arg) {
console.log(arg);
let one = yield 111;
console.log(one);
let two = yield 222;
console.log(two);
let three = yield 333;
console.log(three);
}
//执行获取迭代器对象
let iterator = gen('AAA');
console.log(iterator.next());
//next方法也可以传入实参 作为第一个返回结果
console.log(iterator.next('BBB'));
console.log(iterator.next('CCC'));
console.log(iterator.next('DDD'));
复制代码
生成器函数实例
异步编程 文件操作 网络操作(ajax, request) 数据库操作
1s 后控制台输出 111 2s后输出 222 3s后输出 333
// 回调地狱
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();
复制代码
案例
//模拟获取 用户数据 订单数据 商品数据
function getUsers() {
setTimeout(() => {
let data = '用户数据';
//调用 next 方法, 并且将数据传入
iterator.next(data);
}, 1000);
}
function getOrders() {
setTimeout(() => {
let data = '订单数据';
iterator.next(data);
}, 1000)
}
function getGoods() {
setTimeout(() => {
let data = '商品数据';
iterator.next(data);
}, 1000)
}
function * gen() {
let users = yield getUsers();
let orders = yield getOrders();
let goods = yield getGoods();
}
//调用生成器函数
let iterator = gen();
iterator.next();
复制代码
Promise
异步编程解决方案
语法上是构造函数 用来封装异步操作并可以获取期成功或失败结果
基本语法
//实例化 Promise 对象 状态:初始化 成功 失败
const p = new Promise(function (resolve, reject) {
// 异步操作
setTimeout(function () {
// resolve
// let data = '数据库中的用户数据';
// resolve(data);
let err = '数据读取失败';
reject(err);
}, 1000);
});
//调用 promise 对象的 then 方法 接收两个函数类型值 成功调用第一个函数类型值形参 失败调用第二个
p.then(function (value) {
console.log(value);
}, function (reason) {
console.error(reason);
})
复制代码
Promise封装读取文件 多个异步任务处理
//1. 引入 fs 模块
const fs = require('fs');
// 调用方法读取文件
fs.readFile('./resources/为学.md', (err, data) => {
//如果失败, 则抛出错误
if (err) throw err;
//如果没有出错, 则输出内容
console.log(data.toString()); //成功输出
});
//🍎或 使用 Promise 封装
const p = new Promise(function (resolve, reject) {
fs.readFile('./resources/为学.md', (err, data) => {
//判断如果失败
if (err) reject(err);
//如果成功
resolve(data);
});
});
p.then(function (value) {
console.log(value.toString());
}, function (reason) {
console.log("读取失败!!");
});
复制代码
Promise封装AJAX
// 接口地址: https://api.apiopen.top/getJoke
const p = new Promise((resolve, reject) => {
//1. 创建对象
const xhr = new XMLHttpRequest();
//2. 初始化
xhr.open("GET", "https://api.apiopen.top/getJoke");
//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);
});
复制代码
Promise-then方法
定时用户数据成功还是失败
使用p.then返回结果
调用 then 方法 then方法的返回结果是 Promise 对象, 对象状态由回调函数的执行结果决定
- 如果回调函数中返回的结果是 非 promise 类型的属性, 状态为成功, ⭐返回值为对象的成功的值
//创建 promise 对象
const p = new Promise((resolve, reject) => {
setTimeout(() => {
// resolve('用户数据');
reject('出错啦');
}, 1000)
});
//调用 then 方法 then方法的返回结果是 Promise 对象, 对象状态由回调函数的执行结果决定
//1. 如果回调函数中返回的结果是 非 promise 类型的属性, 状态为成功, ⭐返回值为对象的成功的值
const result = p.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);
});
//链式调用
p.then(value => {
}).then(value => {
});
复制代码
catch promise失败后回调 语法糖,不指定第一个成功函数参数,直接输出第二个失败函数参数形参
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);
});
复制代码
案例 读取多个文件
//引入 fs 模块
const fs = require("fs");
//一般实现
fs.readFile('./resources/为学.md', (err, data1)=>{
fs.readFile('./resources/插秧诗.md', (err, data2)=>{
fs.readFile('./resources/观书有感.md', (err, data3)=>{
let result = data1 + '\r\n' +data2 +'\r\n'+ data3;
console.log(result);
});
});
});
//使用 promise 实现
const p = new Promise((resolve, reject) => {
fs.readFile("./resources/为学.md", (err, data) => {
resolve(data);
});
});
p.then(value => {
return new Promise((resolve, reject) => {
fs.readFile("./resources/插秧诗.md", (err, data) => {
resolve([value, data]);
});
});
}).then(value => {
return new Promise((resolve, reject) => {
fs.readFile("./resources/观书有感.md", (err, data) => {
//压入
value.push(data);
resolve(value);
});
})
}).then(value => {
console.log(value.join('\r\n'));
});
复制代码
set(集合) 数据结构 类似数组
但成员值唯一 集合实现interator接口 可以使用扩展运算符和for of 进行遍历 集合属性和方法
1)size 返回集合元素个数
2)add 增加一个新元素,返回当前集合
3)delete 删除元素,返回boolean值
4)has 检测集合中是否包含某个元素 ,返回boolean值
//声明一个 set 一般传入数组
let s = new Set();
let s2 = new Set(['大事儿', '小事儿', '好事儿', '坏事儿', '小事儿']);
//元素个数
console.log(s2.size);//4
//添加新的元素
s2.add('喜事儿');
//删除元素
s2.delete('坏事儿');
//检测
console.log(s2.has('糟心事'));//false
//清空
s2.clear();
console.log(s2);//''
for (let v of s2) {
console.log(v);
}
复制代码
案例
let arr = [1, 2, 3, 4, 5, 4, 3, 2, 1];
//1. 数组去重
let result = [...new Set(arr)];
console.log(result);//[1,2,3,4,5]
//2. 交集
let arr2 = [4, 5, 6, 5, 6];
let result = [...new Set(arr)].filter(item => {
let s2 = new Set(arr2);// 4 5 6
if (s2.has(item)) {
return true;
} else {
return false;
}
});
// 或者
let result = [...new Set(arr)].filter(item => new Set(arr2).has(item));
//打印
console.log(result);//4,5
//3. 并集
let union = [...new Set([...arr, ...arr2])];
console.log(union);//[1,2,3,4,5,6]
//4. 差集 交集逆运算
let diff = [...new Set(arr)].filter(item => !(new Set(arr2).has(item)));
console.log(diff);//1,2,3
复制代码
Map 类似于对象
键值对集合.键范围不局限于字符串,各种类型值(包括对象).map也实现interator接口.可以使用扩展运算符和for of 进行遍历. map属性和方法
1)size 返回map元素个数
2)set 增加一个新元素,返回当前map
3)get 返回键名对象的键值
4)has 检测map中是否包含某个元素 ,返回boolean值
5)clear 清空集合,返回underfined
//声明 Map
let m = new Map();
//添加元素
m.set('name', '车车'); //Map key:name value:车车
m.set('change', function () {
console.log("我们可以改变你!!");//Map key:'change' value f
});
let key = {
school: 'ATGUIGU'
};
m.set(key, ['北京', '上海', '深圳']); //key:ATGUIGU value:['北京', '上海', '深圳']
//size
console.log(m.size);//3
//删除
m.delete('name');
//获取
console.log(m.get('change'));//f
console.log(m.get(key));//['北京', '上海', '深圳']
//清空
m.clear();//Map(0)
//遍历 每个元素数组
for (let v of m) {
console.log(v);
}
console.log(m);
复制代码
class类 语法糖 更像面向对象编程语法
知识点:
1)clss声明类
2)constructor定义构造函数初始化
3)extends继承父类
4)super调用父级构造方法
5)static定义静态方法和属性
6)父类方法可以重写
//手机
function Phone(brand, price) {
this.brand = brand;
this.price = price;
}
//添加方法
Phone.prototype.call = function () {
console.log("我可以打电话!!");
}
//实例化对象
let Huawei = new Phone('华为', 5999);
console.log(Huawei);//brand:'华为' price:5999 原型_proto_下call方法f
Huawei.call();
console.log(Huawei)// 我可以打电话!! brand:'华为' price:5999
//🍎class
class Shouji {
//构造方法 名constructor字不能修改
constructor(brand, price) {
this.brand = brand;
this.price = price;
}
//⭐方法必须使用该语法, 不能使用 ES5 的对象完整形式
call() {
console.log("我可以打电话!!");
}
}
let onePlus = new Shouji("1+", 1999);
console.log(onePlus);//brand:'1+' price:1999 原型_proto_下call方法f
复制代码
类静态成员
//ES5
function Phone() {
}
Phone.name = '手机';
Phone.change = function () {
console.log("我可以改变世界");
}
Phone.prototype.size = '5.5inch';
let nokia = new Phone();
console.log(nokia.name);//underfined 实例对象没有构造函数上方法
nokia.change();//is not function
console.log(nokia.size);//5.5inch⭐可以
// ES6
class Phone {
//静态属性
static name = '手机';
static change() {
console.log("我可以改变世界");
}
}
let nokia = new Phone();
console.log(nokia.name);//underfined
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 chuizi = new SmartPhone('锤子', 2499, '黑色', '5.5inch');
console.log(chuizi);//SmartPhone brand: "锤子" color: "黑色 price: 2499 size: "5.5inch" 原型方法子 smartPhone 父 phone
复制代码
类继承
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);// Phone.call(this, brand, price)
this.color = color;
this.size = size;
}
photo() {
console.log("拍照"); //2.拍照
}
playGame() {
console.log("玩游戏");//3.玩游戏
}
call() {
console.log('我可以进行视频通话'); //1.我可以进行视频通话
}
}
const xiaomi = new SmartPhone('小米', 799, '黑色', '4.7inch');
console.log(xiaomi);//SmartPhone {brand: '小米', price: 799, color: '黑色', size: '4.7inch'} 子类 constructor=> class SmartPhone 方法 f photo f call父类 call
xiaomi.call();//1
xiaomi.photo();//2
xiaomi.playGame();//3
复制代码
子类对付类方法重写
声明同名方法 子类不能直接调父类同名方法 使用super也不行 普通成员方法里不能出现super去调父类同名方法. 只能完全重写
class中set和get 对对象属性方法绑定
// get 和 set
class Phone {
get price() {
console.log("价格属性被读取了");
return 'iloveyou';
}
set price(newVal) {
console.log('价格属性被修改了');
}
}
//实例化对象
let s = new Phone();
console.log(s.price);//价格属性被读取了 iloveyou
s.price = 'free';//价格属性被修改了
复制代码
数值扩展
//0. 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(0.1 + 0.2 === 0.3);//false
console.log(equal(0.1 + 0.2, 0.3))//true
//1. 二进制和八进制
let b = 0b1010;
let o = 0o777;
let d = 100;
let x = 0xff;
console.log(x);//255
//2. Number.isFinite 检测一个数值是否为有限数
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(Number.isNaN(123));//false
//4. Number.parseInt Number.parseFloat字符串转整数
console.log(Number.parseInt('5211314love'));//5211314
console.log(Number.parseFloat('3.1415926神奇'));//3.1415926
//5. Number.isInteger 判断一个数是否为整数
console.log(Number.isInteger(5));//true
console.log(Number.isInteger(2.5));//false
//6. Math.trunc 将数字的小数部分抹掉
console.log(Math.trunc(3.5));//3
//7. Math.sign 判断一个数到底为正数 负数 还是零
console.log(Math.sign(100));//1
console.log(Math.sign(0));//0
console.log(Math.sign(-20000));//-1
复制代码
对象方法扩展
//1. 🍎Object.is 判断两个值是否完全相等
console.log(Object.is(120, 120));// true
console.log(Object.is(NaN, NaN));// true
console.log(NaN === NaN);// false
//2. 🍎Object.assign 对象的合并
const config1 = {
host: 'localhost',
port: 3306,
name: 'root',
pass: 'root',
test: 'test'
};
const config2 = {
host: 'http://atguigu.com',
port: 33060,
name: 'atguigu.com',
pass: 'iloveyou',
test2: 'test2'
}
console.log(Object.assign(config1, config2));//host: "http://atguigu.com" name: "atguigu.com" pass: "iloveyou" port: 33060test: "test" test2: "test2"
//3. 🍎Object.setPrototypeOf 设置原型对象 Object.getPrototypeof
const school = {
name: '车车'
}
const cities = {
xiaoqu: ['北京', '上海', '深圳']
}
Object.setPrototypeOf(school, cities);
console.log(Object.getPrototypeOf(school));//xiaoqu: (3) ['北京', '上海', '深圳']
console.log(school);//name: "车车" 子类 xiaoqu(3) ['北京', '上海', '深圳'] 父类 构造函数 object
复制代码
ES6模块化
将一个大程序文件,拆分许多小文件,然后将小文件组合起来 好处:
1)防止命名冲突
2)代码复用
3)高维护性
模块化语法 A方法
export命令用于规定模块对外接口
import命令用于输入其他模块提供的功能
以下方法一一对应 m1.js
//🍎分别暴漏
export let school = '123'
export function()
{
console.log('234')
}
//🍎统一暴漏
let school = '123'
function find()
{
console.log('234')
}
export {school,find}
//🍎默认暴漏
export default{
school:'123'
change:function(){console.log('234')}
复制代码
html
<script type='module'>
//🍎通用方式
import * as m1 from './m1.js'
console.log(m1)
//🍎解构赋值
import {school,change} from './m1.js'
console.log(school)
//名字重复 使用`别名
import {school as zz,change} from './m1.js'
console.log(zz)
//🍎默认暴漏解决
import {default as m1} from './m1.js'
或
import m1 from './m1.js'
//该方式只针对默认暴漏
console.log(m1)
</script>
复制代码
es6 module B方法
app.js
//模块引入`
import * as m1 from './m1.js'
//使用js
m1.change();
....
复制代码
html
<script src='./app.js type='module' />
复制代码
解决兼容性 项目中采用方式 转es5
1.安装工具 babel-cli babel-preset-env browserify(或webpack)打包工具 -D
2.npx babel src/js dist/js --presets=babel-preset-env
3.打包 npx browserify dist/js/app.js -o dist/bundle.js
html 报错
<script src="/dist/js/app.js"/>
复制代码
正确
<script src="dist/bundle.js"/>
复制代码
4.不断进行打包
案例 使用jq改背景色
- npm i jquery 2.app.js
import $ from 'jquery'
//正常使用jq代码
...
复制代码
3.打包
ES7
Array.prototypr.includes
数组方法 检测数组中是否包含某个元素 返回布尔值
// includes indexOf
const mingzhu = ['西游记', '红楼梦', '三国演义', '水浒传'];
//判断
console.log(mingzhu.includes('西游记'));//true
console.log(mingzhu.includes('金瓶梅'));//false
复制代码
指数操作符
引入指数运算符 ** 实现幂运算 功能与Math.pow相同
// **
console.log(2 ** 10);// 1024
console.log(Math.pow(2, 10));//1024
复制代码
ES8
async和await
解决异步
async函数
async函数的返回值为promise对象
promise对象的结果由async函数执行的返回值决定
//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);
})
复制代码
await表达式
await必须写在async函数中
await右侧的表达式一般为promise对象
await返回的是promise成功的值
await的promise失败了,就会抛出异常,需要通过try catch 捕获处理
创建 promise 对象
const p = new Promise((resolve, reject) => {
resolve("用户数据");
// reject("失败啦!");//需要用try catch捕获
})
// await 要放在 async 函数中.
async function main() {
try {
let result = await p;
//
console.log(result);
} catch (e) {
console.log(e);
}
}
//调用函数
main();
复制代码
结合使用 读取多个文件
//1. 引入 fs 模块
const fs = require("fs");
//读取『为学』
function readWeiXue() {
return new Promise((resolve, reject) => {
fs.readFile("./resources/为学.md", (err, data) => {
//如果失败
if (err) reject(err);
//如果成功
resolve(data);
})
})
}
function readChaYangShi() {
return new Promise((resolve, reject) => {
fs.readFile("./resources/插秧诗.md", (err, data) => {
//如果失败
if (err) reject(err);
//如果成功
resolve(data);
})
})
}
function readGuanShu() {
return new Promise((resolve, reject) => {
fs.readFile("./resources/观书有感.md", (err, data) => {
//如果失败
if (err) reject(err);
//如果成功
resolve(data);
})
})
}
//声明一个 async 函数
async function main(){
//获取为学内容
let weixue = await readWeiXue();
//获取插秧诗内容
let chayang = await readChaYangShi();
// 获取观书有感
let guanshu = await readGuanShu();
console.log(weixue.toString());
console.log(chayang.toString());
console.log(guanshu.toString());
}
main();
复制代码
结合使用 封装ajax请求
// 发送 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.com/api/?version=v1&city=%E5%8C%97%E4%BA%AC&appid=23941491&appsecret=TXoD5e8P')
console.log(tianqi);
}
main();
复制代码
对象方法扩展 Objext.values和Object.entries
Objext.values()方法返回一个给定对象的所有可枚举属性值的数组
Object.entries()方法返回一个给定对象自身可遍历属性[key,vakue]的数组
Object.getOwnPropertyDescriptors
该方法返回指定对象所有自身属性的描述对象
//声明对象
const school = {
name: "车车",
cities: ['北京', '上海', '深圳'],
xueke: ['前端', 'Java', '大数据', '运维']
};
//获取对象所有的键
console.log(Object.keys(school));//Array(3) 0: "name" 1: "cities" 2: "xueke"
//获取对象所有的值
console.log(Object.values(school));//: "车车" 1: Array(3) 0: "北京" 1: "上海" 2: "深圳" length: 3 [[Prototype]]: Array(0) 2: Array(4) 0: "前端"1: "Java" 2: "大数据"3: "运维"
//entries
console.log(Object.entries(school));//键· 值
//创建 Map
const m = new Map(Object.entries(school));
console.log(m.get('cities'));//['北京', '上海', '深圳'],
//对象属性的描述对象
console.log(Object.getOwnPropertyDescriptors(school));//Object school cites xueke
// create 第一个原型对象 第二个描述对象
const obj = Object.create(null, {
name: {
//设置值
value: '车车',
//属性特性
writable: true,
configurable: true,
enumerable: true
}
});
复制代码
ES9
针对对象的rest参数与扩展与运算符
//rest 参数 其余存user里面
function connect({ host, port, ...user }) {
console.log(host);//127.0.0.1
console.log(port);//3306
console.log(user);
}
connect({
host: '127.0.0.1',
port: 3306,
username: 'root',
password: 'root',
type: 'master'
});
//对象合并 解析出来合并
const skillOne = {
q: '天音波'
}
const skillTwo = {
w: '金钟罩'
}
const skillThree = {
e: '天雷破'
}
const skillFour = {
r: '猛龙摆尾'
}
const mangseng = { ...skillOne, ...skillTwo, ...skillThree, ...skillFour };
console.log(mangseng)
// ...skillOne => q: '天音波', w: '金钟罩'
复制代码
正则扩展 命名捕获分组
对捕获的结果添加属性 方便提取
//声明一个字符串
let str = '<a href="http://www.atguigu.com">车车</a>';
// //提取 url 与 『标签文本』
const reg = /<a href="(.*)">(.*)<\/a>/;
// //执行
const result = reg.exec(str);
console.log(result);//<a href="http://www.atguigu.com">车车</a>
console.log(result[1]);//http://www.atguigu.com
console.log(result[2]);//车车
let str = '<a href="http://www.atguigu.com">车车</a>';
// //分组命名
const reg = /<a href="(?<url>.*)">(?<text>.*)<\/a>/;
const result = reg.exec(str);
console.log(result.groups.url);//http://www.atguigu.com
console.log(result.groups.text);//车车
复制代码
正则扩展 反向断言
判断匹配结果正确与否
//声明字符串
let str = 'JS5211314你知道么555啦啦啦';
//正向断言 数字提取555 根据后面内容判断前面内容是否合法
// const reg = /\d+(?=啦)/;
// const result = reg.exec(str);
//反向断言 根据前面内容 做一个判断
const reg = /(?<=么)\d+/;
const result = reg.exec(str);
console.log(result);
复制代码
正则扩展 dotAll模式
//dot . 元字符 除换行符以外的任意单个字符
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>\s+<a>(.*?)<\/a>\s+<p>(.*?)<\/p>/;
⭐⭐⭐或
dotall模式 g全局匹配
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);//Array(2) 0: { title: '肖生克的救赎', time: '上映日期: 1994-09-10' } 1: { title: '阿甘正传', time: '上映日期: 1994-07-06' }
复制代码
ES10
Object.fromEntries
创建对象 接收二维数组 map
//二维数组 键 值
const result = Object.fromEntries([
['name', '尚硅谷'],
['xueke', 'Java,大数据,前端,云计算']
]);
console.log(result);//Object name: "尚硅谷" xueke: "Java,大数据,前端,云计算"
//Map // 把二维数组转为对象
const m = new Map();
m.set('name', 'ATGUIGU');
const result = Object.fromEntries(m);
console.log(result);//Object name: "ATGUIGU"
//Object.entries ES8 把对象转为二维数组
const arr = Object.entries({
name: "尚硅谷"
})
console.log(arr); //Array(1)=>0: Array(2) 0: "name" 1: "尚硅谷"
复制代码
trimStar与trimEnd
let str = ' iloveyou ';
console.log(str);// iloveyou 完整留空白
console.log(str.trimStart());// iloveyou 清除左
console.log(str.trimEnd());// iloveyou 清除右
复制代码
flat与flatMap
//flat 平
//将多维数组转化为低维数组
const arr = [1, 2, 3, 4, [5, 6]];
console.log(arr.flat());//[1, 2, 3, 4,5, 6];
const arr = [1, 2, 3, 4, [5, 6, [7, 8, 9]]];
//参数为深度 是一个数字 变一维
console.log(arr.flat(2));//[1, 2, 3, 4, 5, 6,7, 8, 9]
//flatMap map结果维度降低
const arr = [1, 2, 3, 4];
const result = arr.map(item => item * 10);
console.log(result);//[10,20,30,40]
// 返回是[10] [20] [30] [40]数组 下面
const result = arr.flatMap(item => [item * 10]);
console.log(result); //Array(4) 0: 10 1: 20 2: 30 3: 40
复制代码
Symbol.prototype.description
获取symbol描述字符串
//创建 Symbol
let s = Symbol('尚硅谷');
console.log(s.description);//尚硅谷
复制代码
ES11
私有属性
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);//18
console.log(this.#weight);//45kg
}
}
girl.intro(); //⭐上面调用打印
//实例化
const girl = new Person('晓红', 18, '45kg');
console.log(girl.name);//晓红
console.log(girl.#age);//报错 外部私有属性访问不到
console.log(girl.#weight);//报错 外部私有属性访问不到
复制代码
Promise.allSettled
接收promise数组,返回结果promise对象
每一个异步任务都想得到结果 用Promise.allSettled
要求每一个异步任务成功才能继续执行 用Promise.all
//声明两个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]);
console.log(result);
复制代码
const res = Promise.all([p1, p2]);
console.log(res);
复制代码
区别
String.prototype.matchAll
字符传扩展方法 用来得到正则批量匹配的结果⭐⭐⭐实用
//需求 把每一个电影名称和上映时间提取出来
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);
复制代码
可选链操作符
?. 配合使用
当应对对象类型参数时 对象层级深
// 传入对象
function main(config) {
1.
const dbHost = config && config.db && config.db.host;
console.log(dbHost);//⭐192.168.1.100
//两种方式
2.可选链操作符
const dbHost = config?.db?.host;
console.log(dbHost);//⭐192.168.1.100
}
main({
db: {
host: '192.168.1.100',
username: 'root'
},
cache: {
host: '192.168.1.200',
username: 'admin'
}
})
复制代码
动态import
hello.js
export function hello(){
alert('Hello');
}
复制代码
app.js
const btn = document.getElementById('btn');
btn.onclick = function(){
import('./hello.js').then(module => {
module.hello();
});
}
复制代码
html 引入使用
<body>
<button id="btn">点击</button>
<script src="./js/app.js" type="module"></script>
</body>
复制代码
bigint
//大整形
let n = 521n;
console.log(n, typeof (n));//521n 'bigint'
//函数
// let n = 123;
console.log(BigInt(n)); //521n
console.log(BigInt(1.2));//报错 Uncaught RangeError: The number 1.2 cannot be converted to a BigInt because it is not an integer 浮点型不可以
//大数值运算
let max = Number.MAX_SAFE_INTEGER;
console.log(max); //9007199254740991
console.log(max + 1); //9007199254740992
console.log(max + 2); //9007199254740992
console.log(BigInt(max)) //9007199254740991n
console.log(BigInt(max) + BigInt(1)) //9007199254740992n
console.log(BigInt(max) + BigInt(2)) //9007199254740993n
复制代码
globalThis 对全局对象做操作 忽略操作环境
全局this
无论执行环境是什么,始终指向全局对象
html
<body>
<script>
console.log(globalThis); //指向window对象
</script>
</body>
复制代码
js run code 运行该js文件
console.log(globalThis); //指向global
复制代码