• 前端架构师之01_ES6_基础


    1 初识ES6

    简单来说,ECMAScript是JavaScript语言的国际标准,JavaScript是实现ECMAScript标准的脚本语言。

    2011年,ECMA国际标准化组织在发布ECMAScript 5.1版本之后,就开始着手制定第6版规范。

    存在的问题:这个版本引入的语法功能太多,而且制定过程当中,还有很多组织和个人不断提交新功能。很明显,在一个版本中不可能包含所有的要引入的新功能,这些功能要被发布在不同的版本中。

    解决方法:标准的制定者决定在每年的6月份发布一次新标准,并且使用年份作为版本号。

    年份版本简称
    2015年6月ECMAScript 2015ES6
    2016年6月ECMAScript 2016ES7
    2017年6月ECMAScript 2017ES8
    2018年6月ECMAScript 2018ES9
    2019年6月ECMAScript 2019ES10
    2020年6月ECMAScript 2020ES11

    2 let和const关键字

    2.1 let关键字

    let是ES6中新增的用于声明变量的关键字。在ES6之前,我们使用var关键字来声明变量。与var关键字相比,let关键字有一些新的特性。

    let关键字的新的特性:

    块级作用域有效
    • let关键字声明的变量只在所处的块级作用域有效。
    • 防止代码块内层变量覆盖外层变量
    <script>
    	if (true) {
    		let a = 10;
    		console.log(a);	// 输出结果:10
    	}
    	console.log(a);	// 报错,a未定义
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 防止循环变量变成全局变量
    <script>
    	for (let i = 0; i < 2; i++) { }
    	console.log(i);	// 报错,i未定义
    script>
    
    • 1
    • 2
    • 3
    • 4
    不存在变量提升
    • let关键字声明的变量不存在变量提升。
    • 在使用var关键字声明变量时,变量可以先使用再声明,这种现象就是变量提升。但一般的编程习惯,变量应该在声明之后才可以使用。
    • 在ES6中,变量的使用规范更加严格,使用let关键字声明的变量只能在声明之后才可以使用,否则就会报错。
    <script>
    	// 不存在变量提升
    	console.log(a);	// 报错,a未初始化
    	let a = 10; 
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    有暂时性死区特性
    • let关键字声明的变量具有暂时性死区特性。
    • 使用let关键字声明的变量具有暂时性死区特性。这是因为let关键字声明的变量不存在变量提升,其作用域都是块级作用域,在块级作用域内使用let关键字声明的变量会被整体绑定在这个块级作用域中形成封闭区域,不再受外部代码影响。
    • 所以在块级作用域内,使用let关键字声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”。
    <script>
    	var num = 10;
    	if (true) {
    		console.log(num);	// 报错,无法在初始化之前访问num
    		let num = 20;
    	}
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    2.2 const关键字

    const是ES6中新增的用于声明常量的关键字。所谓常量就是值(内存地址)不能变化的量。

    const关键字声明的常量的特点:

    块级作用域
    • const关键字声明的常量具有块级作用域。
    <script>
    	if (true) {
    		const a = 10;
    		console.log(a);	// 输出结果:10
    	}
    	console.log(a);	// 报错,a未定义
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    必须赋值
    • const关键字声明常量时必须赋值。
    <script>
    	const PI;	// 报错,常量PI未赋值
    script>
    
    • 1
    • 2
    • 3
    值不能修改
    • const关键字声明常量并赋值后常量的值不能修改。
    • 对于基本数据类型(如数值、字符串),一旦赋值,值就不可修改。
    <script>
    	const PI = 3.14;
    	PI = 100;	// 报错,无法对常量赋值
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 对于复杂数据类型(如数组、对象),虽然不能重新赋值,但是可以更改内部的值。
    <script>
    	const ary = [100, 200];
    	ary[0] = 'a';
    	ary[1] = 'b';
    	console.log(ary);  // 可以更改数组内部的值,结果为['a', 'b']
    	ary = ['a', 'b’];    // 报错,无法对常量赋值
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    2.3 let、const、var关键字之间的区别

    变量的作用域范围不同
    • 使用var关键字声明的变量,其作用域为该语句所在的函数内,且存在变量提升现象。
    • 使用let关键字声明的变量和使用const关键字声明的常量都具有块级作用域。
    变量提升
    • 使用var关键字声明的变量存在变量提升,可以先使用再声明。
    • 使用let关键字声明的变量和const关键字声明的常量不存在变量提升功能,只能先声明再使用。
    值是否可以更改
    • 使用var关键字和let关键字声明的变量,可以更改变量的值。
    • 但使用const关键字声明的常量,不能更改常量值对应的内存地址。

    在编写程序的过程中,如果要存储的数据不需要更改,建议使用const关键字,如函数的定义、 π值或数学公式中一些恒定不变的值。

    由于使用const声明的常量,其值不能更改,且JavaScript解析引擎不需要实时监控值的变化,所以使用const关键字要比let关键字效率更高。

    3 解构赋值

    解构表示对数据结构进行分解,赋值指变量的赋值。也就是拆解架构,重新赋值。

    在ES6中,允许按照一一对应的方式,从数组或对象中提取值,然后将提取出来的值赋给变量。

    解构赋值的优点是它可以让编写的代码简洁易读,语义更加清晰,并且可以方便地从数组或对象中提取值。

    3.1 数组的解构赋值

    数组的解构赋值,就是将数组中的值提取出来,然后赋值给另外的变量。

    • 变量的数量和数组中值的数量相一致的情况
    <script>
    	let [a, b, c] = [1, 2, 3];
    	console.log(a);	// 输出结果:1
    	console.log(b);	// 输出结果:2
    	console.log(c);	// 输出结果:3
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 变量的数量和数组中值的数量不一致的情况
    <script>
    	let [a, b, c, d] = [1, 2, 3];
    	console.log(a);	// 输出结果:1
    	console.log(b);	// 输出结果:2
    	console.log(c);	// 输出结果:3
    	console.log(d);	// 输出结果:undefined
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    3.2 对象的解构赋值

    对象解构允许使用变量的名字匹配对象中属性,如果匹配成功就将对象中属性的值赋值给变量。

    <script>
    	let person = { name: 'zhangsan', age: 20 };
    	// 变量的名字    具体被解构的对象
    	let { name, age } = person; // 解构赋值
    	console.log(name);		    // 输出结果:zhangsan
    	console.log(age);           // 输出结果:20
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    使用另外一种形式去实现对象的解构赋值,该形式支持变量的名字和对象中属性的名字不一样的情况,等号左边的大括号代表对象解构。

    <script>
    	let person = { name: 'zhangsan', age: 20, sex: '男' };
    	// 属性名:变量名       具体被解构的对象
    	let { name: myName } = person;
    	console.log(myName);	// zhangsan
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    3.3 字符串解构赋值

    字符串能够使用解构赋值的原因是: 字符串时特殊的数组(字符串能够被转换成一个类似数组的对象)

    let [a, b, c, d, e] = "Hello";
    console.log(a, b, c, d, e);
    
    • 1
    • 2

    3.4 解构赋值的用途

    • 交换变量的值
    let a = 3, b = 5;
    [a, b] = [b, a];
    console.log(a, b);
    
    • 1
    • 2
    • 3
    • 从函数内部返回多个值
    let {dataObj} = {code: 200, msg: 'ok', dataObj: ['jack','rose','bob','小明']}; 
    console.log(dataObj);
    
    • 1
    • 2
    • 快速提取一个对象中的属性或方法
    let {floor, random, sin} = Math;
    console.log('======');
    console.log(Math.floor(Math.random() * 256)); // 原来的操作
    console.log(floor(random() * 256));	// 现在的操作
    
    • 1
    • 2
    • 3
    • 4

    4 箭头函数

    箭头函数是ES6中新增的函数,它用于简化函数的定义语法,有自己的特殊语法,接收一定数量的参数,并在其封闭的作用域的上下文(即定义它们的函数或其他代码)中操作。

    4.1 箭头函数的语法

    // 箭头函数基本语法
    () => { }
    
    • 1
    • 2
    • 箭头函数以小括号开头,在小括号中可以放置参数。小括号的后面要跟着箭头(=>),箭头后面要写一个大括号来表示函数体,这是箭头函数的固定语法。
    • 箭头函数调用:因为箭头函数没有名字,我们通常的做法是把箭头函数赋值给一个变量,变量名就是函数名,然后通过变量名去调用函数即可。
    <script>
    	// 定义没有参数的箭头函数
    	const fn = () => {
    		console.log(123);  // 输出结果:123
    	};
    	// 函数调用
    	fn();		
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    4.2 箭头函数的特点

    省略大括号
    • 在箭头函数中,如果函数体中只有一句代码,且代码的执行结果就是函数的返回值,此时可以省略函数体大括号。
    <script>
    	// 计算两个数值相加的结果
    	const sum = (num1, num2) => num1 + num2;
    	// 等价于
    	// const sum = (num1, num2) => {
    	//   return num1 + num2;
    	// };
    	const result = sum(10, 20); // 使用result接收sum()函数执行的结果
    	console.log(result); 	     // 在控制台输出result值,结果为30
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    省略参数外部的小括号
    • 在箭头函数中,如果参数只有一个,可以省略参数外部的小括号。
    <script>
    	// 只有一个参数的函数定义方式
    	// 传统的函数定义方式
    	// function fn(v) {
    	//   return v;
    	// }
    	// ES6中函数定义方式
    	const fn = v => v;
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 定义带有一个参数的函数,并在浏览器的弹出框中弹出参数值。
    <script>
    	const fn = v => {
    		alert(v);
    	};
    	fn(20);
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    4.3 箭头函数中的this关键字

    • ES6前,JavaScript的this关键字指向的对象是在运行时基于函数的执行环境绑定的,在全局函数中,this指向的是window;当函数被作为某个对象的方法调用时,this就指向那个对象。
    • ES6中,箭头函数不绑定this关键字,它没有自己的this关键字,如果在箭头函数中使用this关键字,那么this关键字指向的是箭头函数定义位置的上下文this。也就是说,箭头函数被定义在哪,箭头函数中的this就指向谁。
    • 箭头函数解决了this执行环境所造成的一些问题,如解决了匿名函数this指向的问题(匿名函数的执行环境具有全局性),包括setTimeout()和setInterval()中使用this所造成的问题。
    <script>
    	const obj = { name: 'zhangsan' };
    	function fn() {
    		console.log(this);  // 输出结果:{name: "zhangsan"}
    		return () => {
    			console.log(this);  // 输出结果:{name: "zhangsan"}
    		};
    	}
    	// call()方法可以改变函数内部的this指向,将函数fn()内部的this指向obj对象
    	const resFn = fn.call(obj);
    	resFn();
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    5 剩余参数

    5.1 剩余参数的语法

    剩余参数是指在函数中,当函数实参个数大于形参个数时,剩余的实参可以存放到一个数组中。

    剩余参数语法允许将一个不确定数量的参数表示为数组。这种不确定参数的定义方式对于声明一个具有未知参数个数的函数非常方便。

    <script>
    	function sum(first, ...args) {  // 接收剩余参数
    		console.log(first);   // 输出结果:10
    		console.log(args);  // 输出结果:[20, 30]
    	}
    	sum(10, 20, 30);	
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    剩余参数是程序员自定义的一个普通标识符,接收剩余参数的变量是一个数组(Array的实例),能够直接使用所有的数组方法,如 sort()、map()、forEach()或pop()方法等。

    <script>
    	// 使用剩余参数计算多个数值的求和结果
    	const sum = (...args) => {
    		let total = 0;
    		args.forEach((item) => {
    			total += item;
    		});
    		// 等价于:args.forEach(item => total += item);
    		return total;
    	};
    	console.log(sum(10, 20));  // 输出结果:30
    	console.log(sum(10, 20, 30));  // 输出结果:60
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    5.2 剩余参数和解构赋值配合使用

    <script>
    	// 以数组的解构赋值为例
    	let students = ['王五', '张三', '李四'];
    	let [s1, ...s2] = students;
    	console.log(s1);  // 输出结果:王五
    	console.log(s2);  // 输出结果:["张三", "李四"]
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    6 扩展运算符

    6.1 扩展运算符的语法

    扩展运算符和剩余参数的作用是相反的,扩展运算符可以将数组或对象转换为用逗号分隔的参数序列。扩展运算符也用3个点 表示。

    <script>
    	let ary = [1, 2, 3];
    	// ...ary相当于1, 2, 3
    	console.log(...ary);	// 输出结果:1 2 3
    	// 等价于
    	console.log(1, 2, 3);	// 输出结果:1 2 3
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    使用扩展运算符将ary数组拆分成以逗号分隔的参数序列后,又将参数序列放在了console.log()方法中,此时参数序列中的逗号会被当成console.log()方法的参数分隔符,所以输出结果中没有逗号。

    6.2 扩展运算符的应用

    • 利用扩展运算符合并数组
    <script>
    	// 数组合并的第1种方法
    	let ary1 = [1, 2, 3];
    	let ary2 = [4, 5, 6];
    	// ...ary1  			// 表示将ary1数组拆分成1, 2, 3
    	// ...ary2  			// 表示将ary2数组拆分成4, 5, 6
    	let ary3 = [...ary1, ...ary2]; 
    	console.log(ary3);		// 输出结果:(6) [1, 2, 3, 4, 5, 6]
    script>
    
    <script>
    	// 数组合并的第2种方法
    	let ary1 = [1, 2, 3];
    	let ary2 = [4, 5, 6];
    	ary1.push(...ary2);
    	console.log(ary1); 		// 输出结果:(6) [1, 2, 3, 4, 5, 6]
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 利用扩展运算符将伪数组转换为真正的数组
      • 伪数组:可以应用数组的length属性但是无法直接调用数组方法,它也可以像数组一样进行遍历。典型的伪数组包括函数中的arguments、document.getElementsByTagName()返回的元素集合,以及document.childNodes等。
    <body>
    	<div>1div>
    	<div>2div>
    	<div>3div>
    	<div>4div>
    	<div>5div>
    	<div>6div>
    	<script>
    		var oDivs = document.getElementsByTagName('div');
    		console.log(oDivs);	// 输出结果:HTMLCollection(6) [div, div, div, div, div, div]
    		var ary = [...oDivs];
    		ary.push('a');	// 在数组中追加a
    		console.log(ary);	// 输出结果:(7) [div, div, div, div, div, div, "a"]
    	script>
    body>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    7 模板字符串

    7.1 模板字符串的语法

    模板字符串是ES6新增的创建字符串的方式,它使用反引号进行定义。

    <script>
    	let name = `这是一个模板字符串`;
    	console.log(name);	// 输出结果:这是一个模板字符串
    script>
    
    • 1
    • 2
    • 3
    • 4

    7.2 模板字符串的应用

    • 模板字符串可以解析变量
    <script>
    	let name = `张三`;
    	let sayHello = `Hello, 我的名字叫${name}`;
    	console.log(sayHello); // 输出结果:Hello, 我的名字叫张三
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 在模板字符串中可以换行
    <script>
    	let result = { name: 'zhangsan',age: 20,sex: '男' };
    	let html = `
    	
    ${result.name} ${result.age} ${result.sex}
    `
    ; console.log(html);
    script>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 在模板字符串中可以调用函数
    <script>
    	const fn = () => {
    		return '我是fn函数';
    	};
    	let html = `我是模板字符串 ${fn()}`;
    	console.log(html);	// 输出结果:我是模板字符串 我是fn函数
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    8 ES6的内置对象扩展

    8.1 数组的扩展方法

    ES6为Array(数组)、String(字符串)等内置对象提供了许多扩展方法,从而帮助开发人员提高开发效率。

    通过扩展方法可以实现很多方便的功能,如将伪数组转换为真正的数组、在数组中查找出符合条件的数组成员等。

    Array.from()方法
    • Array构造函数提供了一个from()方法,它可以接收一个伪数组作为参数,返回值为转换后的结果,这个结果是一个真正的数组。
    <script>
    	var arrayLike = {
    		'0': '张三','1': '李四','2': '王五',length: 3
    	};
    	var ary = Array.from(arrayLike);
    	console.log(ary); 	// 输出结果:(3) ["张三", "李四", "王五"]
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 在Array构造函数中,from()方法还可以接收两个参数,这与数组中的map()方法类似,它用于处理数组中的每个元素并将处理后的结果放入返回的数组中。
    <script>
    	var arrayLike = {
    		'0': 1,'1': 2,'2': 3,length: 3
    	};
    	var ary = Array.from(arrayLike, (item) => {
    		return item * 2;
    	});
    	// 等价于:var ary = Array.from(arrayLike, item => item * 2)
    	console.log(ary);	// 输出结果:[2, 4, 6]
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    Array.of() 方法
    • 将一组数转为数组。
    console.log(Array.of(9, 4, 2, 7)); // [9, 4, 2, 7]
    
    • 1
    数组实例的copyWithin()方法
    • 用于操作当前数组自身,用来把某些个位置的元素复制并覆盖到其他位置上去。
    • copyWithin(target[, start, end])
    • target 从该位置开始替换数据
    • start 可选值,默认为 0,从该位置开始读取值
    • end 可选值,默认为 数组长度,到该位置前停止读取
    • 注意:三个参数都应该是 数值,如果不是,系统会自动转为数值
    • 该方法会影响到原数组
    const numArr = [1,2,3,4,5,6,7,8];
    // 从0的位置开始替换,从5开始读取值,到8这个位置停止读取
    const relArr = numArr.copyWithin(0,5,8); 
    console.log(relArr);
    console.log(numArr);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    数组实例的find()方法
    • 在数组实例中,ES6提供了一个find()方法,它用于在数组中查找出第一个符合条件的数组成员。
    <script>
    	var ary = [{
    		id: 1, name: '张三'
    	}, {
    		id: 2,name: '李四'
    	}];
    	let target = ary.find((item, index) => item.id == 2);
    	console.log(target);	// 输出结果:{id: 2, name: "李四"}
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    数组实例的findIndex()方法
    • 数组实例提供了一个findIndex()方法,用于在数组中查找出第一个符合条件的数组成员的索引,如果没有找到则返回-1。
    <script>
    	// 找出数组中大于9的元素的位置
    	let ary = [1, 5, 10, 15];
    	let index = ary.findIndex((value, index) => {
    		return value > 9;
    	});
    	// 等价于:let index = ary.findIndex((value, index) => value > 9);
    	console.log(index);   // 输出结果:2
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    数组实例的includes()方法
    • ES6中为数组实例提供了includes()方法来检查某个数组是否包含给定的值,返回一个布尔值,true表示包含给定的值,false表示不包含给定的值。
    <script>
    	let ary = ['a', 'b', 'c'];
    	let result = ary.includes('a');
    	console.log(result);	// 输出结果:true
    	result = ary.includes('e')
    	console.log(result);	// 输出结果:false
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    keys() 遍历键名,values() 遍历值
    var arr = ['张三',18,'zzq2102','男','计算机'];
    var obj = {name:'张三',age:18,class:'zzq2102',sex:'男',major:'计算机'};
    var json = {"name":'张三',"age":18,"class":'zzq2102',"sex":'男',"major":'计算机'};
    
    // 循环输出数组
    for(let key of arr.keys()){
    	console.log(key);
    }
    for (let v of numArr.values()) {
    	console.log(v);
    }
    // 循环输出对象和json
    for(let key of Object.keys(obj)){
    	console.log(key);
    }
    // 数组含空位
    console.log([...[,'a'].keys()]); // [0, 1]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    数组实例的 entries() 键值对
    let numArr = [9, 5, 2, 7];
    for (const [i, v] of numArr.entries()) {
    	console.log(i, v);
    }
    
    • 1
    • 2
    • 3
    • 4

    8.2 字符串的扩展方法

    前面我们学习了数组的includes()方法,它用于在数组中查找出第一个符合条件的数组成员的位置。

    ES6也提供了字符串的includes()方法用来确定一个字符串是否包含在另一个字符串中。

    除此之外,ES6还提供了startsWith()方法和endsWith()方法同样可以用于字符串的查找。

    字符串实例的startsWith()方法和endsWith()方法
    • startsWith()方法表示参数字符串是否在原字符串的头部,用于判断字符串是否以某字符串开头;
    • endsWith()方法表示参数字符串是否在原字符串的尾部,用于判断字符串是否以某字符串结尾。
    • 上述两个方法如果满足条件则返回true,反之返回false。
    <script>
    	let str = 'Hello ECMAScript 2015';
    	let r1 = str.startsWith('Hello');
    	console.log(r1);   // 输出结果:ture
    	let r2 = str.endsWith('2016');
    	console.log(r2);   // 输出结果:false
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    字符串实例的repeat()方法
    • repeat()方法表示将原字符串重复n次,它返回一个新字符串,并接收一个数值作为参数,表示将字符串重复多少次。
    <script>
    	console.log('y' . repeat(5));	// 输出结果:yyyyy
    	console.log('hello' . repeat(2));	// 输出结果:hellohello
    script>
    
    • 1
    • 2
    • 3
    • 4

    8.3 字面量对象简写方式

    ES6中,如果对象的属性名和属性值对应的变量名相同,可以省略不写。

    let age = 20, name = 'Alice';
    
    // ES5: 定义对象字面量
    let obj = {
    	age: age,
    	name: name,
    	say: function() {
    		console.log(1);
    	}
    }
    
    // ES6: 定义对象字面量
    let obj = {
    	age,
    	name,
    	say() {
    		console.log(1);
    	}
    }
    console.log(obj.name)
    obj.say();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    9 初识Symbol

    9.1 Symbol的基本使用

    Symbol是ES6中引入的原始数据类型,它的功能类似于一种标识唯一性的ID值,表示独一无二。

    Symbol通过Symbol()函数创建。Symbol()函数可以接收一个字符串作为参数,为新创建的Symbol实例提供描述信息,该描述信息主要是在控制台中显示或转为字符串时使用,以便于区分。Symbol不是对象,所以Symbol()函数不能使用new命令。

    <script>
    	let s1 = Symbol('a');
    	let s2 = Symbol('b');
    	console.log(s1);	// 输出结果:Symbol(a)
    	console.log(s2);	// 输出结果:Symbol(b)
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    每个Symbol实例都是唯一的,即使具有相同参数的两个Symbol()函数进行比较时,函数的返回结果都会是false。

    <script>
    	let s1 = Symbol('a');
    	let s2 = Symbol('a');
    	console.log(s1);               // 输出结果:Symbol(a)
    	console.log(s2);               // 输出结果:Symbol(a)
    	console.log(s1 === s2);  // 输出结果:false
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    9.2 使用Symbol作为对象属性名

    因为每一个Symbol的值都是不相等的,所以Symbol作为对象的属性名,可以保证属性不重名。这适用于对象由多个模块组成的情况,可以防止某一个键被意外改写或覆盖。

    <script>
    	let MY_NAME = Symbol();
    	// 第1种写法
    	let a = {};
    	a[MY_NAME] = 'Hello!';
    	console.log(a);   // 输出结果:{ Symbol(): "Hello!" }
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    <script>
    	let MY_NAME = Symbol();
    	// 第2种写法 
    	let a = {
    		[MY_NAME]: 'Hello!',
    	};
    	console.log(a);  // 输出结果:{ Symbol(): "Hello!" }
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    <script>
    	let MY_NAME = Symbol();
    	// 第3种写法
    	let a = {};
    	Object.defineProperty(a, MY_NAME, { value: 'Hello!' });
    	console.log(a);   // 输出结果:{ Symbol(): "Hello!" }
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    10 Set数据结构

    10.1 Set数据结构基本使用

    ES6提供了新的数据结构Set。

    Set类似于数组,但是成员的值都是唯一的,没有重复的值。

    Set实例的方法分为两大类,即操作方法(用于操作数据)和遍历方法(用于遍历成员)。

    Set数据结构常用于电商网站的搜索功能中,用户搜索完成后,网站要记录用户搜索的关键字,方便用户下次直接单击搜索历史关键字来完成搜索。

    创建Set数据结构

    Set本身是一个构造函数,创建此构造函数的实例对象就是创建Set数据结构。

    <script>
    	const s1 = new Set();	// 使用new关键字创建Set构造函数的实例
    	console.log(s1.size);	// 输出结果:0
    script>
    
    • 1
    • 2
    • 3
    • 4
    初始化Set数据结构

    在创建Set数据结构时,也可以传递一个数组作为参数,用来初始化。

    <script>
    	const s2 = new Set(['a', 'b']);
    	console.log(s2.size); // 输出结果:2
    script>
    
    • 1
    • 2
    • 3
    • 4
    利用Set数据结构给数组去重

    在初始化Set构造函数时,可以传递一个数组作为参数,如果数组中有重复的值,那么Set数据结构会把重复的值过滤掉。

    <script>
    	const s3 = new Set(["a", "a", "b", "b"]);
    	console.log(s3.size); // 输出结果:2
    	const ary = [...s3];
    	console.log(ary);     // 输出结果:(2) ["a", "b"]
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    10.2 Set实例的操作方法

    add()方法

    Set实例提供的add()方法用于向Set数据结构中添加某个值,它接收一个参数代表要添加的值,返回Set结构本身。

    <script>
    	const s4 = new Set();
    	s4.add('a').add('b');
    	console.log(s4.size); // 输出结果:2
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    delete()方法

    Set实例提供的delete()方法用于删除Set数据结构中的某个值,它接收一个参数代表要删除的值,返回一个布尔值,如果结果为true则表示删除成功,为false则表示删除失败。

    <script>
    	const s4 = new Set();
    	s4.add('a').add('b');
    	const r1 = s4.delete('a');
    	console.log(s4.size);  // 输出结果:1
    	console.log(r1);  // 输出结果:true
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    has()方法

    Set实例提供has()方法,该方法接收一个参数并判断该参数是否为Set数据结构中的成员,返回一个布尔值,如果结果为true则表示包含该成员,为false则表示不包含该成员。

    <script>
    	const s4 = new Set();
    	s4.add('a').add('b');
    	const r1 = s4.delete('a');
    	console.log(s4.size);  // 输出结果:1
    	console.log(r1);       // 输出结果:true
    	const r2 = s4.has('a');
    	console.log(r2);       // 输出结果:false
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    clear()方法

    Set实例提供的clear()方法用于清除Set数据结构中的所有成员,该方法没有返回值。

    <script>
    	const s4 = new Set();
    	s4.add('a').add('b');
    	s4.clear();
    	console.log(s4.size); // 输出结果:0
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    10.3 Set实例的遍历方法

    Set数据结构的实例与数组一样,也拥有一个forEach()方法,用于遍历Set数据结构中的成员,该方法可以对每个成员执行某种操作,没有返回值。

    注:由于Set数据结构没有下标,所以不能使用通过下标方式获取数据。

    <script>
    	const s5 = new Set(['a', 'b', 'c']);
    	s5.forEach(value => {
    		console.log(value);  // 依次输出a、b、c
    	});
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    11 Map数据结构

    11.1 Map数据结构的基本使用

    JavaScript 的对象(Object),本质上是键值对的集合(属性值对),但是传统上只能用字符串当作键。这给它的使用带来了很大的限制。

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

    总的来说就是,Map数据结构类似于对象,用来存储键值对。但对象只能使用字符串作为属性名,而Map可以使用任意类型的数据做为属性名。

    创建初始化Map数据结构

    作为构造函数,Map 也可以接受一个数组作为参数。该数组的成员是一个个表示键值对的数组。

    let map = new Map([['a',1],['b',2]])
    let arr = [1,2,3]
    let map1 = new Map([[arr,5]])
    console.log(map1)
    
    • 1
    • 2
    • 3
    • 4

    11.2 Map实例的属性和方法

    size 属性
    let arr = [1,2,3]
    let map = new Map([['a',1],['b',2]])
    // 获取长度
    console.log(map.size); // 2
    
    • 1
    • 2
    • 3
    • 4
    set()方法
    map.set("name","John")
    map.set(arr,'100')
    
    • 1
    • 2
    get()方法
    console.log(map.get(arr));
    
    • 1
    has()方法
    console.log(map.has("b"));
    
    • 1
    delete()方法
    map.delete("a");
    
    • 1
    clear()方法
    map.clear()
    console.log(map);
    
    • 1
    • 2

    11.3 Map实例的遍历方法

    let map = new Map([['a', 1], ['b', 2]])
    
    // 遍历map
    for(let i of map){
    	// console.log(i);
    	console.log(i[0]);
    }
    
    // entries 键值对
    // 等价于上面的写法
    for(let data of map.entries()){
    	console.log(data);
    }
    
    // 分别获取键和值
    for(let [key,val] of map.entries()){
    	console.log(key,val);
    }
    
    // map.keys(): 返回所有的键名
    for(let key of map.keys()){
    	console.log(key);
    }
    
    // 返回所有的值
    for(let val of map.values()){
    	console.log(val);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
  • 相关阅读:
    备战蓝桥杯Day23-桶排序
    Android Studio Gradle中没有Task任务,没有Assemble任务,不能方便导出aar包
    JS基础--强制类型转换(易错点,自用)
    iOS 蓝牙连接 connectionSupervisionTimeout 是720ms 还是 2~6s
    一线大厂必问微服务系列——SpringCloudAlibaba整合Sleuth
    汽车服务门店小程序模板制作指南
    网页版微信客户管理系统,常见疑问解答
    Azkaban 内存不足报错
    Shrio整合Jwt
    Linux资源限制命令—ulimit
  • 原文地址:https://blog.csdn.net/zhangchen124/article/details/133386851