let a;
let b,c,d;
let e=100;
let f=521,g="iloveyou",h=[]
let 关键字用来声明变量,使用 let 声明的变量有几个特点:
let star='罗志祥';
let star='小猪' //error
//但使用var 重复定义 star 不会报错,因此要使用let,防止变量污染
全局,函数,eval
{
let girl='周扬青'
}
console.log(girl) //error
不仅仅针对花括号,例如if 、else、while、for里面
console.log(song) //error
let song='恋爱达人'
//var可变量提升,在变量定义之前可以使用,不会报错
{
let school='abc'
function fn(){
console.log(school) //abc
}
fn()
}
应用场景:以后声明变量使用 let 就对了
Title
const ABC = 'abc'
const 关键字用来声明常量,const 声明有以下特点:
const A; //error
{
const pyaler = 'uzi'
}
console.log(player) //error
const TEAM = ['uzi','MXLG','Ming','Letme'];
TEAM.push('Meiko'); //不报错,常量地址没有发生变化
TEAM = 100 //error
注意: 对象属性修改和数组元素变化不会出发 const 错误
应用场景:声明对象类型使用 const,非对象类型声明选择 let
ES6 允许按照一定模式从数组和对象中提取值,对变量进行赋值,这被称为解构赋值。
数组的解构(不常用)
const F4 = ['小沈阳','刘能','赵四','宋小宝']
let [xiao,liu,zhao,song] = F4;
console.log(xiao)
console.log(liu)
console.log(zhao)
console.log(song)
对象的解构(常用)
const zhao = {
name : '赵本山',
age: '不详',
xiaopin: function(){
console.log("我可以演小品")
}
}
let {name,age,xiaopin} = zhao;
console.log(name);
console.log(age);
console.log(xiaopin);
xiaopin();
// 不用以上方法的话,使用xiaopin方法时,需要 zhao.xiaopin()
// 使用以上方法结构,只需要 xiaopin() ,不用带前面的 zhao.
复杂结构
let wangfei = {
name: '王菲',
age: 18,
songs: ['红豆', '流年', '暧昧', '传奇'],
history: [
{name: '窦唯'},
{name: '李亚鹏'},
{name: '谢霆锋'}
]
};
let {songs: [one, two, three], history: [first, second, third]} =
wangfei;
注意:频繁使用对象方法、数组元素,就可以使用解构赋值形式
模板字符串(template string)是增强版的字符串,用反引号(`)标识,特点:
// 声明
let str = `我也是一个字符串`
console.log(str,typeof str);
// 特性1:内容中可以直接出现换行符
// 否则之前使用 ""+ 进行拼接
let str = `
- 沈腾
- 玛丽
- 魏翔
- 艾伦
`;
// 特性2:变量拼接
let lovest = '魏翔';
let out = `${lovest}在前几年离开了开心麻花`;
console.log(out)
注意:当遇到字符串与变量拼接的情况使用模板字符串
ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法。这样的书写更加简洁。
属性名和变量名相同的话,可以进行简化。
let name = '尚硅谷';
let slogon = '永远追求行业更高标准';
let improve = function () {
console.log('可以提高你的技能');
}
//属性和方法简写
let atguigu = {
name, //name:name, 简写成 name
slogon, //slogon:slogon, 简写成 slogon
improve,
change() {
console.log('可以改变你')
}
}
注意:对象简写形式简化了代码,所以以后用简写就对了
ES6 允许使用「箭头」(=>)定义函数。
/**
* 1. 通用写法
*/
let fn = (arg1, arg2, arg3) => {
return arg1 + arg2 + arg3;
}
fn(1,2,3)
function A(){
console.log(this.name)
}
let B = () => {
console.log(this.name);
}
window.name = '尚硅谷';
const school = {
name: 'ATGUIGU'
}
//直接调用
A() //尚硅谷
B() //尚硅谷
//call 改变作用域
A.call(school); //ATGUIGU
B.call(school); //尚硅谷 箭头函数的this值未改变
let A = (name,age) => {
this.name=name;
this.age=age;
}
let me = new A('xiao',123);
console.me //error
(arguments变量是用来保存实参的)
let fn = () => {
console.log(arguments);
}
fn(1,2,3) //error
let add = n => {
return n + 1;
}
let add = n => n+1;
注意:箭头函数不会更改 this 指向,用来指定回调函数会非常合适
箭头函数实践
function add(a,b,c=12){
return a+b+c;
}
let result = add (1,2);
console.log(result) // 15
function A({host='127.0.0.1',username,password,port}){
console.log(host+username+password+port)
}
A({
host:"shangguigu.com",
username:'ran',
password:'123456',
port:3306
})
// 传参了,使用传的值,没传参使用默认值
ES6 引入 rest 参数,用于获取函数的实参,用来代替 arguments
/**
* 作用与 arguments 类似
*/
function add(...args){
console.log(args);
}
add(1,2,3,4,5); //得到的是一个数组,可以使用数字的一些方法:filter、some、every、map
/**
* rest 参数必须是最后一个形参
*/
function minus(a,b,...args){
console.log(a,b,args);
}
minus(100,1,2,3,4,5,19);
注意:rest 参数非常适合不定个数参数函数的场景
扩展运算符(spread)也是三个点(…)。它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列,对数组进行解包。
特性
const tfboys=['AA','BB','CC']
function chunwan(){
console.log(arguments);
}
chunwan(...tfboys); //0:'AA' 1:'BB' 2:'CC'
rest 参数 和 spread区别:
rest 参数 : function add(…args) 是放在函数传参
spread: fn(…tfboys) 是放在调用函数时
应用
const A = ['aa','bb'];
const B = ['cc','dd'];
//方法1:
const C = A.concat(B)
console.log(C) //[aa,bb,cc,dd]
//方法2:(推荐)
const C = [...A,...B];
console.log(C) //[aa,bb,cc,dd]
const A = ['a','b','c'];
const B = [...A];
console.log(B) //[a,b,c]
const A = documents.querySelectorAll('div');
const B = [...A];
console.log(B) // [div,div,div]
ES6 引入了一种新的原始数据类型 Symbol,表示独一无二的值。它是JavaScript 语言的第七种数据类型,是一种类似于字符串的数据类型。
Symbol 特点:
// 1. 创建
//创建 Symbol
let s1 = Symbol();
console.log(s1, typeof s1); //内部实现唯一性,我们看不到
//添加标识的 Symbol
let s2 = Symbol('尚硅谷');
let s2_2 = Symbol('尚硅谷');
console.log(s2 === s2_2); //false
//使用 Symbol for 定义
let s3 = Symbol.for('尚硅谷');
let s3_2 = Symbol.for('尚硅谷');
console.log(s3 === s3_2); //true
// 2. 不能与其他数据进行运算
let result = s + 100 //error
let result = s > 100 //error
let result = s + s //error
// 数据类型
// USONB you are so niubility
u undefined
s string symbol
o object
n bull number
b boolean
// 3.Symbol内置值
class Person {
static [Symbol.hasInstance](param){
console.log(param);
console.log("我被用来检测了");
return false;
}
}
let o = {};
console.log(o instanceof Person); //我被用来检测了,false
注: 遇到唯一性的场景时要想到 Symbol
let game = {
name : 'ran'
}
let methods = {
up:Symbol()
down:Symbol()
}
game[methods.up]=function(){
console.log('aaa');
}
game[methods.down]=function(){
console.log('bbb');
}
console.log(game) // name: 'ran',Symbol(),Symbol()
let youxi = {
name: '狼人杀',
[Symbol('say')]:function(){
console.log('阿萨德')
}
}
console.log(youxi) // name:'狼人杀',Symbol(say)
除了定义自己使用的 Symbol 值以外,ES6 还提供了 11 个内置的 Symbol 值,指向语言内部使用的方法。可以称这些方法为魔术方法,因为它们会在特定的场景下自动执行。
迭代器(Iterator)就是一种机制。它是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署 Iterator 接口,就可以完成遍历操作。
ES6 创造了一种新的遍历命令 for…of 循环,Iterator 接口主要供 for…of 消费
原生具备 iterator 接口的数据(可用 for of 遍历)
a) Array
b) Arguments
c) Set
d) Map
e) String
f) TypedArray
g) NodeList
a) 创建一个指针对象,指向当前数据结构的起始位置
b) 第一次调用对象的 next 方法,指针自动指向数据结构的第一个成员
c) 接下来不断调用 next 方法,指针一直往后移动,直到指向最后一个成员
d) 每调用 next 方法返回一个包含 value 和 done 属性的对象
注: 需要自定义遍历数据的时候,要想到迭代器
const xiyou=['AA','BB','CC','DD'];
//for in保存的是键名,for of保存的是键值
// for(let v of xiyou){
// console.log(v) // 'AA','BB','CC','DD'
// }
let iterator = xiyou[Symbol.iterator]();
console.log(iterator.next()); //{{value:'唐僧',done:false}}
console.log(iterator.next()); //{{value:'孙悟空',done:false}}
const banji = {
name : "终极一班",
stus: [
'aa',
'bb',
'cc',
'dd'
],
[Symbol.iterator](){
let index = 0;
let _this = this;
return {
next: () => {
if(index < this.stus.length){
const result = {value: _this.stus[index],done: false};
//下标自增
index++;
//返回结果
return result;
}else {
return {value: underfined,done:true};
}
}
}
}
}
for(let v of banji){
console.log(v); // aa bb cc dd
}
生成器函数是 ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同
// 生成器其实就是一个特殊的函数
//异步编程 纯回调函数 node 方式 ajax mongodb
function * gen (){ //函数名和function中间有一个 *
yield '耳朵'; //yield是函数代码的分隔符
yield '尾巴';
yield '真奇怪';
}
let iterator = gen();
console.log(iteretor.next());
//{value:'耳朵',done:false} next()执行第一段,并且返回yield后面的值
console.log(iteretor.next()); //{value:'尾巴',done:false}
console.log(iteretor.next()); //{value:'真奇怪',done:false}
代码说明:
function * gen(args){
console.log(args);
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());
console.log(iterator.next('BBB')); //next中传入的BBB将作为yield 111的返回结果
console.log(iterator.next('CCC')); //next中传入的CCC将作为yield 222的返回结果
console.log(iterator.next('DDD')); //next中传入的DDD将作为yield 333的返回结果
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 one(){
setTimeout(()=>{
let data='用户数据';
iterator.next(data)
},1000)
}
function two(){
setTimeout(()=>{
let data='订单数据';
iterator.next(data)
},2000)
}
function three(){
setTimeout(()=>{
let data='商品数据';
iterator.next(data)
},3000)
}
function * gen(){
let users=yield one();
console.log(users)
let orders=yield two();
console.log(orders)
let goods=yield three();
console.log(goods)
}
let iterator = gen();
iterator.next();
Promise 主要解决回调地狱的问题,是 ES6 引入的异步编程的新解决方案。语法上 Promise 是一个构造函数,用来封装异步操作并可以获取其成功或失败的结果。
Promise的三种状态:初始化,成功,失败
//1. 引入 fs 模块
const fs = require('fs');
//2. 调用方法读取文件 (方法1)(问题:会存在回调地狱的问题)
// fs.readFile('./resources/为学.md', (err, data)=>{
// //如果失败, 则抛出错误
// if(err) throw err;
// //如果没有出错, 则输出内容
// console.log(data.toString());
// });
//3. 使用 Promise 封装 (方法2)
const p = new Promise(function(resolve, reject){
fs.readFile("./resources/为学.mda", (err, data)=>{
//判断如果失败
if(err) reject(err);
//如果成功
resolve(data);
});
});
p.then(function(value){
console.log(value.toString());
}, function(reason){
console.log("读取失败!!");
});
//catch()函数只有一个回调函数,意味着如果Promise对象状态为失败就会调用catch()方法并且调用回调函数
//引入 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'));
});
ES6 提供了新的数据结构 Set(集合)。它类似于数组,但成员的值都是唯一的,集合实现了 iterator 接口,所以可以使用『扩展运算符…』和『for…of…』进行遍历,集合的属性和方法:
//应用
ES6 提供了 Map 数据结构。它类似于对象,也是键值对的集合。但是“键”
的范围不限于字符串,各种类型的值(包括对象)都可以当作键。Map 也实现了
iterator 接口,所以可以使用『扩展运算符…』和『for…of…』进行遍历。Map 的属
性和方法:
ES6 提供了更接近传统语言的写法,引入了 Class(类)这个概念,作为对象的模板。通过 class 关键字,可以定义类。基本上,ES6 的 class 可以看作只是一个语法糖,它的绝大部分功能,ES5 都可以做到,新的 class 写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。
知识点:
//父类
class Phone {
//构造方法
// constructor 这个名字不能修改,在进行new Phone时,自动执行
constructor(brand, color, price) {
this.brand = brand;
this.color = color;
this.price = price;
}
//对象方法,只能使用 方法名(){} 的写法,不能使用 方法名:function(){}
call() {
console.log('我可以打电话!!!')
}
}
//子类
class SmartPhone extends Phone {
constructor(brand, color, price, screen, pixel) {
super(brand, color, price);
this.screen = screen;
this.pixel = pixel;
}
//子类方法
photo(){
console.log('我可以拍照!!');
}
playGame(){
console.log('我可以玩游戏!!');
}
//方法重写
call(){
console.log('我可以进行视频通话!!');
}
//静态方法
static run(){
console.log('我可以运行程序')
}
static connect(){
console.log('我可以建立连接')
}
}
//实例化对象
const Nokia = new Phone('诺基亚', '灰色', 230);
const iPhone6s = new SmartPhone('苹果', '白色', 6088,
'4.7inch','500w');
//调用子类方法
iPhone6s.playGame();
//调用重写方法
iPhone6s.call();
//调用静态方法
SmartPhone.run();
ES5构造函数继承
Class的类继承
ES6 提供了二进制和八进制数值的新的写法,分别用前缀 0b 和 0o 表示。
Number.isFinite() 用来检查一个数值是否为有限的
Number.isNaN() 用来检查一个值是否为 NaN
ES6 将全局方法 parseInt 和 parseFloat,移植到 Number 对象上面,使用不变。
用于去除一个数的小数部分,返回整数部分。
Number.isInteger() 用来判断一个数值是否为整数
ES6 新增了一些 Object 对象的方法
模块化是指将一个大的程序文件,拆分成许多小的文件,然后将小文件组合起来。
模块化的优势有以下几点:
ES6 之前的模块化规范有:
模块功能主要由两个命令构成:export 和 import。
导出语法汇总
// m1.js
export let school = '尚硅谷'
export function teach(){
console.log('教技能')
}
// index.html
// m2.js
//统一暴露
let school = '尚硅谷';
function findjob(){
console.log('找工作吧');
}
export {school,findjob}
// index.html
//m3.js
//默认暴露
export default {
school:'ATGUIGU',
change:function(){
console.log('我们可以改变你')
}
}
// index.html
引入语法汇总
import * as m1 from "./src/js/m1.js"
import * as m2 from "./src/js/m2.js"
import * as m3 from "./src/js/m3.js"
import {school,teach} from "./src/js/m1.js"
import {school as guigu,findJob} from "./src/js/m2.js"
import {default as m3 } from "./src/js/m3.js" // 必须给default起个别名
简便形式(只针对默认暴露)
只能针对默认暴露
import m3 from "./src/js/m3.js"
// app.js
import * as m1 from "./src/js/m1.js"
import * as m2 from "./src/js/m2.js"
import * as m3 from "./src/js/m3.js"
//index.html
//不推荐 原因:浏览器的兼容问题
// 推荐 把es6转化为es5的语法
Includes 方法用来检测数组中是否包含某个元素,返回布尔类型值
在 ES7 中引入指数运算符「**」,用来实现幂运算
,功能与 Math.pow 结果相同
async 和 await 两种语法结合可以让异步代码像同步代码一样
async function fn(){
//1.如果返回的是一个非Promise的对象,则fn()返回的结果就是成功状态的Promise对象,值为返回值
return "尚硅谷";
return ;
//2.如果返回的是一个Promise对象,则fn()返回的结果与内部Promise对象的结果一致
throw new Error("出错了")
//3.如果返回的是抛出错误,则fn()返回的就是失败状态的Promise对象
return new Promise((resolve,reject)=>{
resolve('成功的数据');
// reject("失败的错误")
});
}
const result = fn();
result.then(value=>{
console.log(value) //成功的数据
},reason=>{
console.log(reason)
})
async 和await 结合读取文件
//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请求
该方法返回指定对象所有自身属性的描述对象
Rest 参数与 spread 扩展运算符在 ES6 中已经引入,不过 ES6 中只针对于数组,
在 ES9 中为对象提供了像数组一样的 rest 参数和扩展运算符
ES9 允许命名捕获组使用符号『?』,这样获取捕获结果可读性更强
let str = '尚硅谷';
const reg = /(?.*)<\/a>/;
const result = reg.exec(str);
console.log(result.groups.url);
console.log(result.groups.text);
ES9 支持反向断言,通过对匹配结果前面的内容进行判断,对匹配进行筛选。
//声明字符串
let str = 'JS5211314 你知道么 555 啦啦啦';
//正向断言
const reg = /\d+(?=啦)/;
const result = reg.exec(str);
//反向断言
const reg = /(?<=么)\d+/;
const result = reg.exec(str);
console.log(result);
正则表达式中点.匹配除回车外的任何单字符,标记『s』改变这种行为,允许行
终止符出现
let str = `
`;
//声明正则
const reg = /.*?(.*?)<\/a>.*?(.*?)<\/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);
用来创建一个对象,参数是一个数组或者是map对象。
将二维数组转为对象,而ES8 中 Object.entries 方法是把对象转化为数组
**trimStart :**清除字符串左侧的字符
**trimEnd:**清除字符串右侧的字符
**flat:**将多维数组转化为低维数组
**flatMap:**将map对象进行降维
用来获取Symbol的字符串描述
let s = Symbol('尚硅谷');
console.log(s.description) //尚硅谷
allSettled 和all 方法,主要用于批量处理异步任务。
let str = ``;
//声明正则
const reg = /.*?(.*?)<\/a>.*?(.*?)<\/p>/sg
//调用方法
const result = str.matchAll(reg); //返回的是一个可迭代对象
//展开可迭代对象 方法1
// for(let v of result){
// console.log(v);
// }
//展开可迭代对象 方法2
const arr = [...result];
console.log(arr);
免去层层判断的麻烦
//相当于一个判断符,如果前面的有,就进入下一层级
function main(config){
const dbHost = config?.db?.host //等价于 config && config.db && 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'
}
})
// hello.js
export function hello(){
alert('Hello');
}
// app.js
// import * as m1 from "./hello.js"; //静态传入
//获取
const btn = document.getElementById('btn');
btn.onclick = function(){
//使用之前并未引入,动态引入,返回的其实是一个Promise对象
// 使用的时候再进行传入,import函数,参数是路径
import('./hello.js').then(module => {
module.hello();
});
}
// index.html
动态 import
//大整型
let n = 521n;
console.log(n,typeof(n)) // 521n n
//函数 将整型转为大整型
let n = 123;
console.log(BigInt(n)) // 123n //不要使用浮点型,只能用int
//大数值运算
let max = Number.MAX_SAFE_INTEGER; // 9007199254740991
console.log(max +1) // 9007199254740992
console.log(max +2) // 9007199254740992 出问题了
console.log(BigInt(max)+BigInt(1)) 9007199254740992n
console.log(BigInt(max)+BigInt(2)) 9007199254740993n
始终指向全局对象
console.log(globalThis) //window //适用于复杂环境下直接操作window