一.let const var
1.块级作用域
块级作用域就是使用一对大括号包裹的一段代码,比如函数、判断语句、循环语句,甚至单独的一个{}都可以被看作是一个块级作用域。
2.声明变量方式(let var)
let声明变量时没有不会声明提升 存在暂时性死区
使用let关键字声明的变量才具有块级作用域,使用var声明的变量不具备块级作用域特性。
let声明变量时 在同一个块级作用域中 不能重复声明
使用var声明的变量会进行声明提升 在let声明变量之前访问会放置暂时性死区(在声明之前访问会报错) 声明之后正常访问
3.const 常量
const声明的变量不可以改变
使用const声明变量 必须赋予初始值
常量赋值后,值不能重新赋值修改。如果里面存放是数组和对象可以通过下标修改里面值(可以修改的为对象/数组 里面的值)
4.区别
使用 var 声明的变量,其作用域为该语句所在的函数内,且存在变量提升现象。
使用 let 声明的变量,其作用域为该语句所在的代码块内,不存在变量提升,不可以在同一个块级作用域中重复声明,存在暂时性死区。
使用 const 声明的是常量,在后面出现的代码中不能再修改该常量的值。
二.解构赋值
1.按照一定模式,从数组中或对象中提取值,将提取出来的值赋值给另外的变量。
2.在数组中解构赋值。从数组和对象中提取值,对变量进行赋值,这被称为解构赋值
三.扩展运算符(...)
1.... 和 解构配合使用
2.剩余参数语法允许我们将一个不定数量的参数表示为一个数组。(剩余参数rest)
3.展开对象时需要使用大括号括住
四.数组新增方法
1.Array.from() 将伪数组 转换为数组 第一个参数为需要转换的伪数组 第二个参数为函数
2.Array.of() 用于将一组值,转换为数组
3.find() 用于找出第一个符合条件的数组成员(不写return 也为undefined),如果没有找到返回undefined
4.findLast() 用于找出最后一个符合条件的数组成员(不写return 也为undefined),如果没有找到返回undefined
5.filter() 过滤
6.map() 映射 即原数组映射成一个新的数组
7.findIndex() 用于找出第一个符合条件的数组成员的下标 没有找到则返回 -1
8.includes() 方法返回一个布尔值,表示某个数组是否包含给定的值
该方法的第二个参数表示搜索的起始位置,默认为0。如果第二个参数为负数,则表示倒数的位置,
如果这时它大于数组长度(比如第二个参数为-3,但数组长度为3),则会重置为从0开始。
9.fill() 替换
10.some() 只要有一个数据符合条件 则返回true
11.every() 全部符合条件 返回true
12.entries() 返回数组中的键值对
五.字符串新增方式
1.startsWith() 查看指定字符 是否在原字符串的开头处 返回值为布尔值
2.endsWith() 查看指定字符 是否在原字符串的结尾处 返回值为布尔值
3.repeat(n) 将字符串重复 n 次
4.padStart(); 向字符串开头处填充字符,使整个字符串达到指定长度.
不指定 字符 将以 空格进行填充
5.padEnd() 向字符串末尾处填充字符,使整个字符串达到指定长度
不指定 字符 将以 空格进行填充
6.trimStart() 消除字符串开头处的空格(tab 、回车)
7.trimEnd() 消除字符串结尾处的空格(tab 、回车)
8.replaceAll() 替换字符 将符合条件的字符 全部替换成指定的字符
六.对象新增方法
1.assign() 将多个对象合并到一起 (合并至第一个参数对象内) 该方法返回合并之后的对象
2.is() 用来判断两个参数是否相等 和 === 类似
3.函数的默认值 (注意含有默认值的参数放到所有参数的最后面)
默认参数 当实参没有传递时 使用默认参数 当实参传递时,则使用实参的值
4.对象的简写方式
var name = 'xxx';
var age = 18;
var sex = '男';
var obj = {
name,
age,
sex,
fn(){
}
}
七.箭头函数
1.箭头函数与普通函数的区别 :
写法不同,this指向不同
2.写法
()=>{} 等同于 function(){}
3.this 指向的是箭头函数定义位置的上下文this (外层函数this指向哪个对象 箭头函数中的this也指向哪个对象) /
在箭头函数内 只有一个参数时 可以省略小括号 函数体中只有一句代码,且代码的执行结果就是返回值,可以省略大括号、return
4.使用地方
类似于 定时器、事件绑定、数组方法(以回调函数的方式编写) 等等
八.数据类型
1.6大数据类型:
Number 数字类型
boolean 布尔值类型
undefined 未定义类型
String 字符串类型
null 空类型
Object 对象类型
2.es6中新增一种原始数据类型
symbol
3.特点:
Symbol的值是唯一的,用来解决命名冲突的问题。
不需要使用new 就能创建
通常把它当做属性名或者常量去用
Symbol的值不可以与其他数据类型的值 进行运算。
Symbol 定义的属性不可以使用 for...in 进行遍历,可以使用Reflect.ownKeys() 遍历对象的属性
返回的值是属性的集合;可以使用object.getOwnProperSymbol() 获取所有的symbol 属性
4.Symbol.for()
有时使用同一个 Symbol 值,Symbol.for()方法可以做到这一点。它接受一个字符串作为参数,然后搜索有没有以该参数作为名称的 Symbol 值。如果有,就 返回这个 Symbol 值,否则就新建一个以该字符串为名称的 Symbol 值,并将其注册到全局。
九.set、map数据结构
1.set 数据结构中值都是唯一的,不可重复的,类似于数组
可以方便快捷对数组进行去重
2.Set 结构的实例与数组一样,也拥有forEach方法,用于对每个成员执行某种操作,没有返回值
3.set方法
res.add('') 向 set结构中 添加数据
res.delete('') 删除set结构中 指定的所有数据
res.has('') 查找set结构中 是否包含了指定的数据
res.clear() 清空set结构中所有数据
res.values() 对set结构进行遍历 返回属性值
res.keys() 对set结构进行遍历 返回属性
entries() 对set结构进行遍历 返回键值对(属性和属性值)
4.Map 数据结构
类似于对象
Map 数据结构 与 Object 的区别
属性名 Map可以是任意数据 而 对象只能是 字符串或者 Symbol
Map数据可以有迭代器 可以使用for of 遍历
Map 里面可以使用size属性来统计长度
5.map方法
1.set() 向map中添加数据(键值对)
2.get() 通过属性名字获取属性值
3.delete() 根据属性名字去删除属性
4.has() 判断指定属性名是否存在map数据中 存在返回 true 不存在返回 false
5.clear() 清空
6.size() 长度
6.for...in...
for...of 是 ES6 新引入的循环,用于替代 for..in 和 forEach() ,并且支持新的迭代协议。它可用于迭代常规的数据类型,如 Array 、 String 、 Map 和Set 等等。对象暂时不可以使用 for of 循环
例子
let arr = ['a','b','c','d','e'];
for(let i of arr){
console.log(i) // i : 迭代之后的每一个属性值
}
十.函数
1.普通函数
function fn(){
}
fn()
2.自运行函数
(function(){
console.log(123)
})()
3.回调函数
回调地狱 : 多次嵌套回调函数为回调地狱
function fn(callback){
var res = 50;
callback(res)
}
fn(function(r){
console.log(r)
})
4.递归函数
function fn(){
if(){
return
}
fn()
}
fn()
5.闭包
function Home(){
let ID = '410522200408246418';
function Cat(){
return ID;
}
return Cat;
}
console.log(Home()())
6.构造函数
function Fn(){
}
new Fn();
7.箭头函数
let fn = ()=>{
}
十一.
1. js 预解析
JS有两个特性,一个是单线程,一个是解释性语言。不同于编译性语言,解释性语言通常理解为不整体编译,由解释器解释一句执行一句。但JS不是直接 对着代码解释执行,在解释执行之前,需要进行其他的步骤。
JS运行步骤:语法分析;预编译;解释执行。
预编译有个特点:任何变量,如果未声明就赋值,那该变量为全局变量,并且所有的全局变量都是window的属性。
2.Ao对象
AO对象全称为:activation object (活跃对象/执行期上下文),在函数执行前执行函数预编译,此时会产生一个AO对象,AO对象保存该函数的参数变量。
将函数的参数以及函数里面声明的变量当做AO对象的属性名,值全部为undefined。
将实参的值赋值给形参。
在函数里面声明的函数,函数名作为AO对象的属性名,值赋值给函数体。(若参数名和函数名重叠,则函数体值会覆盖参数值)
3.1.数字的分隔符 _
数值分隔符有几个使用注意点。
不能放在数值的最前面(leading)或最后面(trailing)。
不能两个或两个以上的分隔符连在一起。
小数点的前后不能有分隔符。
科学计数法里面,表示指数的e或E前后不能有分隔符。
4.方法
Number.isFinite() 用来判断 数据 是否为有限的
Number.isNaN() 判断数据是否为NaN类型
Number.isInteger() 用来判断数据 是否为整数
Math.pow(n,m) n的m次幂
Number.isSafeInteger() 判断一个数字 是否在安全整数之间 返回值为布尔值
Math.trunc() 去除小数点后的数字
Math.sign() 判断一个数到底是正数、负数、还是零。对于非数值,会先将其转换为数值。
它会返回五种值。
参数为正数,返回+1;
参数为负数,返回-1;
参数为 0,返回0;
参数为-0,返回-0;
其他值,返回NaN。
5.安全整数
JavaScript 能够准确表示的整数范围在-2^53到2^53之间(不含两个端点),超过这个范围,无法精确表示这个值。
6.排错
try(){
放置 不确定因素
当这里的代码报错时 执行 catch内的代码
没有报错则正常运行
}catch(){
}
7.手动报错
throw new Error()
十二.对象
1.super
当前对象的原型对象
2. Object.defineProperty()
向对象中添加属性.
使用这个方法给对象定义property属性,能够更精确的操作这个属性
示例:
Object.defineProperty(obj,'name',{
get(){
//当name属性被获取时 执行 get方法
console.log('有人访问name属性了')
//name属性被访问时, name属性的值为 get方法的返回值
return res;
},
set(a){
//当name属性被修改时 执行 set方法
res = a;
// set方法的参数接受的数据为 name属性将要修改的值
console.log(a,'有人修改name属性了')
}
})
obj.name = '456';
console.log(obj.name)
方法:
writable:true, 用来设置 属性是否可以被修改 true:可以被修改 false:不可以被修改 (默认为false)
value:'', 用来设置属性值
configurable:false, 描述属性可否删除 true:可以删除 false:不可以删除 (默认为false)
enumerable:false, 描述属性是否会出现在for in 或者 Object.keys()的遍历中 false是不会出现在遍历中 默认是false
模拟响应式数据
let obj = {}
Object.defineProperty(obj,'text',{
get(){
//将修改之后的值 进行返回
return this.res;
},
set(res){ //接受 修改后的数据
//当text属性被修改时 inp和box里的内容也被修改
inp.value = res;
box.innerText = res;
//储存修改后的数据
this.res = res;
}
})
3.Proxy
Proxy给对象进行预处理
new Proxy(参数1,参数2)
参1 obj需要处理的那个对象
参2 {set,get }
当你访问读取Proxy对象里面属性的时候,会自动调用get方法
修改属性的时候会自动触发set方法
let obj = {
name:'xxx',
age:18,
}
let res = new Proxy(obj,{
get(obj,attr,proxyObj){// obj: 原有obj对象 attr:要修改的属性名字 proxyObj: 转换后的proxy对象
// console.log(obj,attr,proxyObj);
return obj[attr];
},
set(obj,attr,value,proxyObj){ // obj: 原有obj对象 attr:要修改的属性名字 value:修改的属性值 proxyObj: 转换后的proxy对象
// console.log(obj,attr,value,proxyObj,'set方法');
obj[attr] = value; //在set方法中修改属性
}
当对当前proxy对象使用 in 运算符时 执行 has方法
has(obj,attr){ obj:原对象 attr:需要检查的属性
if(attr == 'name'){
return false;
}else{
return attr in obj;
}
}
})
res.name = '123';
console.log(res.name)
console.log(res)
4.promise
回调地狱 : 在回调函数中嵌套回调函数
promise对象 解决回调地狱 / 将异步代码用同步流程写出
Promise对象只有三种状态
异步操作“未完成”(pending)
异步操作“已完成”(resolved,又称fulfilled)
异步操作“失败”(rejected)
改变状态的方法只有两种
1. 从“未完成”(pending) => 已完成”(resolved,又称fulfilled)
2. 从“未完成”(pending) => “失败”(rejected)
创建方式
let p = new Promise((resolved,rejected)=>{ resolved: 成功状态(已完成状态) rejected:失败状态
console.log(this)
});
调用 resolved()方法 和 rejected() 改变promise的状态
在promise对象中 只能改变一次状态
这种变化只能发生一次,一旦当前状态变为“已完成”或“失败”,就意味着不会再有新的状态变化了。因此,Promise对象的最终结果只有两种:
ajak
function getJson(type,url,async=true){
return new Promise((resolved,rejected)=>{
let xhr = new XMLHttpRequest();
xhr.open(type,url,async);
xhr.send();
xhr.onreadystatechange = function(){
if(xhr.status == 200){
if(xhr.readyState == 4){
resolved(JSON.parse(xhr.response))
}
}else{
rejected(xhr)
}
}
})
}
getJson('get','http://127.0.0.1:8800/宏志23班/3月/3.13/代码/json/demo1.json')
then: 根据promise的状态 执行相应的函数
.then((res)=>{
console.log(res)
return getJson('get','http://127.0.0.1:8800/宏志23班/3月/3.13/代码/json/demo2.json')
},()=>{
})
.then((res)=>{
console.log(res)
return getJson('get','http://127.0.0.1:8800/宏志23班/3月/3.13/代码/json/demo1.json')
},()=>{
})
.then((res)=>{
console.log(res)
},()=>{
})
catch:promise的状态为失败时执行
p.catch((err)=>{
console.log(err,'catch')
})
finally: 无论 promise状态 为成功 还是失败 都会执行
p.finally(()=>{
console.log(123)
})
Promise.all : 方法接受一个数组作为参数 数组里面要求为Promise 实例
将多个promise对象转成一个promise对象
Promise.all 会返回一个promise对象
res的状态有两种:
1. p1,p2,p3 的状态都为成功 res的状态也为成功
2. p1,p2,p3 中有一个状态为失败 res的状态也为失败
Promise.resolve : 创建promise对象 默认状态为成功 "fulfilled" Promise对象中的数据为传递来的参数
Promise.reject : 创建promise对象 默认状态为失败 "rejected" Promise对象中的数据为传递来的参数
Promise.resolve('abc') 等价于 new Promise((resolved,rejected)=>{ resolved('abc') })
Promise.reject('abc') 等价于 new Promise((resolved,rejected)=>{ rejected('abc') })
Promise.race() : 将多个 Promise 对象,包装成一个新的 Promise 对象。
let p = Promise.race([p1,p2,p3]); p1,p2,p3中谁的状态先改变 p就为谁的状态 (例如 p1的状态先改变 , 那么p的状态则为p1的状态)
十三.迭代器
Iterator 是 ES6 引入的一种新的遍历机制,迭代器有两个核心概念:
1.迭代器是一个统一的接口,它的作用是使各种数据结构可被便捷的访问,它是通过一个键为Symbol.iterator 的方法来实现。
2.迭代器是用于遍历数据结构元素的指针
迭代过程
通过 Symbol.iterator 创建一个迭代器,指向当前数据结构的起始位置
随后通过 next 方法进行向下迭代指向下一个位置, next 方法会返回当前位置的对象,对象包含了 value 和 done 两个属性, value 是当前属性的值,
done 用于判断是否遍历结束 done 为 true 时则遍历结束
3.迭代器 iterator 专门供于 for of 进行使用
4.概念: iterator是一种接口机制,为各种不同的数据结构提供统一的访问机制
作用:
1、为各种数据结构,提供一个统一的、简便的访问接口;
2、使得数据结构的成员能够按某种次序排列
3、ES6创造了一种新的遍历命令for...of循环,Iterator接口主要供for...of消费。
工作原理:
- 创建一个指针对象,指向数据结构的起始位置。
- 第一次调用next方法,指针自动指向数据结构的第一个成员
- 接下来不断调用next方法,指针会一直往后移动,直到指向最后一个成员
- 每调用next方法返回的是一个包含value和done的对象,{value: 当前成员的值,done: 布尔值}
* value表示当前成员的值,done对应的布尔值表示当前的数据的结构是否遍历结束。
* 当遍历结束的时候返回的value值是undefined,done值为true
原生具备iterator接口的数据(可用for of遍历)
1、Array
2、arguments
3、set容器
4、map容器
5、String
6、......
十四.内置扩展对象
1.Generator函数
generator: 解决代码的异步编程 首先可以把它理解成,Generator 函数是一个状态机,封装了多个内部状态
yield: 暂停函数的运行 等待next方法调用
yield* : 在generator函数中 调用generator函数
constructor : 构造方法,当你实例化对象时,会自动调用constructor这个方法,并且把外面的实参传递进来(this指向 当前的实例对象 )
2.继承 extends
当使用extends继承时 需要在constructor中 调用super方法
调用父类的 constructor 构造器 ,super类似call()方法
class Fn{
constructor(){
this.name = 123;
this.age = 789;
this.sex = 'xxx';
}
获取attr属性时 执行get方法
get attr(){
console.log('get方法')
return this.value;
}
修改attr属性时 执行set方法
set attr(value){
console.log('set方法')
this.value = value;
}
static 添加静态方法或属性
静态static存到类身上的不是对象身上
static静态属性和方法通过 类去访问,不需要实例化,直接存放在类身上了
static say(){
console.log('静态方法')
}
static username = '信息';
password = '147258369';
}
3.私有属性
(只能在当前类中使用) 在属性名之前使用#表示。 #属性名
4.
extends 继承
super() 调用父类构造器
static 为类添加静态方法 静态属性
get(){} set(){}
私有属性 在属性名之前使用#表示 #name
5.模块化(async)
模块化 模块化是指将一个很大的程序文件,拆分为许多个小的文件,然后将多个小文件组合起来
模块化优点 : ① 阻止命名冲突; ② 代码复用; ③ 高维护性
暴露方式 1. 分别暴露 2.统一暴露 3.默认暴露
导入方式 1.结构赋值导入 2.默认导入
解决异步编程 是generator的语法糖写法
await 后的值为promise对象
await 后面的值不是promise对象 那么它的状态默认为成功
会将promise对象中 成功函数的参数 返回至await声明处 需要使用变量接受await的返回值
await中promise状态为失败 停止向下执行