- let 和 const 声明:引入了块级作用域的变量声明方式,let 声明的变量只在其所在的块级作用域内有效,而 const 声明的变量是只读的。
- 箭头函数:提供了更简洁的函数定义方式,并且自动绑定 this 上下文。
- 模板字符串:使用反引号(`)来定义字符串,可以进行多行字符串的定义,并且支持插入变量和表达式。
- 解构赋值:允许从数组或对象中提取值,并将其赋值给变量。
- 默认参数:函数可以定义默认参数值,当参数未传递时使用默认值。
- 展开运算符:用于将数组或对象展开为单个元素或属性。
- 类和继承:引入了类的概念,支持面向对象编程的特性,如继承、方法定义等。
- Promise:用于处理异步操作,提供了更优雅的异步编程方式。
- 模块化:支持使用模块来组织代码,通过 export 和 import 关键字实现模块的导出和导入。
- 新的对象属性和方法:如 Object.assign ()、Object.entries ()、Object.values () 等,提供了更方便的对象操作方法。
class
extends super
js
//1.类的定义
class Person{
//2.类的构造方法
/**
* 1.传参调用构造函数
* 2.不传参调用默认构造函数
* 3.一个类只有一个构造方法
*/
constructor(name,age){
this.name=name
this._age=age
}
//3.类的实例方法
say(){
console.log("hello",this.name);
}
//4.类的访问器方法
get age(){
return this._age;
}
set age(val){
this._age=val
}
//5.类的静态方法
static before()
{
console.log("创建了");
}
}
//类的继承
class Stu extends Person{
constructor(name,age,sno)
{
// 1.继承父类属性 使用this之前必须调用super()
super(name,age)
this.sno=sno
}
//2.重写父类方法
say(){
super.say()
console.log("子类");
}
}
let stu=new Stu("lxy","22","123893478923")
//方法是定义在prototype上
console.log(stu.age);
Person.before()
对象
继承内置类
js
// 1.继承内置类
class MyArray extends Array{
//重写toString方法
toString(){
return 'MyArray'+super.toString()
}
}
let arr1=new Array(1,2,3)
let arr = new MyArray(1,2,3)
console.log(arr1.toString());// 1,2,3
console.log(arr.toString())// MyArray,1,2,3
类的混入
实现多继承
js
//2.类的混入
//js是单继承,只能继承一个父类,但是可以通过混入的方式实现多继承
class Person{
constructor(name){
this.name=name
}
sayName(){
console.log(this.name)
}
}
function mixin(c){
return class extends c{
eating()
{
console.log("eating")
}
}
}
let newClass=mixin(Person)
let obj=new newClass('obj')
console.log(obj.name)// mixin
多态
传统面向对象的多态
- 有继承
- 有重写
- 父类引用指向子类对象
js多态
不用数据类型执行同一操作,结果不同
对象字面量增强
- 属性简写
- 方法简写
- 计算属性名
js
//1.属性简写
let name='obj'
let key=18
let obj={
name,//属性简写
[key]:'obj2',//计算属性名
say(){//方法简写
console.log('say')
}
}
解构
- 对象解构
- 数组解构
常用于函数参数解构
js
//1.对象解构
let obj={
name:'obj',
age:18,
sno:123
}
let {name,age,sno:no="7838"}=obj
console.log(name,age)//obj 18;
//2.数组解构
let arr=[1,2,3]
let [a,b,c]=arr
let [a,...newArr] = arr//解构一个元素,剩下的放到数组中
let [,,c]=arr//解构后面的元素
let [a,b,c,d=0]=arr//解构默认值
console.log(a,b,c)//1 2 3
let const
新增定义变量的关键字
用法
在用法上,var和let 的用法类似,用于定义变量
const 常用于声明常量,其值不能修改,但是如果传递的是引用类型,引用对象内部属性可以修改
作用域提升
var 声明的变量存在作用域提升,可以在声明之前访问
let const 声明的变量不能在声明之前访问,报错
这个区域称为暂时性死区
js
console.log(name);//undefined
var name='name';
console.log(age);//ReferenceError: Cannot access 'age' before initialization
console.log(a);//ReferenceError: Cannot access 'a' before initialization
let age=18;
const a=1;
在代码编译期间,变量与函数的声明会存放在VO
变量对象中,在es6中是VE
变量环境
var声明的变量会存放到GO
,所以提前访问是undefined
但是let const
不会在代码编译期间存放到GO
中吗??
不是
let const 声明的变量会在代码编译期间创建只是不能访问
与window的关系
在全局使用var声明变量,实际会在window上添加属性
let /const 不会在window上添加属性,那么变量是保存在哪里呢??
es5 的执行上下文
每一个执行上下文会关联到一个变量环境variable object
,在源代码中的变量与函数声明会作为属性添加到VO中
es6 的执行上下文
每个执行上下文会关联到一个变量环境variableEnvirable
,代码中的函数与变量声明会作为环境记录添加到VE中
VE没有指定是window对象或者其他,js引擎有自己的实现,v8中通过一个hashmap实现存储
window对象是早期的GO对象,最新的实现是浏览器天机的全局对象,并保持var与window对象的连接
块级作用域
var 情况下 只有
- 函数作用域
- 全局作用域
let const 增加了块级作用域
- 函数作用域
- 全局作用域
- 块级作用域 {}
示例
循环中使用var,只输出3
点击触发函数,在当前函数作用域中不存在i,
向上层作用寻找,对于var来讲{}不产生作用域,因此会找到全局的i
此时i已经执行完毕,值为3
js
//遍历对象,注册点击事件
for(var i=0;i<btns.length;i++){
btns[i].onclick=function(){
console.log(i);//3
}
}
//立即执行函数改进
for(var i=0;i<btns.length;i++){
(function(n){
btns[i].onclick=function(){
console.log(n);
}
})(i)
}
使用let
* why:点击触发函数,当前作用域没有i,向上层作用域寻找,
* 上层作用域是块级作用域{},因此会找到let声明的i,此时i的值为每一次i的值
js
for(let i=0;i<btns.length;i++){
btns[i].onclick=function(){
console.log(i);
}
}
模板字符串
字符串与变量拼接,使用${}
剩余参数
...
收集没有实参的形参,是一个数组
而arguments是一个类数组对象
js
// 函数剩余参数
function tag(a,...b)
{
console.log(a,b);//a=1,b=[2,3,4,5]
console.log(arguments);//[Arguments] { '0': 1, '1': 2, '2': 3, '3': 4, '4': 5 }
}
tag(1,2,3,4,5)
symbol
- 新增数据类型,用于创建唯一值
js
et s1=Symbol();
let s2=Symbol("222");
let s3=Symbol.for("s3");
let s4=Symbol.for("s3");
let s5=Symbol.for();
console.log(s1,s2,s3);//Symbol() Symbol(222) Symbol(s3)
console.log(s3===s4);//true
console.log(s1===s5);//false
console.log(Symbol.keyFor(s3));//s3
- 应用场景:解决属性名冲突
js
//1.1 应用场景 解决属性名冲突
let obj={};
obj.name="obj";
obj.name="obj1";
console.log(obj);//{name: 'obj1'} 被覆盖
let s1=Symbol("name");
obj[s1]="objsymbol";
console.log(obj.name);//obj1
console.log(obj[s1]);//objsymbol
- symbol属性无法遍历得到
js
console.log(Object.keys(obj));//[ 'name' ] symbol属性无法被遍历
console.log(Object.getOwnPropertySymbols(obj));//[ Symbol(name) ] 获取symbol属性
Set
类似数组,但是存储不重复
的值
js
//2.set -- > 数组
//存储不重复的值 可以遍历
let set=new Set([1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9]);
console.log(set);//Set(9) { 1, 2, 3, 4, 5, 6, 7, 8, 9 }
weakSet
弱引用,存储对象,不能遍历
js
let obj={name:"obj"};
let obj1={name:"obj1"};
let obj2={name:"obj2"};
let weakSet=new WeakSet();
weakSet.add(obj);
weakSet.add(obj1);
weakSet.add(obj2);
console.log(weakSet);//WeakSet { <items unknown> }
Map
类似对象,存储键值对
js
et map=new Map([["name","obj"],["age",18],[1,2]]);
console.log(map);//Map(3) { 'name' => 'obj', 'age' => 18, 1 => 2 }
weakMap
弱引用,不能遍历,key只能是对象
js
let obj3={name:"obj3"};
let obj4={name:"obj4"};
let obj5={name:"obj5"};
let weakMap=new WeakMap();
weakMap.set(obj3,"obj3");
weakMap.set(obj4,"obj4");
weakMap.set(obj5,"obj5");
// weakMap.set(1,2)
console.log(weakMap);//WeakMap { <items unknown> }