let
不存在变量提升(用
var
声明的存在变量提升,打印undefined
,而let声明的,打印会报错)同一个作用域下不能重复定义同一个名称(var重复定义的会覆盖上一个变量的值,let重复定义会报错)
有着严格的作用域(
var
属于函数作用域,let
属于块级作用域)存在暂时性死区的特性
const
- 声明一个只读的
常量
,一旦声明,常量
的值就不能改变- 一定要初始化,不能只声明不赋值
let、const、var的区别
- 使用
var
声明的变量,其作用域为该语句所在的函数内
,并且存在变量提升- 使用
let
声明的变量,其作用域为该语句所在的代码块内,不存在变量提升- 使用
const
声明的是常量,不能修改这个常量,且需要赋初始值
解构赋值
- 解构赋值就是将数据结构进行分解,再给变量进行赋值
- 如果解构不成功,变量的值为
undefined
- 数组结构使用
中括号包裹
,多个变量用逗号隔开- 对象解构使用
花括号包裹
,多个变量用逗号隔开
//数组解构
let [a,b,c]=[1,2,3]//传统方式需要通过索引依次赋值给变量
console.log(a)//1
console.log(b)//2
console.log(c)//3
//若解构失败,则打印undefined
//对象解构
let person={name:'张三',age:18}
let {name,age}=person
console.log(name)//张三
console.log(age)//18
//也可以使用别名
let {name:newName,age:newAge}=person
console.log(newName)//张三
console.log(newAge)//18
//赋初始值,当传入的值为undefined时则该变量为默认值
function show(name,age=18){
console.log(name)
console.log(age)
}
show('李四')//得到结果为李四 18
箭头函数
- 简化了函数的定义
- 修改了函数中this指向,定义箭头函数中的作用域的this指向谁,this就指向谁
let f=v=>v //变量名=参数=>返回值(函数体)
//es5中函数定义
let f=function(n1,n2){
return n1+n2;
}
//es6中函数定义
let f=(n1,n2)=>n1+n2;//参数为一个时括号可以省略
//面试题
var age =100
var obj={
age:20,
say:()=>{
console.log(this.age)
}
}
obj.say()//100 因为箭头函数this指向被声明的作用域里面,而对象中是没有作用域的,所以对象当中的this指向的是全局作用域
内置对象扩展
Array 的扩展方法
//扩展运算符
let ary = [1, 2, 3];
console.log(...ary); // 1 2 3
//复制数组
let ary1=[1,2,3]
let ary2=[...ary1]
console.log(ary1===ary2)//false
//扩展运算符合并数组
let ary1=[1,2,3]
let ary2=[4,5,6]
//方法一
let ary3=[...ary1,...ary2]
//方法二
ary1.push(...ary2)
console.log(ary3)//[1, 2, 3, 4, 5, 6]
console.log(ary1)//[1, 2, 3, 4, 5, 6]
Array.from()
将伪数组或可遍历对象转换为真正的数组
let arr={
'0':0,
'1':1,
'2':2,
length:3
}
//转成数组
let newArr=Array.from(arr)
console.log(newArr)//[0, 1, 2]
//from可以接受第二个参数,用来对每个元素进行处理
let arr={
'0':0,
'1':1,
'2':2,
length:3
}
//转成数组
let newArr=Array.from(arr,item=>item*2)
console.log(newArr)//[0, 2, 4]
Array.find()
用于查找第一个符合条件的数组成员,未找到返回undefined
let ary = [{
id: 1,
name: '张三'
}, {
id: 2,
name: '李四'
}];
let obj=ary.find(item=>item.id===1)//查找数组中id等于1的成员,只匹配第一个
findIndex()
用于查找第一个符合条件的数组成员位置,未找到返回-1
let ary = [{
id: 1,
name: '张三'
}, {
id: 2,
name: '李四'
}];
let objIndex=ary.findIndex(item=>item.id===1)//查找数组中id等于1的成员索引,只匹配第一个
includes()
判断数组是否包含给定的值,返回布尔值
let arr1=[1,2,3]
console.log(arr1.includes(2))//true
console.log(arr1.includes(4))//false
String 的扩展
模板字符串
创建字符串的方式,使用反引号定义
let {name,age}={name:'张三',age:18}
let sayHi=`大家好,我叫${name},今年${age}`
console.log(sayHi)//大家好,我叫张三,今年18
//可以换行
let html=`
<div>
<span>${name}</span>
<span>${age}</span>
</div>
`
//可以调用函数
let sayHello=()=>'你好'
let text=`${sayHello()}`
console.log(text)//你好
startsWith() 和 endsWith()
startsWith():表示参数字符串是否在原字符串的头部,返回布尔值
endsWith():表示参数字符串是否在原字符串的尾部,返回布尔值
let text='hello js'
console.log(text.startsWith('he'))//true
console.log(text.endsWith('he'))//false
repeat()
将原字符串重复n次,返回一个新字符串
let text='hello'
console.log(text.repeat(2))//hellohello
set map
set
- set类似于数组,但成员是唯一的
- add(value):添加某个值,返回 Set 结构本身
- delete(value):删除某个值,返回一个布尔值,表示删除是否成功
- has(value):返回一个布尔值,表示该值是否为 Set 的成员
- clear():清除所有成员,没有返回值
//set去重处理
const arr=[1,1,2,3,3]
let arr2=[...new Set(arr)]//...扩展运算符
console.log(arr2)//1,2,3
//set api调用
const s=new Set()
s.add(1).add(2).add(3)//添加值,支持链式操作
s.delete(4)//1,2,3 //移除4
s.has(4)//false //是否存在4
s.clear()//清空所有成员
map
- 以键值对形式存储
- set(key,value):添加某个key值
- get(key):通过key获取某个key值
- delete(key):删除某个key值,返回一个布尔值,true表示删除是否成功
- has(key):返回一个布尔值,表示该值是否为 map 的成员
- clear():清除所有成员,没有返回值
- 支持链式操作
//map键值对形式存储
let m=new Map()
m.set('name','张三').set('age',18)
m.get('name')//得到张三
m.delete('name')//移除张三的name
m.has('name')//false
m.clear()//清空所有成员
class
class
关键字,构造器和类分开
-class
直接添加方法,不用再写function
关键字,多个方法也不需要逗号分隔constructor
方法是类的默认方法,通过new
命令生成对象实例时,自动调用该方法
//定义类
class User{
//构造器
constructor(name,age){
//这里的this代表当前实例对象
this.name=name
this.age=age
}
//定义方法不用再写function关键字,多个方法也不需要逗号分隔
sayHi(){
console.log(`我叫${this.name},姓名:${this.age}`)
}
}
//es6继承
class VipUser extends User{
constructor(name,age,level){
//super()必须放在第一句
//super()只能用在子类的构造函数
super(name,age)
this.level=level
}
showLevel(){
console.log(`等级:${this.level}`)
}
}
const vipUser=new VipUser('张三',18,3)
vipUser.sayHi()//我叫张三,姓名:18
vipUser.showLevel()//等级:3
Generator
-
Generator
函数是一个普通函数,但是有两个特征。一是,function
关键字与函数名之间有一个星号
;二是,函数体内部使用yield表达式
,定义不同的内部状态方法
在函数上添加* 表示该函数为Generator函数,*位置任意位置都可以
function * foo(x, y) { ··· }
function *foo(x, y) { ··· }
function* foo(x, y) { ··· }
function*foo(x, y) { ··· }
function * helloWorldGenerator(){
//yield表达式就是暂停标志。
//遇到yield表达式,就暂停执行后面的操作,yield后的值作为返回对象的value的值
//下一次调用next(),继续调用后面的操作,直至遇到yield
yield 1
yield 2
yield 3
return 4
}
let h=helloWorldGenerator()
//next()开始执行,直到遇到第一个yield表达式为止,value=yield值,done:false表示该函数还未结束
h.next()
//{value: 1, done: false}
h.next()
//{value: 2, done: false}
h.next()
//{value: 3, done: false}
h.next()
//此时done=true,该函数已执行完毕
//{value: 4, done: true}
h.next()
//{value: undefined, done: true}
async
- 它就是
Generator
函数的语法糖async
作为一个关键字放到函数前面
任何一个async
函数都会隐式返回一个promise
await
关键字只能在使用async
定义的函数中使用
await
后面可以直接跟一个Promise
实例对象
await
函数不能单独使用async/await
让异步代码看起来、表现起来更像同步代码
使用async函数
function timeout(time){
//1.创建promise对象
//接受一个函数对象,参数为两个对象:resolve,reject
//resolve表示成功操作
//reject表示失败操作
return new Promise((resolve, reject)=>{
//2. 这里用于实现异步任务 setTimeout
setTimeout(()=>{
let flag=true
if(flag){
//3. 正常情况
resolve('成功')
}else{
//4.出错情况
reject('失败')
}
},time)
})
}
async function getTimer(time) {
let data=await timeout(time);//不需要then就可以拿到resolve或reject中的值
//等await后的异步代码完成后再去执行后面的代码
return data
}
getTimer(1000).then(data=>{
console.log(data)
}).catch(err=>{
console.log(err)
});
async 函数有多种使用形式。
// 函数声明
async function foo() {}
// 函数表达式
const foo = async function () {};
// 对象的方法
let obj = { async foo() {} };
obj.foo().then(...)
// Class 的方法
class Storage {
constructor() {
this.cachePromise = caches.open('avatars');
}
async getAvatar(name) {
const cache = await this.cachePromise;
return cache.match(`/avatars/${name}.jpg`);
}
}
const storage = new Storage();
storage.getAvatar('jake').then(…);
// 箭头函数
const foo = async () => {};
module
- 模块功能主要由两个命令构成:
export
和import
。export
命令用于导出模块,import
命令用于导入模块。
exprot
第一种写法
//xxx.js
export const name='张三'
export const age=18
第二种写法
//xxx.js
const name='张三'
const age=18
export {name,age}
export命令除了输出变量,还可以输出函数或类(class)。
export function multiply(x, y) {
return x * y;
};
导出的变量就是本身名字,也可以重命名
const name='张三'
const age=18
export {
name as newName
age as newAge
};
必须与模块内部的变量建立一一对应关系。
// 报错
export 1;
// 报错
var m = 1;
export m;
正确的写法
// 第一种
export const m=1;
// 第二种
var m = 1;
export {m};
// 第三种(重命名)
var m = 1;
export {m as m1};
import 命令
//.js路径可以省略
//对象解构方式
import {name,age} from 'xxx.js'//这里的为js文件路径
//对象方式
import person from 'xxx.js'//这里的为js文件路径
//重命名
import {name as newName,age as newAge} from 'xxx.js'//这里的为js文件路径
export default 命令
为模块指定默认输出。
// export-default.js
export default function () {
console.log('hello');
}
注意
:使用export default
后导入不能再使用解构赋值形式导入
import
命令可以为该匿名函数指定任意名字。
// import-default.js
import sayHi from './export-default';
sayHi (); // 'hello'