ES6标准---【七】【学习ES6标准看这一篇就够了!!!】

目录

以往ES6文章:

iterator(遍历器)概念

Iterator的作用

Iterator遍历过程

一个模拟next方法返回值的例子

默认Iterator接口

原生具有Iterator接口的数据结构

调用Iterator的场合

解构赋值

扩展运算符

yield*

其他场合

字符串的Iterator接口

修改原生的Symbol.iterator方法

for...of循环【重要】

遍历数组

Set和Map结构

计算生成的数据结构

类似数组的对象

对象

与其他遍历语法的比较

 最原始for循环

内置的forEach方法

for...in循环

for...of循环

以往ES6文章:

ES6标准---【一】【学习ES6看这一篇就够了!!】_es6学习-CSDN博客

ES6标准---【二】【学习ES6看这一篇就够了!!】_es6中的includes-CSDN博客

ES6标准---【三】【学习ES6看这一篇就够了!!!】-CSDN博客

ES6标准---【四】【学习ES6标准看这一篇就够了!!!】_es6 有arguments 吗-CSDN博客

ES6标准---【五】【看这一篇就够了!!!】-CSDN博客

ES6标准---【六】【学习ES6标准看这一篇就够了!!!】-CSDN博客

iterator(遍历器)概念

JavaScript原有的表示“集合”的数据结构,主要是数组(array)对象(object)

ES6又添加了“Map”、“Set

用户还可以组合使用它们,定义自己的数据结构

如:“数组的成员是MapMap的成员是对象

为此我们需要一种统一的接口机制,来处理所有不同的数据结构(包括用户自定义的数据结构),这个机制就是“遍历器”(Iterator)

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

Iterator的作用

  • 为各种数据结构,提供一个统一的、简便的访问接口
  • 使得数据结构的成员能够按某种次序排列
  • 创造了一种“for...of”循环,Iterator主要依靠它来实现遍历

Iterator遍历过程

  • 创建一个指针对象,指向当前数据结构的起始位置
  • 第一次调用指针对象的next方法,可以将指针指向数据结构的第一个成员
  • 第二次调用指针对象的next方法,可以将指针指向数据结构的第二个成员
  • 不断调用指针对象的next方法,直到指向结束位置

每一次调用next方法,都会返回数据结构当前遍历成员的信息

返回内容:一个包含“value”和“done”两个属性的对象

  • value:当前成员的值
  • done:布尔值,表示遍历是否结束

一个模拟next方法返回值的例子

注意:

只是模拟!!!!

var it = makeIterator(['a', 'b']);
it.next() // { value: "a", done: false }
it.next() // { value: "b", done: false }
it.next() // { value: undefined, done: true }
function makeIterator(array) {
  var nextIndex = 0;
  return {
    next: function() {
      return nextIndex < array.length ?
        {value: array[nextIndex++], done: false} :
        {value: undefined, done: true};
    }
  };
}

默认Iterator接口

ES6规定,默认的Iterator接口部署在数据结构的“Symbol.iterator”属性(一个数据结构只要有Symbol.iterator属性,就可以遍历)

ES6的有些数据结构原生具有Iterator接口,而有的数据结构需要部署“Symbol.iterator属性”才能够遍历,称部署了遍历器接口

原生具有Iterator接口的数据结构

  • array:数组
  • Map:映射
  • Set:集合
  • String:字符串
  • TypedArray
  • 函数的arguments对象
  • NodeList对象

对于原生部署Iterator接口的数据结构,不用自己写遍历器生成函数,“for...of”循环会自动遍历它们

调用Iterator的场合

解构赋值

数组set结构进行解构赋值时,会默认调用Symbol.iterator方法

let set = new Set().add('a').add('b').add('c');
let [x,y] = set;
// x='a'; y='b'
let [first, ...rest] = set;
// first='a'; rest=['b','c'];

扩展运算符

扩展运算符(...)也会调用默认的Iterator接口

// 例一
var str = 'hello';
[...str] //  ['h','e','l','l','o']
// 例二
let arr = ['b', 'c'];
['a', ...arr, 'd']
// ['a', 'b', 'c', 'd']

实际上,这提供了一种简便机制,可以将任何部署了Iterator接口的数据结构转为数组

let arr = [...iterable];

yield*

yield*后面跟的是一个可遍历的结构,它会调用该结构的遍历器接口

let generator = function* () {
  yield 1;
  yield* [2,3,4];
  yield 5;
};
var iterator = generator();
iterator.next() // { value: 1, done: false }
iterator.next() // { value: 2, done: false }
iterator.next() // { value: 3, done: false }
iterator.next() // { value: 4, done: false }
iterator.next() // { value: 5, done: false }
iterator.next() // { value: undefined, done: true }

其他场合

  • for...of
  • Array.from()
  • Map()、Set()、
  • Promise.all()
  • Promis.race()

字符串的Iterator接口

字符串是一个类似数组的对象,也原生具有Iterator接口

var someString = "hi";
typeof someString[Symbol.iterator]
// "function"
var iterator = someString[Symbol.iterator]();
iterator.next()  // { value: "h", done: false }
iterator.next()  // { value: "i", done: false }
iterator.next()  // { value: undefined, done: true }

修改原生的Symbol.iterator方法

我们可以覆盖原生的Symbol.iterator方法,达到修改遍历器的目的

var str = new String("hi");
[...str] // ["h", "i"]
str[Symbol.iterator] = function() {
  return {
    next: function() {
      if (this._first) {
        this._first = false;
        return { value: "bye", done: false };
      } else {
        return { done: true };
      }
    },
    _first: true
  };
};
[...str] // ["bye"]
str // "hi"

for...of循环【重要

for...of循环可以使用的范围包括“数组”、“Set”、“Map”、“字符串”等等

for...of循环内部调用的是数据结构的Symbol.iterator方法

语法:

for(变量 of Iterator)

{

        ....

}

遍历数组

<body>
	<script>
		const arr = ['red', 'green', 'blue'];
		console.log("遍历arr:"); 
		for(let v of arr) {
			console.log(v); // red green blue
		}
		const obj = {};
		console.log("遍历obj:"); 
		obj[Symbol.iterator] = arr[Symbol.iterator].bind(arr);
		for(let v of obj) {
			console.log(v); // red green blue
		}
	</script>
</body>

效果:

因为对象obj部署了arr的Symbol.iterator属性,结果obj的for...of循环产生了与arr完全一样的结果(因为for...of遍历的是Iterator的Symbol.iterator属性)

  • JavaScript原有的“for...in”循环,只能获得对象的键名,不能直接获取键值。ES6提供“for...of”循环,允许遍历获得键值
var arr = ['a', 'b', 'c', 'd'];
for (let a in arr) {
  console.log(a); // 0 1 2 3
}
for (let a of arr) {
  console.log(a); // a b c d
}
  • for...of循环调用遍历器接口,数组的遍历器接口只返回具有数字索引的属性,而for...in会全部返回对象的所有属性
let arr = [3, 5, 7];
arr.foo = 'hello';
for (let i in arr) {
  console.log(i); // "0", "1", "2", "foo"
}
for (let i of arr) {
  console.log(i); //  "3", "5", "7"
}

Set和Map结构

SetMap的遍历顺序都是按照“各个成员被添加进数据结构的顺序”

  • Set结构遍历:返回一个值
  • Map结构遍历:返回一个数组(键:键名)
var engines = new Set(["Gecko", "Trident", "Webkit", "Webkit"]);
for (var e of engines) {
  console.log(e);
}
// Gecko
// Trident
// Webkit
var es6 = new Map();
es6.set("edition", 6);
es6.set("committee", "TC39");
es6.set("standard", "ECMA-262");
for (var [name, value] of es6) {
  console.log(name + ": " + value);
}
// edition: 6
// committee: TC39
// standard: ECMA-262

计算生成的数据结构

ES6数组SetMap都部署了下面三个方法,调用后都返回遍历器对象

  • entries():返回一个遍历器对象,用来遍历[键名,键值],对于数组,键名就是索引,键是索引值,对于Set,键名与键值相同(Map结构的iterator接口默认调用entries方法)
  • keys():返回一个遍历器对象,用来遍历所有的键名
  • values():返回一个遍历器对象,用来遍历所有的键值
let arr = ['a', 'b', 'c'];
for (let pair of arr.entries()) {
  console.log(pair);
}
// [0, 'a']
// [1, 'b']
// [2, 'c']

类似数组的对象

// 字符串
let str = "hello";
for (let s of str) {
  console.log(s); // h e l l o
}
// DOM NodeList对象
let paras = document.querySelectorAll("p");
for (let p of paras) {
  p.classList.add("test");
}
// arguments对象
function printArgs() {
  for (let x of arguments) {
    console.log(x);
  }
}
printArgs('a', 'b');
// 'a'
// 'b'
  • 并不是所有类似数组的对象都具有Iterator结构,一个解决办法,就是用array.from方法将其转为数组(或使用扩展运算符)
let arrayLike = { length: 2, 0: 'a', 1: 'b' };
// 报错
for (let x of arrayLike) {
  console.log(x);
}
// 正确
for (let x of Array.from(arrayLike)) {
  console.log(x);
}

效果

对象

对于普通的对象,for...of结构不能直接使用,会报错,必须部署了iterator接口才能使用

但是for...in仍然可以用来遍历键名

let es6 = {
  edition: 6,
  committee: "TC39",
  standard: "ECMA-262"
};
for (let e in es6) {
  console.log(e);
}
// edition
// committee
// standard
for (let e of es6) {
  console.log(e);
}
// TypeError: es6[Symbol.iterator] is not a function
  • 可以使用Object.keys()Object.values()Object.entries()方法来遍历普通对象
<body>
	<script>
		let es6 = {
			edition: 6,
			committee: "TC39",
			standard: "ECMA-262"
		}
		console.log("遍历键:");
		for (let e of Object.keys(es6)) {
			console.log(e);
		}
		console.log("遍历值:");
		for (let e of Object.values(es6)) {
			console.log(e);
		}
		console.log("遍历键值对:");
		for (let e of Object.entries(es6)) {
			console.log(e);
		}
	</script>
</body>

效果:

与其他遍历语法的比较

数组为例说明不同遍历语法之间的区别

 最原始for循环

for (var index = 0; index < myArray.length; index++) {
  console.log(myArray[index]);
}

内置的forEach方法

foeEach的问题在于,break命令、return命令不能中途退出for循环

myArray.forEach(function (value) {
  console.log(value);
});

for...in循环

for...in循环有几个缺点

  • 数组的键名全是数字,但是for...in循环是以字符串“0”、“1”、“2”作为键名
  • for...in循环不仅遍历数组键名,还会遍历手动添加的其他键
  • 某些情况下,for...in循环会以任意顺序遍历键名

for...in循环主要是为遍历对象而设计的,不适用于遍历数组

for (var index in myArray) {
  console.log(myArray[index]);
}

for...of循环

for...of循环的优点

  • 有着与for...in一样的语法,但是没有for...in的缺点
  • 可以与breck、return、continue配合使用
  • 提供了遍历所有数据结构的统一操作接口
for (let value of myArray) {
  console.log(value);
}
学习webpack是为了掌握前端代码打包工具的使用。随着前端工程化的发展,webpack已经成为了前端开发中最常用的打包工具之一。学习webpack可以帮助我们对项目的模块化管理、代码压缩与优化、资源加载等方面进行更加灵活和高效的处理。 这篇文章主要介绍了webpack的基础知识和使用方法。首先,它解释了webpack的基本概念,如入口和出口文件、loader和plugin等。然后,它详细介绍了如何配置webpack的各个参数和插件,包括如何使用Babel处理ES6语法,如何使用Less或Sass处理CSS,如何使用图片压缩插件等。 接着,文章讲解了webpack的打包原理和优化技巧。它介绍了webpack的模块化加载机制,以及如何使用Code Splitting和Dynamic Import等功能来提高页面加载速度。同时,它还提到了如何使用webpack进行代码分割和缓存优化,以及如何使用Tree Shaking和代码压缩插件来减小项目的体积。 最后,文章介绍了webpack的常见问题和解决方法。它列举了一些常见的错误和警告信息,并提供了相应的解决方案。此外,它还提供了一些常用的webpack插件和工具的推荐,帮助我们更好地进行前端开发。 总的来说,这篇文章提供了一个很好的入门教程,可以帮助我们快速掌握webpack的基本概念和使用方法。但是,要想在实际项目中灵活应用webpack,还需要深入学习官方文档和相关资料,并结合实际项目进行实践。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

是洋洋a

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

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

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

打赏作者

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

抵扣说明:

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

余额充值