自学内容网 自学内容网

ES6的简单介绍

一 ECMAScript的简介

1.1 什么是 ECMAScript

        ECMAScript,发音 [ek - ma - script] 。在中文中, ECMAScript 可以读作 "伊克玛Script"。

        官方定义: ECMAScript 是定义脚本语言的规范, 而 JavaScript 是遵循 ECMAScript 规范实现的一种编程语言。ECMAScript 6.0(以下简称 ES6)是 JavaScript 语言的下一代标准,已经在 2015 年 6 月正式发布了。它的目标,是使得 JavaScript 语言可以用来编写复杂的大型应用程序,成为企业级开发语言。

1.2 ES6 和 JavaScript 的区别

        ECMAScript 和 JavaScript 的关系是,前者是后者的规格,后者是前者的一种实现(另外的 ECMAScript 方言还有 JScript 和 ActionScript)。日常场合,这两个词是可以互换。

        ES6(ECMAScript 2015)是ECMAScript规范的第六个版本,JavaScript基于第六版的规范,新增很多功能。

1.3 ES6的新规范

  • ES6引入了"块级作用域",使用let和const关键字来声明变量和常量,使变量的作用域清晰可控

  • ES6引入了"箭头函数",箭头函数比传统的函数语法更简洁, 具有更少的冗余代码

  • ES6引入了"类(Class)"的概念,这是一种基于原型的面向对象编程的语法糖, 使用类可以更方便地创建和管理对象

  • ES6引入了"模板字符串", 使用反引号(`)创建字符串可以方便地嵌入变量和表达式

  • ES6引入了"解构赋值", 这是一种新的赋值语法,可以将数组或对象的属性直接赋值给变量

  • ES6引入了"函数参数默认值"

  • ES6引入了"Promise对象", 简化了异步编程, 使其更可读和可维护

  • ES6引入了 Set、Map 等

  • ES6引入了"模块化"(ES Module)

    ……

ES7 ~ ES13 新特性

ES7(ECMAScript 2016)

数组 includes() 方法

指数运算符

Array.prototype.includes()

ES8(ECMAScript 2017)

async/await 异步编程解决方案的改进

共享内存和原子操作的支持

Object.values() 和 Object.entries()

String.prototype.padStart() 和 String.prototype.padEnd()

ES9(ECMAScript 2018)

异步迭代器

Promise finally() 方法

Rest/Spread 属性

正则表达式具有命名捕获组

ES10(ECMAScript 2019)

Array.prototype.flat() 和 Array.prototype.flatMap()

Object.fromEntries()

String.prototype.trimStart() 和 String.prototype.trimEnd()

catch 块可以省略参数

ES11(ECMAScript 2020)

可选链 ?. 和 Nullish 合并运算符 ??

Promise.allSettled() 方法

动态 import()

全局对象globalThis

ES12(ECMAScript 2021)

String.prototype.replaceAll()

数字分隔符

WeakRefs 弱引用

Promise.any() 方法

ES13(ECMAScript 2022)

Class fields 类字段

SIMD(Single Instruction, Multiple Data)指令集

更好的BigInt支持

二 变量与常量

2.1 var定义变量(ES6之前)

  • var可以在全局范围或者函数范围内声明变量

  • var 变量可以重新声明和修改

  • var 的变量提升:在执行代码前,变量或函数的声明会移至到作用域的顶端。比如

我们这样写会被解析成这样

console.log(age);

var age = 20

var age

console.log(age)

age=20

 变量提升后,会使用undefined进行初始化,因此并不会报 变量没有被定义错误

  • 总结如下:

    var定义的变量,与java语言中的变量的用法相比较,并没有那么严谨。因此ES6之后引入了两个let和const,以及块级作用域的概念。

  测试代码:

// 1. var可以定义全局变量、和在函数内定义局部变量。
var myfriend = "zhangSan"
function f1(){
    var hisfriend="lisi"
}

//输出变量
console.log("全局变量:"+myfriend);
// console.log("局部变量: "+hisfriend);//报错,会终止下面代码进行
console.log("全局变量会自动绑定到window对象上:"+window.myfriend);

//2. var定义的变量,可以重新定义和修改
var myfriend = "小七";
console.log("全局变量:"+myfriend);

myfriend="小八";
console.log("全局变量:"+myfriend);

//3.var 定义的变量,可以提升:在执行代码时,将变量或者函数提升到了执行的代码之前(作用域顶端)
//3.1 变量的提升: 相当于在使用变量前 增加了变量的定义以及初始化: var 变量=undefined
//3.2 函数的提升: 函数的定义提升到了使用前,因此不会报错。

f2()
function f2(){
    console.log("--执行了f2--")
}

console.log(yourfriend);
var yourfriend = "小九";

2.2 let和const(ES6之后)

        从ES6开始,引入了块级作用域,以及let和const两个关键字来规范变量的用法。目的是要像java变量一样更具严谨性。块级作用域,其实就是{}包含的范围。直接书写{},或者函数体的{}就是块级作用域

2.2.1 let定义的变量

  • 必须先声明和初始化,才能使用变量

  • 变量的作用域,就是其所在的{},在作用域范围外使用,会报错

  • 在作用域内,变量可以被修改,但是不能重复声明

2.2.2 const定义的变量

  • const定义的变量,是常量,因此不能被再次赋值

  • const定义的常量,也是有其作用域的,只能在作用域内被访问。

 测试代码如下:

// 因为var定义的变量不够严谨,因此ES6规范,引入了块级作用域与两个关键字let const
// 1. 块级作用域: 可以直接书写的{}, 以及函数体的{}
// 2. let用于定义变量,严谨性与java语音的变量一直。
// 3. const用于定义变量,是常量,与java语言的常量相似

{
    let x = 10
    let y = 20 , z = 30;
    console.log(x,y,z);
    //可以被覆盖
    x = 100,y=200,z=300;
    console.log(x,y,z);

}
// let定义的变量不能超出作用域范围
// console.log(x,y,z);//Uncaught ReferenceError: x is not defined
let x =1000;
console.log("x:"+x);
// let x =2000;   //同一个作用域内,变量只能定义一次。
console.log("全局变量"+window.x);  //undefined  let定义的全局变量  不会自动绑定到window上 

// let定义的变量 可以提升  但是提升后没有初始化,因此在使用时会报Cannot access 'num1' before initialization。
// 自己理解, 就是let定义不能提前使用
// console.log(num1);
let num1 = 100;



const pi=3.1415926535;
// pi = 3.15;   const定义的变量,不能被再次赋值,因为是常量
console.log("pi的值:"+pi);
{
    console.log("在块里打印pi的值:"+pi);
    const pe = 0.618;
    console.log("黄金比例值:"+pe);
}
// 定义的变量也不能在作用域外面使用
// console.log("在作用域外面打印黄金比例值:"+pe)

// 定义一个变量,来存储匿名函数对象
let f3= function(){
    console.log("hello es6");
}
f3()

三 模版字符串与解构

3.1 模版字符串

//1. 模版字符串    ES6规范中,引入了返单引号 `` 与linux的shell脚本中的``是一个意思
// 之前的字符串拼接方式,使用 + 号拼接
let name = "zhansgan";
let age= 21;
let information = '我的名字是'+name+',今年'+age+"岁。";
console.log(information);

// es6中,在返单引号里,可以直接写变量,只不过变量需要使用${}包起来, 返单引号里也可以直接换行
let name1="lisi";
let age1 = 21;
let information2 = `我的名字是${name1},我今年${age1}岁`;
console.log(information2);

let information3 = `鹅鹅鹅,
曲项向天歌。
白毛浮绿水,
红掌拨清波。
`
console.log(information3);

3.2 解构

// 2. 解构: 可以理解为解开解构。 即将数组元素、集合元素、对象属性等赋值给变量
// 语法结构: [变量1,变量2,变量3.....] = 数组|集合|对象
let names=['张三','lisi','rose'];
let n1 = names[0];
let n2 = names[1];
let n3 = names[2];
console.log(n1,n2,n3);

// 使用中括号定义一个变量数组,分别从左到右接收后面的数组对象里的元素
let[x,y,z] = ['join','tom','michael']
console.log(x,y,z);
var [,m1,,m2] = [10,20,30,40]
console.log(m1,m2);
let[,,,last]=[100,200,300,400]
console.log(last);

//3. 使用解构的方式来完成两个变量里的值的交换
let a1 = 10;
let a2 = 20;
[a1,a2]=[a1,a2];
console.log(a1,a2);

// 4. 解构对象
let person ={
    'pname':"zhangsan",
    gender:'f',
    age:21
}
console.log(person);
// 4.1 在解构对象时,使用{}存储变量名,不是[],而且变量名要和属性名相同
let{pname}= person;
console.log(pname);
// 4.2 如果想用一个不与属性名相同的变量,也就是自定义变量,那么需要再属性名变量后添加冒号和自定义变量名
let{gender,age:myage, pname:pname1} = person;
console.log(gender,myage,pname1);
//4.3 可以给没有的属性,设置默认值
let{gender: mygender,idcard = 1004}=person;
console.log(mygender,idcard);

let[h1,h2,h3=3] = [1,2];
console.log(h1,h2,h3);

四 JS中的数据类型

之前我们学习过,JS中的数据类型主要分为两类,

一类是数值(基本)类型

String,Number,Boolean, null, undefined, Symbol

一类是引用数据(对象)类型

Object,Array,Function,RegExp,Date

在ES6中,又引入了Set、Map、Class等引用类型…

4.1 Set、扩展运算符

Set 是一种特殊的数据结构,是用于存储无序且唯一的值的集合对象。

// ES6规范中,引入了一个新的类型set
// 回顾: 基本数值类型(Number,Boolean,String,null,undefined,Symbol)
//       引用(对象)类型(Array,Object,Function,Date,RegExp)

// set: 是一种数据结构,无序且唯一(不能重复) 

// set的创建
let s1 = new Set() //空Set
console.log(s1);
let s2 = new Set([1,2,3]);// 创建一个有元素的set集合, 注意  元素使用中括号[]包起来
console.log("集合对象:",s2);
console.log("集合的元素个数:"+s2.size);
// set是无序的,因此不能使用下标访问s2
// console.log(s2[2]);

// 添加元素
s2.add(4);
console.log(s2);
s2.add(4);// 再次添加相同元素,添加不进去
console.log(s2);

//删除元素
s2.delete(3);
console.log(s2);

// 查看set中是否有某一个元素
let f1 = s2.has(2);
console.log("是否有2这个元素:",f1);

//遍历1: for...of
// for(let element of s2){
for(element of s2){
    console.log(element);
}
// 遍历2: forEach
// 回调函数: 函数A作为参数,传入到另外一个函数B中,函数A会在函数B中执行,函数A就是回调函数
let print1=function (a,b,c){
    console.log(a,b,c);
} 
s2.forEach(print1);

// 清空set
s2.clear();
console.log("集合对象:",s2);
console.log("集合的元素个数:"+s2.size);


// 扩展运算符: ... 作用:用于展开数组、set、map

let s3 = new Set([1,2,3]);
//将s3装成数组对象,使用了扩展运算符
let arr1 = [...s3]
console.log(arr1);

let s4 = [1,2,3];
let s5 = [5,6,7];
let s6 = [s4,4,s5];
console.log(s6);
let s7 = [...s4,4,...s5];
// let s8 = [...s6];
console.log(s7);
// console.log(s8);
// 使用扩展运算符,展开对象操作
let obj1 = {name:"zhangsan"};
let obj2 = {gender:'f'};
let obj3 = {
    ...obj1,
    age:21,
    ...obj2
}
console.log(obj3);

//set 转成数组的另外一种方式: Array.from方法
let s8 = new Set(['lucy','lily','tom']);
let arr2 = Array.from(s8);
console.log(arr2);
//遍历数组
arr2.forEach((value,index)=>console.log(index,value))

4.2 Map

Map 是一种特殊的数据结构,是用于存储键值对的有序集合对象。

// map:ES6规范引入的一种新的数据结构,用于存储键值对。有序(添加顺序)。

// 创建Map对象
let m1 = new Map();
console.log(m1);
let m2 = new Map([
    ['1003','tom'],
    ['1004','lily']
]);
console.log(m2);
console.log("map的长度:",m2.size);

//添加元素
m2.set("1005","john");
console.log(m2);
// 添加key重复的元素,会覆盖原有的value
m2.set("1004","wangwu")
console.log(m2)

m2.delete("1003");
console.log(m2);

//查看上下文是否有某一个key的元素
console.log("是否存在key为1002的元素:",m2.has("1002"));

// 遍历1
m2.forEach((value,key)=>console.log(value,key));
// 遍历2
for([key,value] of m2){
    console.log(key,value);
}
//遍历3
let es = m2.entries();
console.log(es);
es.forEach((entry,index)=>{
    // entry 是每一个键值对,又因为键值对是两个元素的数组,因此可以使用下标访问entry的key和value
    console.log(entry[0],entry[1]);
})

// 遍历4:
let ks = m2.keys();
ks.forEach(key=>{console.log(key,m2.get(key));
})

//遍历5:
let vs = m2.values();
vs.forEach(v=> console.log(v))

//map转数组
let arr1 = Array.from(m2);
console.log(arr1);
console.log(arr1[0][1]);

//清空map
m2.clear();
console.log(m2);

4.3 class

        ES6引入了class关键字,用来定义类。 类是多个具有相同特征的对象的模版,用一个类可以创建许多不同的对象。

4.3.1 基本用法

  • 语法格式: class 类名{…}

  • 类名首字母需要大写,用于区别变量名

  • 类体中可以定义属性、构造方法、实例方法

4.3.2 案例演示

//ES6中,也引入了关键字class,用于描述类的概念,类是一堆具有相同特征的模版,对象是类的具体实例。
// 我们可以用类,来创建多个不同的对象。
class Person{
    //提供属性
    name
    age
    gender
    
    //提供构造函数   一般用于初始化属性。
    constructor(name,age,gender){
        this.name=name;
        this.age=age;
        this.gender = gender;
    }
    // 提供实例方法
    sayHi(othername){
        console.log(`${othername},你好,我是${this.name},今年${this.age}岁`);
    }

}

// 使用类创建一个对象
let p1 = new Person("张三",21,'女')  //new关键字后书写类名(有参传参),底层默认就会调用构造函数
console.log(p1);
p1.sayHi("李四")



class Teacher{
    //如果没有显式的书写属性,在构造函数中,直接使用的变量就会自动提升为属性,注意,必须使用this.调用
    constructor(name,age,gender,a){
        this.name=name;
        this.age=age;
        this.gender = gender;
        // idcard = a;
        this.idCard=a;
    }
}

let t1 = new Teacher("liu",21,'nan',123123);
console.log(t1);
//调用属性:
console.log(t1.name,t1.age,t1.gender,t1.idCard);

class Student{
    #idCard  //设置私有属性,前面添加#
    constructor(name,gender,age,idCard){
        this.name = name;
        this.gender = gender;
        this.age = age;
        this.#idCard = idCard;
    }
    //为私有属性提供getter方法(也叫存取器)
    get idCard(){
        return this.#idCard;
    }
    set idCard(value){
        this.#idCard=value;
    }
}

let s1 = new Student("wangwu","男",21,123123123);
console.log(s1);
//访问非私有属性
console.log(s1.name,s1.age,s1.gender);
//访问私有属性
console.log(s1.idCard);  //当获取私有属性时,其实调用的是getter存取器

// 给非私有属性赋值
s1.name ="wanglaowu";
console.log(s1);

//给私有属性赋值
s1.idCard=123321333111222; //底层调用的是setter存取器
console.log(s1.idCard);

4.4 类的继承

        ES6类支持单继承,使用extends关键字,就可以继承class了。

// 类的继承:关键字extends
class Human {
    constructor(name,gender,age){
        this.name=name;
        this.gender=gender;
        this.age=age;
    }
    // 提供实例方法
    sayHi(othername){
        console.log(`${othername},你好,我是${this.name},今年${this.age}岁`);
    }
}
//子类型 : 
// 1.子类的构造器可以不写,默认调用父类的构造器进行赋值操作
// 2.子类提供构造函数时,必须使用super(有参传参)调用父类的构造器。必须放在首行。
// 3.父类的属性,方法,都会被继承到子类型中
class Emp extends Human{
    constructor(name,gender,age,idcard){
        super(name,gender,age)
        this.idcard = idcard;
    }
}

let emp = new Emp("员工1","男",21,19292929);
console.log(emp);
console.log(emp.age);
emp.sayHi("wanglaoqi")
console.log(emp.idcard);

注意:

子类型 : 
        1.子类的构造器可以不写,默认调用父类的构造器进行赋值操作
        2.子类提供构造函数时,必须使用super(有参传参)调用父类的构造器。必须放在首行。
        3.父类的属性,方法,都会被继承到子类型中 

4.5 箭头函数

 ES6规范中引入的新写法, 目的是为了简化函数的写法,对标的是java的lambda表达式。

// 匿名函数的定义
let getSum1 = function(a,b){
    console.log(a+b);
}
getSum1(10,20)
//使用箭头函数来简化写法  (形参列表)=>{函数体}
let getSum2 = (a,b)=>{console.log(a+b);};
let getSum3 = (a,b)=>console.log(a+b);

// 调用的时候
getSum2(10,20);
getSum3(10,20);
// 箭头函数的继续简化: 形参列表中只有一个形参时,可以省略小括号
let getSum4 = num =>{return Math.pow(num,3);};
console.log(getSum4(3));
// 箭头函数的继续简化:函数体中只有一行代码时,可以省略花括号,但是不能有return。如果有return,必须省略
let getSum5= (n1,n2)=>n1+n2;
console.log(getSum5(1,2));

 


原文地址:https://blog.csdn.net/zhaogodzero/article/details/142331736

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!