【ES6】新特性详解篇(二)

💻【ES6】新特性详解🏠专栏:JavaScript
👀个人主页:繁星学编程🍁
🧑个人简介:一个不断提高自我的平凡人🚀
🔊分享方向:目前主攻前端,其他知识也会阶段性分享🍀
👊格言:☀️没有走不通的路,只有不敢走的人!☀️
👉让我们一起进步,一起成为更好的自己!!!🎁

【ES6】新特性详解

一. 模块化开发(js文件之间的导入和导出)

JavaScript中的导入导出方式有两对,并且是对应着使用的。

import:静态的 import 语句用于导入由另一个模块导出的绑定。无论是否声明了 strict mode,导入的模块都运行在严格模式下。在浏览器中,import 语句只能在声明了 type="module"script 的标签中使用。

<script src="./index.js" type="module"></script> <!-- 导入文件中引入导出文件 -->

(1) 第一组导入导出

导出方式一:

export default 要导出的数据 // export default 导入模块的默认导出接口的引用名,一个页面只能写一个
export default {数据1,数据2...} // 批量导出

导入方式一:

import 变量 from "来源的文件"
// eg:
// 导出文件:
let a
let b = 200
let c = 300
var obj = {
  a: a,
  b: b
}
export default a = 100 // 对外暴露变量a的值

// 导入文件:
import headerModules from './header.js' // 引入导出文件
console.log(headerModules); // 100

(2) 第二组导入导出

导出方式二:

export 要导出的数据 // 可以同时使用多个export导出

导入方式二:

import {变量1,变量2...} from "来源的文件";
// 或
import * as 变量 from "来源文件"
// eg:
// 导出文件:
export const a = 3;
export const b = [1, 45, 'zs'];
export const c = {
  name: 'zs',
  age: 18
}

// 导入文件:
import { b } from './two.js'
console.log(b) // [1, 45, 'zs']

二. 新的数据类型

JavaScript中原来的数据类型:Number、Boolean、Unll、Undefined、String、object

ES6新增的数据类型:Symbol、BigInt

(1) Symbol

symbol 是一种基本数据类型。Symbol() 函数会返回 symbol 类型的值,该类型具有静态属性和静态方法。
每个从 Symbol() 返回的 symbol 值都是唯一的。一个 symbol 值能作为对象属性的标识符;这是该数据类型仅有的目的

  1. 创建Symbol数据类型

    语法:

    var 变量名 = Symbol(数据)
    
    // eg:
    var a = Symbol('1');
    var b = Symbol('1');
    console.log(a, b); // Symbol(1) Symbol(1)
    console.log(a === b); // false
    console.log(a == b);  // false // 独一无二 的,无法比较
    
  2. Symbol作为对象的属性

    不会覆盖

    不能通过对象语法获取,只能通过遍历的方式拿到

    Object.getOwnPropertySymbols()方式,可以获取到对象的所有Symbol属性名

    const obj = {
        [Symbol('tom')]:1,
        [Symbol('jerry')]:2,
    }
    obj[Symbol('tom')] = 3
    console.log(obj); // 不会覆盖,可以添加 // {Symbol(tom): 1, Symbol(jerry): 2, Symbol(tom): 3} 
    console.log(obj[Symbol('tom')]); // undefined , Symbol('tom') 表示独一无二的值,获取的时候的Symbol('tom'),和设置的时候的Symbol('tom'), 不是同一个
    // 无法通过对象语法获取symbol, 只能遍历
    
    const obj = {
        [Symbol('tom')]: 1,
        [Symbol('jerry')]: 2,
    }
    obj[Symbol('tom')] = 3;
    console.log(Object.getOwnPropertySymbols(obj)); // [Symbol(tom), Symbol(jerry), Symbol(tom)]
    for (let i = 0; i < Object.getOwnPropertySymbols(obj).length; i++) {
        // 获取对象的symbol属性名对应的属性值
        console.log(Object.getOwnPropertySymbols(obj)[i], obj[Object.getOwnPropertySymbols(obj)[i]]);
    }
    

(2) BigInt

BigInt 是一种内置对象,它提供了一种方法来表示大于 2^53 - 1 的整数。这原本是 Javascript 中可以用Number 表示的最大数字。BigInt 可以表示任意大的整数。

新增加这个数据类型的目的:js存储16位以上的数据会出现精度丢失的问题

var num = 100;
num = 100n; // 转为BigInt
console.log(num); // 100n
console.log(typeof num); // bigint

console.log(100n + 100n); // 200n
console.log(100n + 100); // Uncaught TypeError: Cannot mix BigInt and other types, use explicit conversions

  • 将任意数字转为BigInt , 在数字后面添加n

  • bigInt只能和bigInt一起操作

  • BigIntNumber不是严格相等的,但是宽松相等的。

    10n == 10; // true
    10n === 10; // false
    

三. class类

(1) 在之前的js中,我们会通过定义函数的方式进行构造函数的创建,在通过new 一个构造函数的类来实现一种独立的数据类型(Class)。

function Person (name) {
    this.name = name;
    this.say = function (){
        console.log('这是一个构造函数方法', this)
    }
}
// 通过定义在原型链上的方式来进行类之间数据共享
const person = new Person('df');
person.say();
person.property.action = function () {console.log('原型链上的数据共享')}

现在,ES6中,定义了一个class关键字来定义类,和java、php这些面向对象语言一样中类的功能类似(强调,JavaScript是面向函数式编程)。

class Dog {
    constructor (name,age) { // 这是构造器,对象一经创建就立即执行的类,里面的参数就是new对象时候传入的参数
        this.name = name
        this.age = age
    }
    say () { // 之前都是将方法放在原型上或者属性上,不能直接定义,现在可以了
        console.log('这是一个calss创建的类', this)
    }
}

(2) 通过静态方法来创建对象,静态方法只能函数自己来调用,它的实例对象不能调用,而实例方法只能通过它的实例对象来调用,它本身不能调用。实例方法都是定义在类原型上的,而通过关键字static修饰后,这个方法就变成了静态方法,只能通过类名去调用了。

class Dog {
    constructor (name,age) { // 这是构造器,对象一经创建就立即执行的类,里面的参数就是new对象时候传入的参数
        this.name = name
        this.age = age
    }
    say () { // 之前都是将方法放在原型上或者属性上,不能直接定义,现在可以了
        console.log('这是一个calss创建的类', this)
    }
    static action (name,age) {
        console.log('这是Dog类的静态方法')
        return new Dog(name, age)
    }
}
const ha = Dog.action('哈士奇', 3)
console.log(ha);  // 这是Dog类的静态方法    Dog { name: '哈士奇', age: 3 }

3、 静态方法中的this是是指向当前类型,而不是当前对象。

4、使用extends关键字来实现继承一个父类,通过super关键字来调用继承的父类的属性和方法

class Dog {
    constructor (name,age) { // 这是构造器,对象一经创建就立即执行的类,里面的参数就是new对象时候传入的参数
        this.name = name
        this.age = age
    }
    say () { // 之前都是将方法放在原型上或者属性上,不能直接定义,现在可以了
        console.log('这是一个calss创建的类', this)
    }
    static action (name,age) {
        console.log('这是Dog类的静态方法')
        return new Dog(name, age)
    }
}
class MinDog extends Dog {
    constructor (name,age,type) {
        super(name,age) // super关键字是用来调用父类 的,这里相当于在调用父类的构造方法
        this._type = type
    }
    hello () {
        super.say()
        console.log('上一句是调用父类super打印出来的');
    }
}
const ha = new MinDog('哈士奇', 3, 'man')
ha.hello() // 这是一个calss创建的类 MinDog { name: '哈士奇', age: 3, _type: 'man' }   // 上一句是调用父类super打印出来的

四. ES6新增数据结构

数据结构 Set

ES6 提供了新的数据结构 Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。

Set本身是一个构造函数,用来生成 Set 数据结构。

由于Set是伪数组,并且伪数组里面的值都是唯一的,所以可以用在数组去重中

const s = new Set()
const arr = [7, 2, 3, 4, 2, 5, 5];
arr.forEach(item => { s.add(item) });
console.log(s); // Set(5) {7, 2, 3, 4, 5}
console.log([...s]); // (5) [7, 2, 3, 4, 5]
// 简化为
const set = new Set([7, 2, 3, 4, 2, 5, 5]);
[...set]// [7, 2, 3, 4, 5]
(1) 创建 Set 数据结构

语法

var s = new Set([数据1, 数据2, 数据3....])
(2) Set 数据结构的属性和方法

属性:size

方法:add()、has()、delete()、clear()、forEach()

  1. size 属性

    该数据结构中有多少个数据

    语法:数据结构.size

    // eg:
    const s = new Set([100, 200, 300, 200]);
    console.log(s.size); // 3
    
  2. add() 方法

    向该数据结构添加内容

    语法:数据结构.add(数据)

    // eg:
    const s = new Set([100, 200, 300]);
    s.add(500)
    s.add(100)
    console.log(s); // Set(4) {100, 200, 300, 500}
    
  3. has() 方法

    查找Set中是否有该数据

    语法:数据结构.has(数据)

    true 该数据结构内有该数据
    false 该数据结构内没有该数据

    // eg:
    const s = new Set([100, 200, 300]);
    console.log(s.has(100)); // true
    console.log(s.has(500)); // false
    
  4. delete()方法

    删除数据

    语法:数据结构.delete(数据)

    // eg:
    const s = new Set([100, 200, 300]);
    s.delete(100);
    console.log(s); // Set(2) {200, 300}
    
  5. clear() 方法

    清除该数据结构内所有内容

    语法:数据结构.clear()

    // eg:
    const s = new Set([100, 200, 300]);
    s.clear();
    console.log(s); // Set(0) {size: 0}
    
  6. forEach() 方法

    语法 :数据结构.forEach(function(value, key, origin){})

    // eg:
    const s = new Set([100, 200, 300]);   
    s.forEach(function(value, key, origin){
        console.log(value, key, origin); // 100 100 Set(3) {100, 200, 300}
    });
    
(3) Set中判断两个值是否不同

向 Set 加入值的时候,不会发生类型转换,所以5"5"是两个不同的值。Set 内部判断两个值是否不同,使用的算法叫做“Same-value-zero equality”,它类似于精确相等运算符(===),主要的区别是向 Set 加入值时认为NaN等于自身,而精确相等运算符认为NaN不等于自身。

let set = new Set();
let a = NaN;
let b = NaN;
set.add(a);
set.add(b);
set // Set {NaN}

上面代码向 Set 实例添加了两次NaN,但是只会加入一个。这表明,在 Set 内部,两个NaN是相等的。

另外,两个对象总是不相等的。

let set = new Set();

set.add({});
set.size // 1

set.add({});
set.size // 2

上面代码表示,由于两个空对象不相等,所以它们被视为两个值。

数据结构 Map

Map 数据结构:类似于对象的数据结构,它的key可以是任何数据类型,可以被看做为一个 值 = 值 的数据结构

(1) Map 基本概念

ES6 提供了 Map 数据结构。它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。也就是说,Object 结构提供了“字符串—值”的对应,Map 结构提供了“值—值”的对应,是一种更完善的 Hash 结构实现。如果你需要“键值对”的数据结构,Map 比 Object 更合适。

(2) Map 特征
  • Map 对象保存键值对,并且能够记住键的原始插入顺序。
  • 任何值(对象或者原始值) 都可以作为一个键或一个值。
  • Map 是 ES6 中引入的一种新的数据结构
(3) Maps 和 Objects 的区别
  • 一个 Object 的键只能是字符串或者 Symbols,但一个 Map 的键可以是任意值。
  • Map 中的键值是有序的(FIFO 原则),而添加到对象中的键则不是。
  • Map 的键值对个数可以从 size 属性获取,而 Object 的键值对个数只能手动计算。
  • Object 都有自己的原型,原型链上的键名有可能和你自己在对象上的设置的键名产生冲突。
(4) 创建一个 Map数据结构

语法

var m = new Map( [ [key, value], [key, value] ] )
(5) Map 数据结构的属性和方法

属性:size

方法:set()、get()、has()、delete()、clear()、forEach()

  1. size 属性

    该数据结构内有多少个数据

    语法:数据结构.size

    // eg:
    const m = new Map([['name', 'zs'], ['age', 18]]);
    console.log(m.size); // 2
    
  2. set() 方法

    向该数据结构添加内容

    语法:数据结构.set(key, value)

    // eg:
    const m = new Map([['name', 'zs'], ['age', 18]]);
    m.set('time', '两年半');
    console.log(m); // Map(3) {'name' => 'zs', 'age' => 18, 'time' => '两年半'}
    
  3. get() 方法

    语法:数据结构.get(key)

    返回值:该数据结构内key对应的value

    // eg:
    const m = new Map([['name', 'zs'], ['age', 18]]);
    console.log(m.get('name')); // zs
    
  4. has() 方法

    该数据结构中是否有该数据

    语法:数据结构.has(key)

    // eg:
    const m = new Map([['name', 'zs'], ['age', 18]]);
    console.log(m.has('name')); // true
    
  5. delete() 方法

    删除该数据结构内某一个数据

    语法:数据结构.delete(key)

    // eg:
    const m = new Map([['name', 'zs'], ['age', 18]]);
    m.delete('name');
    console.log(m); // Map(1) {'age' => 18}
    
  6. clear() 方法

    清除该数据结构里面的所有内容

    语法:数据结构.clear()

    // eg:
    const m = new Map([['name', 'zs'], ['age', 18]]);
    m.clear();
    console.log(m); // Map(0) {size: 0}
    
  7. forEach()

    语法:

    数据结构.forEach(function(value, key, origin){})
    
    // eg:
    const m = new Map([['name', 'zs'], ['age', 18]]);
    m.forEach(function (value, key, origin) {
        console.log(value, key, origin); // zs name Map(2) {'name' => 'zs', 'age' => 18}
        							  // 18 'age' Map(2) {'name' => 'zs', 'age' => 18}
    })
    

参考文章Set 和 Map 数据结构 - ECMAScript 6入门 (ruanyifeng.com)

五. Iterator 和 for…of

Iterator(遍历器)

  • 是一个接口,为不同的数据结构提供了同一个的访问机制
  • ES6中提供了Symbol.iterator接口(属性),只要数据有这个接口,就可以用for…of遍历数据

Iterator 的作用有三个:一是为各种数据结构,提供一个统一的、简便的访问接口;二是使得数据结构的成员能够按某种次序排列;三是 ES6 创造了一种新的遍历命令for...of循环,Iterator 接口主要供for...of消费。

Iterator 的遍历过程

  1. 创建一个指针对象,指向当前数据结构的起始位置。也就是说,遍历器对象本质上,就是一个指针对象。
  2. 第一次调用指针对象的next方法,可以将指针指向数据结构的第一个成员。
  3. 第二次调用指针对象的next方法,指针就指向数据结构的第二个成员。
  4. 不断调用指针对象的next方法,直到它指向数据结构的结束位置。

每一次调用next方法,都会返回数据结构的当前成员的信息。具体来说,就是返回一个包含valuedone两个属性的对象。其中,value属性是当前成员的值,done属性是一个布尔值,表示遍历是否结束。

// 这里我们创建一个数组
const arr = [1,2,3]
const t = arr[Symbol.iterator]() //调用iterator方法可以得到该方法的执行体,里面有一个next()方法,这个方法就是循环中指向下一个地址的指针
console.log(t.next()) // {value: '1', done: false} // 这里得到的对象就是每次循环的对象值(value)和是否完成循环(done)

for…of… 遍历

语法

for(let 变量名 of 数据) {}
var arr = [100, 200, 300, 400, 500];
arr.name = 'tom';
for (let value of arr) {
    console.log(value);
    /*
    	100
    	200
    	300
    	400
    	500
    */
}

六. 生成器

生成器:允许你定义一个包含自有迭代算法的函数,同时它可以自动维护自己的状态。生成器函数使用 function*语法编写。最初调用时,生成器函数不执行任何代码,而是返回一种称为 Generator 的迭代器。通过调用生成器的下一个方法消耗值时,Generator 函数将执行,直到遇到 yield 关键字。

// eg:
function* makeRangeIterator(start = 0, end = Infinity, step = 1) {
    for (let i = start; i < end; i += step) {
        yield i;
    }
}
var a = makeRangeIterator(1,10,2)
a.next() // {value: 1, done: false}
a.next() // {value: 3, done: false}
a.next() // {value: 5, done: false}
a.next() // {value: 7, done: false}
a.next() // {value: 9, done: false}
a.next() // {value: undefined, done: true}

注意:虽然自定义的迭代器是一个有用的工具,但由于需要显式地维护其内部状态,因此需要谨慎地创建。它可以根据需要多次调用该函数,并且每次都返回一个新的 Generator,但每个 Generator 只能迭代一次。

结束语

希望对您有一点点帮助,如有错误欢迎小伙伴指正。
👍点赞:您的赞赏是我前进的动力!
⭐收藏:您的支持我是创作的源泉!
✍评论:您的建议是我改进的良药!
一起加油!!!💪💪💪

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

繁星学编程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值