Symbol

  • ES6 引入了一种新的原始数据类型Symbol,表示独一无二的值

  • Symbol 值通过Symbol函数生成

let symbol = Symbol();
console.log(typeof symbol); // symbol

let symbol2 = Symbol("xxx");
console.log(symbol2); // Symbol(XXX)

let symbol3 = Symbol(5);
console.log(symbol3); // Symbol(5)

由于Symbol类型是原始类型,是不能通过new Symbol()来创建对象的。

注意:

  • 尝试将一个 symbol值转换为一个 number值时,会抛出一个typeError,错误。

  • Object(symbol) == symbol表达式的结果返回true。

  • 阻止从一个symbol值隐式地创建一个新的string类型的属性名。

Symbol方法:

  • Symbol.for()方法

    • 作用 - 从symbol类型中查找指定的key

      • 如果存在这个key的话,返回

      • 如果不存在这个key的话,创建

  • Symbol.keyfor()方法

    • 用于获取symbol注册表中与某个symbol关联的键

Symbol与for…in

Symbols在 for …in迭代中不可枚举。

Object.getOwnPropertyNames()不会返回symbol对象的属性,但是可以使用Obiect.getOwnPropertySymbols()得到它们。

var obj = {};
//使用Symbol作为对象的属性名出现,是不可枚举的
obj[Symbol( "a")]= "a" ;
obj[Symbol.for("b")]="b";
obj["c"] = "c";
obj.d = "d";
for (var i in obj) {
    console.log(i); // logs "c" and "d"
}

迭代器

为各种不同的数据结构提供统一的访问机制。

任何数据结构只要部署lterator接口,就可以完成遍历操作。

作用:

  • 为各种数据结构,提供一个统一的、简便的访问接口。

  • 使得数据结构的成员能够按某种次序排列。

  • ES6新增了for…of循环语句,用于遍历迭代器。

lterator接口

在JavaScript 中迭代器( lterator )是一个对象,该对象提供next()方法用于返回序列中的下一项。该方法返回包含done和 value 两个属性的对象。

  • 作用 - 用于返回序列中的下一项

  • 返回值 - 是一个对象

    • done属性 - 表示是否迭代完毕

      • false - 表示当前没有迭代完毕

      • true - 表示当前迭代完毕

    • value属性 - 表示当前迭代的值

function fn(array) {
    var index = 0;
    return {
        next: function () {
            return index < array.length
                ? {
                    // 是否迭代完毕
                    done: false,
                    value: array[index++],
                }
                : {
                    done: true,
                };
        },
    };
}

let arr = ["tom", "king", "luck"];
let iterator = fn(arr);

console.log(iterator.next()); // { done: false, value: 'tom' }
console.log(iterator.next()); // { done: false, value: 'king' }
console.log(iterator.next()); // { done: false, value: 'luck' }
console.log(iterator.next()); // { done: true }

迭代器对象一旦被创建,就可以反复调用next()方法用于依次访问对象中的键值。

数据结构:

  • Array

  • Map

  • Set

  • String

  • TypedAccay.

  • 函数的arguments 对象

  • NodeList 对象

迭代协议
  • 可迭代协议

  • 迭代器协议

for…of语句

for…of语句的用法

遍历迭代器

// 遍历数组
let arr = [1, 2, 3, 4, 5];
for (let attr of arr) {
    // attr得到的是数组的元素内容
    console.log(attr);
}

// 遍历Set集合
let set = new Set(arr);
for (let attr of set) {
    // attr得到的是Set的元素内容
    console.log(attr);
}
// 遍历map集合
let num = 100,
    str = "张无忌",
    fun = function () {},
    obj = {};

map.set("num", num);
map.set("str", str);
map.set("fun", fun);
map.set("obj", obj);

for (let attr of map) {
    // attr得到的是Map的[key,value]键值对数组
    console.log(attr);
}

// 遍历字符串
let string = "dg";
for (let attr of string) {
    // attr得到的是字符串的每一个
    console.log(attr);
}

 

返回选代器对象的方法

返回一个迭代器对象

与forEach()方法的区别
  • forEach()方法无法跳出循环。换句话讲,break 语句和 continue语句无效。

  • for…of语句不仅可以使用break语句和 continue语句,还可以配合使用return语句。

与for…in语句的区别

用于遍历对象

  • for…in不仅遍历自身,还会遍历手动添加的,甚至包括原型链的。

  • 如果用于遍历数组的话,遍历得到的键名为字符串类型的数字值。

object.prototype.objcustom = function() {};
Array. prototype.arrcustom = function() {};
let iterable = [3,5,7];

iterable.foo = 'hello' ;
let result = object.getOwnPropertyNames(iterable);
console.log(result);

for (let i in iterable) {
    console.log(i);// logs o,1,2,"foo","arrcustom","objcustom"
}

生成器

Generator函数是什么

虽然可以自定义一个迭代器,但自定义的迭代器需要显式地维护其内部状态。而生成器提供了另一个强大的选择,其提供了允许定义一个包含自有迭代算法的函数,同时可以自动维护其内部状态。Generator函数可以作为生成一个迭代器的特殊函数,该函数被调用时返回一个 Generator对象,该对象是符合可迭代协议和迭代器协议的。

Generator函数与普通函数的区别在于:

  • function*这种声明方式会定义一个生成器函数,它返回一个 Generator对象。

  • yield关键字用来暂停和恢复一个生成器函数。

 

function*表达式

function*这种声明方式( function关键字后跟一个星号)会定义一个生成器函数(Generatorfunction ),它返回一个 Generator 对象。

生成器函数在执行时能暂停,后面又能从暂停处继续执行。

function* fn() {}
let result = fn();

console.log(result);// Object [Generator] {}
yield表达式

用来暂停和恢复一个生成器函数。

[rv]=yield[expression]
// 定义一个生成器函数
function* fn() {
    let arr = ["tom", "king", "lucky"];
    for (let i = 0; i < arr.length; i++) {
        yield arr[i];
    }
}
// 生成器函数调用返回生成器对象
let generator = fn();
// 生成器对象就是ES6提供的迭代器
console.log(generator.next()); // { value: 'tom', done: false }
console.log(generator.next()); // { value: 'king', done: false }
console.log(generator.next()); // { value: 'lucky', done: false }
console.log(generator.next()); // { value: 'undefined', done: true }
yield*表达式

用于委托给另一个Generator 或可迭代对象。

yield*[[expression]]
function* g1() {
    yield 2;
    yield 3;
}
function* g2() {
    yield 1;
    yield* g1();
    yield 4;
}
// 生成器函数调用返回生成器对象
let generator = g2();
// 生成器对象就是ES6提供的迭代器
console.log(generator.next()); // { value: 1, done: false }
console.log(generator.next()); // { value: 2, done: false }
console.log(generator.next()); // { value: 3, done: false }
console.log(generator.next()); // { value: 4, done: false }
console.log(generator.next()); // { value: undefined, done: true }
Generator对象的方法
方法名称 描述
next()方法 返回一个包含属性done和value 的对象。该方法也可以通过接受一个参数用以向生成器传值
return()方法 返回给定的值并结束生成器
throw()方法 用于向生成器抛出异常,并恢复生成器的执行,返回带有done及 value两个属性的对象

next()、throw()、return()这三个方法本质上是同一件事,可以放在一起理解。它们的作用都是让Generator函数恢复执行,并且使用不同的语句替换yield表达式。