ES6总结大全(一)

一.ECMAScript和JavaScript的关系:

ECMAScript是JavaScript的规格,JavaScript是ECMAScript的一种实现(另外的 ECMAScript 方言还有 Jscript 和 ActionScript)。

日常场合,这两个词是可以互换的。

二.ES6与不同版本:

ES6 既是一个历史名词,也是一个泛指,含义是 5.1 版以后的 JavaScript 的下一代标准,涵盖了 ES2015、ES2016、ES2017 等等,而 ES2015 则是正式名称,特指该年发布的正式版本的语言标准。 ES6,一般是指 ES2015 标准,但有时也是泛指“下一代 JavaScript 语言”

三.Babel(Traceur是另外一个ES6转换器):

1.定义:

将ES6的代码转换成ES5的代码,从而在现有的环境中运行,让我们能用下一代JS(即ES6)编写前端代码

2.如何在webpack中使用babel:

(1)安装babel:

		      npm install --save-dev babel-loader babel-core

(2)在webpack中配置babel-loader:

				module: {
					rules: [
					  { test: /\.js$/, exclude: /node_modules/, loader: "babel-loader" }
						 ]
					}

(3)创建.babelrc配置文件:

安装预设:

npm install babel-preset-env --save-dev

在.bashrc中配置这些预设:

							{
								 "presets": ["env"]
							  }

3.注意:

在babel 6中,将babel拆分成两个包:babel-cli和babel-core。如果你想要在CLI(终端或REPL)使用babel就下载babel-cli,如果想要在node中使用就下载babel-core

四.let和const:

1.let:

作用域只限于当前代码块,TDZ: 暂时性死区;

使用let申明的变量作用域不会被提升

在相同作用域不能申明相同变量,不存在变量提升;

for循环体现let的父子作用域(es5中var申明时用闭包解决该问题)

2.const:

只在当前代码块中有效

作用域不能被提升

不能重复申明

申明的常量必须赋值(注意:常量为复合类型的数据时可以修改)

Object.freeze()可以将对象冻结,彻底不能修改

五.ES6中六种声明变量的方法:

var、function、let、const、import和class

var命令和function命令声明的全局变量,依旧是顶层对象的属性;

另一方面规定,let命令、const命令、class命令声明的全局变量,不属于顶层对象的属性

全局变量将逐步与顶层对象的属性脱钩

六.变量的解构赋值:

1.数组的解构赋值:

(1)解构:ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值

(2)ES6 允许写成下面这样:

		let [a, b, c] = [1, 2, 3];

(3)解构赋值允许指定默认值:

		let [x, y = 'b'] = ['a'];             // x='a', y='b'

		let [x, y = 'b'] = ['a', undefined];  // x='a', y='b'

注意:ES6 内部使用严格相等运算符(===),判断一个位置是否有值。

所以,只有当一个数组成员(===)严格等于undefined,默认值才会生效,为null时不生效

		let [x = 1] = [undefined];
		x // 1

		let [x = 1] = [null];
		x // null

2.对象的解构赋值:

(1)对象的解构与数组有一个重要的不同。数组的元素是按次序排列的,变量的取值由它的位置决定;

而对象的属性没有次序,变量必须与属性同名,才能取到正确的值

		let { bar, foo } = { foo: "aaa", bar: "bbb" };
		foo // "aaa"
		bar // "bbb"

(2) 和下面这种方法一样:

		let { foo: foo, bar: bar } = { foo: "aaa", bar: "bbb" };

3.字符串的解构赋值:

	const [a, b, c, d, e] = 'hello';

4.数值和布尔值的解构赋值:

(1)解构赋值时,如果等号右边是数值和布尔值,则会先转为对象;

由于undefined和null无法转为对象,所以对它们进行解构赋值

(2)示例:

		let {toString: s} = 123;
		s === Number.prototype.toString // true

		let {toString: s} = true;
		s === Boolean.prototype.toString // true

5.函数参数的解构赋值:

函数参数的解构也可以使用默认值

6.圆括号问题:

(1)不能使用圆括号的情况:

变量声明语句

函数参数

赋值语句的模式

(2)可以使用圆括号的情况:

只有一种:赋值语句的非模式部分,可以使用圆括号

7.解构赋值的用途:

(1)交换变量的值

(2)从函数返回多个值

(3)函数参数的定义

(4)提取json数据

(5)函数参数的默认值

(6)遍历Map结构

(7)输入模块的制定方法

七.字符串的扩展:

1.字符的 Unicode 表示法:

JavaScript 允许采用\uxxxx形式表示一个字符,其中xxxx表示字符的 Unicode 码点

比如:

"\u0061"
// "a"

2.codePointAt方法:

能够正确处理 4 个字节储存的字符,返回一个字符的码点

codePointAt方法会正确返回 32 位的 UTF-16 字符的码点。对于那些两个字节储存的常规字符,它的返回结果与charCodeAt方法相同

3.tring.fromCodePoint():

可以识别大于0xFFFF的字符,弥补了String.fromCharCode方法的不足。在作用上,正好与codePointAt方法相反

4.字符串的遍历器接口:

ES6 为字符串添加了遍历器接口,使得字符串可以被for…of循环遍历

	for (let codePoint of 'foo') {
			console.log(codePoint)
			}

5.normalize():

用来将字符的不同表示方法统一为同样的形式,这称为 Unicode 正规化;

	'\u01D1'.normalize() === '\u004F\u030C'.normalize()

6.includes(), startsWith(), endsWith():

字符串查找:str.includes(要找的东西) 返回true/false

str.indexof(要找的东西) 返回索引位置,没找到返回-1

(1)includes():返回布尔值,表示是否找到了参数字符串;

(2)startsWith():返回布尔值,表示参数字符串是否在原字符串的头部;

(3)endsWith():返回布尔值,表示参数字符串是否在原字符串的尾部。

这三个方法都支持第二个参数,表示开始搜索的位置

	let s = 'Hello world!';
	s.startsWith('world', 6) // true
	s.endsWith('Hello', 5) // true
	s.includes('Hello', 6) // false

7.repeat():

repeat方法返回一个新字符串,表示将原字符串重复n次;

	'na'.repeat('3') // "nanana"
	'hello'.repeat(2) // "hellohello"

8.padStart(),padEnd() :

ES2017 有了字符串补全长度功能。如果某个字符串不够指定长度,会在头部或尾部补全。

padStart()用于头部补全,padEnd()用于尾部补全;

padStart()和padEnd()一共接受两个参数,第一个参数是字符串补全生效的最大长度,第二个参数是用来补全的字符串

	'x'.padStart(5, 'ab') // 'ababx
	'x'.padEnd(5, 'ab') // 'xabab'

9.matchAll():

返回一个正则表达式在当前字符串的所有匹配

10.模板字符串:

模板字符串(template string)是增强版的字符串,用反引号(`)标识。

它可以当作普通字符串使用,也可以用来定义多行字符串,或者在字符串中嵌入变量

${ 变量或者函数或者字符串 }

11.标签模板:

模板字符串可以紧跟在一个函数名后面,该函数将被调用来处理这个模板字符串。称为“标签模板”

12.String.raw():

用来充当模板字符串的处理函数,返回一个斜杠都被转义(即斜杠前面再加一个斜杠)的字符串,对应于替换变量后的模板字符串

作为处理模板字符串的基本方法,它会将所有变量替换,而且对斜杠进行转义,方便下一步作为字符串来使用

作为正常的函数使用。这时,它的第一个参数,应该是一个具有raw属性的对象,且raw属性的值应该是一个数组

八.数值的扩展:

1.Number.isFinite(), Number.isNaN():

Number.isFinite()用来检查一个数值是否为有限的(finite),即不是Infinity;

Number.isNaN()用来检查一个值是否为NaN

Number.isFinite()对于非数值一律返回false,

Number.isNaN()只有对于NaN才返回true,非NaN一律返回false

2.Number.parseInt(), Number.parseFloat():

ES6 将全局方法parseInt()和parseFloat(),移植到Number对象上面,行为完全保持不变

3.Number.isInteger():

Number.isInteger()用来判断一个数值是否为整数

4.Number.EPSILON:

它表示 1 与大于 1 的最小浮点数之间的差;

是 JavaScript 能够表示的最小精度

5.安全整数和 Number.isSafeInteger():

(1)JavaScript 能够准确表示的整数范围在-253到253之间(不含两个端点),超过这个范围,无法精确表示这个值

(2)ES6 引入了Number.MAX_SAFE_INTEGER和Number.MIN_SAFE_INTEGER这两个常量,用来表示这个范围的上下限

(3)Number.isSafeInteger()则是用来判断一个整数是否落在这个范围之内;

6.Math 对象的扩展:

(1)Math.trunc():用于去除一个数的小数部分,返回整数部分;

(2)Math.sign():用来判断一个数到底是正数、负数、还是零。对于非数值,会先将其转换为数值。

它会返回五种值:

			参数为正数,返回+1;

			参数为负数,返回-1;

			参数为 0,返回0;

			参数为-0,返回-0;

			其他值,返回NaN。

(3)Math.cbrt():用于计算一个数的立方根

(4)Math.clz32():返回一个数的 32 位无符号整数形式有多少个前导 0;

(5)Math.imul():返回两个数以 32 位带符号整数形式相乘的结果,返回的也是一个 32 位的带符号整数。

(6)Math.fround():返回一个数的32位单精度浮点数形式

(7)Math.hypot():返回所有参数的平方和的平方根

(8)Math.expm1():Math.expm1(x)返回 ex - 1,即Math.exp(x) - 1

(9)Math.log1p():Math.log1p(x)方法返回1 + x的自然对数,即Math.log(1 + x)。如果x小于-1,返回NaN。

(10)Math.log10():Math.log10(x)返回以 10 为底的x的对数。如果x小于 0,则返回 NaN;

(11)Math.log2():返回以 2 为底的x的对数。如果x小于 0,则返回 NaN;

(12)ES6 新增了 6 个双曲函数方法:

			Math.sinh(x) 返回x的双曲正弦(hyperbolic sine)

			Math.cosh(x) 返回x的双曲余弦(hyperbolic cosine)

			Math.tanh(x) 返回x的双曲正切(hyperbolic tangent)

			Math.asinh(x) 返回x的反双曲正弦(inverse hyperbolic sine)

			Math.acosh(x) 返回x的反双曲余弦(inverse hyperbolic cosine)

			Math.atanh(x) 返回x的反双曲正切(inverse hyperbolic tangent)			

7.指数运算符:

指数运算符(**)

九.函数的扩展:

1.函数参数的默认值:

ES6 允许为函数的参数设置默认值,即直接写在参数定义的后面;

2.可与解构赋值默认值结合使用:

3.参数默认值的位置:

通常情况下,定义了默认值的参数,应该是函数的尾参数

4.函数的 length 属性:

指定了默认值以后,函数的length属性,将返回没有指定默认值的参数个数

5.作用域:

一旦设置了参数的默认值,函数进行声明初始化时,参数会形成一个单独的作用域(context)。

等到初始化结束,这个作用域就会消失

6.rest参数:

(1)ES6 引入 rest 参数(形式为…变量名),用于获取函数的多余参数,这样就不需要使用arguments对象了。

rest 参数搭配的变量是一个数组,该变量将多余的参数放入数组中。

例子:

		function add(...values) {
				 let sum = 0;
			for (var val of values) {
					  sum += val;
						 }
			 return sum;
			}

			add(2, 5, 3) // 10 

(2)与arguments的区别:

arguments对象不是数组,而是一个类似数组的对象。所以为了使用数组的方法,必须使用Array.prototype.slice.call先将其转为数组

rest 参数,它就是一个真正的数组,数组特有的方法都可以使用

(3)rest 参数之后不能再有其他参数(即只能是最后一个参数),否则会报错

(4)函数的length属性,不包括 rest 参数

7.name属性:

函数的name属性,返回该函数的函数名

8.箭头函数:

(1)ES6 允许使用“箭头”(=>)定义函数

		var f = v => v;
		// 等同于
		var f = function (v) {
		  return v;
			};

(2)箭头函数的一个用处是简化回调函数:

		// 正常函数写法
		[1,2,3].map(function (x) {
		  return x * x;
		});

		// 箭头函数写法
		[1,2,3].map(x => x * x);

(3) rest 参数与箭头函数结合的例子:

		const numbers = (...nums) => nums;
		numbers(1, 2, 3, 4, 5)

(4)箭头函数有几个使用注意点:

函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象;

不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误;

不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替;

不可以使用yield命令,因此箭头函数不能用作 Generator 函数

this对象的指向是可变的,但是在箭头函数中,它是固定的;this总是指向函数定义生效时所在的对象

由于箭头函数没有自己的this,所以当然也就不能用call()、apply()、bind()这些方法去改变this的指向

(5)不应该使用箭头函数场合:

第一个场合是定义函数的方法,且该方法内部包括this;

第二个场合是需要动态this的时候,也不应使用箭头函数

9.双冒号运算符:

(1)函数绑定运算符是并排的两个冒号(::),双冒号左边是一个对象,右边是一个函数。该运算符会自动将左边的对象,作为上下文环境(即this对象),绑定到右边的函数上面。
用来取代call、apply、bind调用

		foo::bar(...arguments);
		// 等同于
		bar.apply(foo, arguments);

(2)如果双冒号左边为空,右边是一个对象的方法,则等于将该方法绑定在该对象上面

(3)如果双冒号运算符的运算结果,还是一个对象,就可以采用链式写法

10.尾调用优化:

(1)尾调用(Tail Call):指某个函数的最后一步是调用另一个函数

		function f(x){
			 return g(x);
			}

(2)尾调用优化:只保留内层函数的调用帧。如果所有函数都是尾调用,那么完全可以做到每次执行时,调用帧只有一项,这将大大节省内存

(3)注意:只有不再用到外层函数的内部变量,内层函数的调用帧才会取代外层函数的调用帧,否则就无法进行“尾调用优化”

11.尾递归:

(1)函数调用自身,称为递归。如果尾调用自身,就称为尾递归

(2)对于尾递归来说,由于只存在一个调用帧,所以永远不会发生“栈溢出”错误。

		function factorial(n, total) {
			 if (n === 1) return total;
			return factorial(n - 1, n * total);
			}
		factorial(5, 1) // 120        

(3)递归函数的改写:

a.在尾递归函数之外,再提供一个正常形式的函数。

		function tailFactorial(n, total) {
			 if (n === 1) return total;
			 return tailFactorial(n - 1, n * total);
			}
		function factorial(n) {
			 return tailFactorial(n, 1);
				}
		factorial(5) // 120   

b.采用 ES6 的函数默认值:

		 function factorial(n, total = 1) {
			 if (n === 1) return total;
			 return factorial(n - 1, n * total);
			}
		 factorial(5) // 120        

(4)尾调用优化发生时,函数的调用栈会改写,因此上面两个变量就会失真。

严格模式禁用这两个变量,所以尾调用模式仅在严格模式下生效

(5)在非严格模式下也可以实现尾递归:采用“循环”换掉“递归”

12.函数参数的尾逗号:

ES2017 允许函数的最后一个参数有尾逗号

十.数组的扩展:

1.扩展运算符:

(1)三个点(…),它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列;

		console.log(1, ...[2, 3, 4], 5)
		// 1 2 3 4 5

		[...document.querySelectorAll('div')]
		// [<div>, <div>, <div>]

(2)该运算符主要用于函数调用

(3)该运算符主要用于函数调用

			function f(x, y, z) {
			// ...
				}
			var args = [0, 1, 2];
			f.apply(null, args);
			// ES5 的写法

			// ES6的写法
			function f(x, y, z) {
			 // ...
			}
			let args = [0, 1, 2];
			f(...args);  

(4)扩展运算符的应用:

a.复制数组:

			const a1 = [1, 2];
			const a2 = [...a1];

b.合并数组:

			const arr1 = ['a', 'b'];
			const arr2 = ['c'];
			const arr3 = ['d', 'e'];
			[...arr1, ...arr2, ...arr3]
			// [ 'a', 'b', 'c', 'd', 'e' ]

c.与解构赋值结合:

扩展运算符可以与解构赋值结合起来,用于生成数组

			const [first, ...rest] = [1, 2, 3, 4, 5];
			first // 1
			rest  // [2, 3, 4, 5]

d.字符串:

扩展运算符还可以将字符串转为真正的数组

			[...'hello']
			// [ "h", "e", "l", "l", "o" ]

			[...'hello'].reverse().join('')

e.实现了Iterator接口:

任何 Iterator 接口的对象,都可以用扩展运算符转为真正的数组

			let nodeList = document.querySelectorAll('div');
			let array = [...nodeList];

f.Map 和 Set 结构,Generator 函数:

扩展运算符内部调用的是数据结构的 Iterator 接口,因此只要具有 Iterator 接口的对象,都可以使用扩展运算符

2.Array.from():

(1)Array.from方法用于将两类对象转为真正的数组:类似数组的对象(array-like object)和可遍历(iterable)的对象。

包括 ES6 新增的数据结构 Set 和 Map

		let arrayLike = {
				 '0': 'a',
				 '1': 'b',
			         '2': 'c',
				 length: 3
				};
		let arr2 = Array.from(arrayLike); // ['a', 'b', 'c']

(2)只要是部署了 Iterator 接口的数据结构,Array.from都能将其转为数组。

		Array.from('hello')
		// ['h', 'e', 'l', 'l', 'o']

(3)任何有length属性的对象,都可以通过Array.from方法转为数组,而此时扩展运算符就无法转换

(4)Array.from还可以接受第二个参数,作用类似于数组的map方法,用来对每个元素进行处理,将处理后的值放入返回的数组。

		Array.from([1, 2, 3], (x) => x * x)
		// [1, 4, 9]

(5)Array.from()的另一个应用是,将字符串转为数组,然后返回字符串的长度

3.Array.of():

(1)Array.of方法用于将一组值,转换为数组

(2)Array.of基本上可以用来替代Array()或new Array(),并且不存在由于参数不同而导致的重载。它的行为非常统一

(3)Array.of总是返回参数值组成的数组。如果没有参数,就返回一个空数组

4.数组实例的 copyWithin():

(1)在当前数组内部,将指定位置的成员复制到其他位置(会覆盖原有成员),然后返回当前数组。

也就是说,使用这个方法,会修改当前数组。

(2)Array.prototype.copyWithin(target, start = 0, end = this.length)

它接受三个参数。

target(必需):从该位置开始替换数据。如果为负值,表示倒数。

start(可选):从该位置开始读取数据,默认为 0。如果为负值,表示倒数。

end(可选):到该位置前停止读取数据,默认等于数组长度。如果为负值,表示倒数。

这三个参数都应该是数值,如果不是,会自动转为数值

		[1, 2, 3, 4, 5].copyWithin(0, 3)
		// [4, 5, 3, 4, 5]

5.数组实例的 find() 和 findIndex():

(1)数组实例的find方法,用于找出第一个符合条件的数组成员。它的参数是一个回调函数,所有数组成员依次执行该回调函数,直到找出第一个返回值为true的成员,然后返回该成员。

如果没有符合条件的成员,则返回undefined

		[1, 5, 10, 15].find(function(value, index, arr) {
		return value > 9;
			}) // 10

find方法的回调函数可以接受三个参数,依次为当前的值、当前的位置和原数组。

(2)findIndex方法的用法与find方法非常类似,返回第一个符合条件的数组成员的位置,如果所有成员都不符合条件,则返回-1。

		[1, 5, 10, 15].findIndex(function(value, index, arr) {
		return value > 9;
			}) // 2

(3)这两个方法都可以接受第二个参数,用来绑定回调函数的this对象;

(4)这两个方法都可以发现NaN,弥补了数组的indexOf方法的不足:

indexOf方法无法识别数组的NaN成员,但是findIndex方法可以借助Object.is方法做到

		[NaN].indexOf(NaN)
		// -1

		[NaN].findIndex(y => Object.is(NaN, y))
		// 0

6.数组实例的fill():

(1)fill方法使用给定值,填充一个数组;

fill方法用于空数组的初始化非常方便。数组中已有的元素,会被全部抹去。

		['a', 'b', 'c'].fill(7)
		// [7, 7, 7]

(2)fill方法还可以接受第二个和第三个参数,用于指定填充的起始位置和结束位置

		['a', 'b', 'c'].fill(7, 1, 2)
		// ['a', 7, 'c']

7.数组实例的 entries(),keys() 和 values():

(1)entries(),keys()和values()用于遍历数组。它们都返回一个遍历器对象,可以用for…of循环进行遍历;

唯一的区别是keys()是对键名的遍历、values()是对键值的遍历,entries()是对键值对的遍历。

(2)示例代码:

		for (let index of ['a', 'b'].keys()) {
		console.log(index);
		}
		// 0
		// 1

		for (let elem of ['a', 'b'].values()) {
		 console.log(elem);
			}
		// 'a'
		// 'b'

		for (let [index, elem] of ['a', 'b'].entries()) {
		 console.log(index, elem);
			}
		// 0 "a"

8.数组实例的 includes():

(1)该方法返回一个布尔值,表示某个数组是否包含给定的值

(2)该方法的第二个参数表示搜索的起始位置,默认为0。如果第二个参数为负数,则表示倒数的位置,如果这时它大于数组长度(比如第二个参数为-4,但数组长度为3),则会重置为从0开始。

(3)Map 和 Set 数据结构有一个has方法,需要注意与includes区分。

Map 结构的has方法,是用来查找键名的,比如Map.prototype.has(key)、WeakMap.prototype.has(key)、Reflect.has(target, propertyKey)。

Set 结构的has方法,是用来查找值的,比如Set.prototype.has(value)、WeakSet.prototype.has(value)。

9.数组实例的 flat(),flatMap():

(1)Array.prototype.flat()用于将嵌套的数组“拉平”,变成一维的数组。该方法返回一个新数组,对原数据没有影响

		[1, 2, [3, 4]].flat()
		// [1, 2, 3, 4]

(2)flat()默认只会“拉平”一层,如果想要“拉平”多层的嵌套数组,可以将flat()方法的参数写成一个整数,表示想要拉平的层数,默认为1。

		[1, 2, [3, [4, 5]]].flat()
		// [1, 2, 3, [4, 5]]

		[1, 2, [3, [4, 5]]].flat(2)
		// [1, 2, 3, 4, 5]

(3)如果不管有多少层嵌套,都要转成一维数组,可以用Infinity关键字作为参数。

		[1, [2, [3]]].flat(Infinity)
		// [1, 2, 3]

(4)flatMap()方法对原数组的每个成员执行一个函数(相当于执行Array.prototype.map()),然后对返回值组成的数组执行flat()方法。该方法返回一个新数组,不改变原数组

		// 相当于 [[2, 4], [3, 6], [4, 8]].flat()
		[2, 3, 4].flatMap((x) => [x, x * 2])
		// [2, 4, 3, 6, 4, 8]

10.数组的空位:

ES6 则是明确将空位转为undefined

十一.对象的扩展:

1.属性的简洁表示法:

直接写入变量和函数,作为对象的属性和方法

	const baz = {foo: foo};

2.属性名表达式:

(1)ES6 允许字面量定义对象时,用方法二(表达式)作为对象的属性名,即把表达式放在方括号内

(2)代码示例:

		let propKey = 'foo';	
		let obj = {
			[propKey]: true,
			['a' + 'bc']: 123
			};

3.方法的name属性:

(1)函数的name属性,返回函数名。对象方法也是函数,因此也有name属性

(2)如果对象的方法使用了取值函数(getter)和存值函数(setter),则name属性不是在该方法上面,而是该方法的属性的描述对象的get和set属性上面,返回值是方法名前加上get和set

(3)有两种特殊情况:

bind方法创造的函数,name属性返回bound加上原函数的名字;

Function构造函数创造的函数,name属性返回anonymous

4.属性的可枚举性和遍历:

(1)可枚举性:

对象的每个属性都有一个描述对象(Descriptor),用来控制该属性的行为。Object.getOwnPropertyDescriptor方法可以获取该属性的描述对象

		let obj = { foo: 123 };
		Object.getOwnPropertyDescriptor(obj, 'foo')
		//  {
		//    value: 123,
		//    writable: true,
		//    enumerable: true,
		//    configurable: true
		//  }

描述对象的enumerable属性,称为”可枚举性“,如果该属性为false,就表示某些操作会忽略当前属性

(2)有四个操作会忽略enumerable为false的属性:

for…in循环:只遍历对象自身的和继承的可枚举的属性。

Object.keys():返回对象自身的所有可枚举的属性的键名。

JSON.stringify():只串行化对象自身的可枚举的属性。

Object.assign(): 忽略enumerable为false的属性,只拷贝对象自身的可枚举的属性。

(3)属性的遍历:

a. for…in

for…in循环遍历对象自身的和继承的可枚举属性(不含 Symbol 属性)。

b. Object.keys(obj)

Object.keys返回一个数组,包括对象自身的(不含继承的)所有可枚举属性(不含 Symbol 属性)的键名。

c. Object.getOwnPropertyNames(obj)
Object.getOwnPropertyNames返回一个数组,包含对象自身的所有属性(不含 Symbol 属性,但是包括不可枚举属性)的键名。

d. Object.getOwnPropertySymbols(obj)

Object.getOwnPropertySymbols返回一个数组,包含对象自身的所有 Symbol 属性的键名。

e. Reflect.ownKeys(obj)

Reflect.ownKeys返回一个数组,包含对象自身的所有键名,不管键名是 Symbol 或字符串,也不管是否可枚举。

以上的 5 种方法遍历对象的键名,都遵守同样的属性遍历的次序规则:

首先遍历所有数值键,按照数值升序排列。

其次遍历所有字符串键,按照加入时间升序排列。

最后遍历所有 Symbol 键,按照加入时间升序排列。

5.super关键字:

(1)ES6 又新增了另一个类似this的关键字super,指向当前对象的原型对象

(2)super关键字表示原型对象时,只能用在对象的方法之中,用在其他地方都会报错

(3)JavaScript 引擎内部,super.foo等同于Object.getPrototypeOf(this).foo(属性)或Object.getPrototypeOf(this).foo.call(this)(方法)

6.扩展运算符:

对象的扩展运算符(…)用于取出参数对象的所有可遍历属性,拷贝到当前对象之中

十二.对象的新增方法:

1.Object.is():

(1)ES5 比较两个值是否相等,只有两个运算符:相等运算符()和 严格相等运算符(=)。

它们都有缺点,前者会自动转换数据类型,后者的NaN不等于自身,以及+0等于-0

(2)Object.is就是部署这个算法的新方法。它用来比较两个值是否严格相等,与严格比较运算符(===)的行为基本一致;

不同之处只有两个:一是+0不等于-0,二是NaN等于自身

		Object.is('foo', 'foo')  // true
		
		Object.is({}, {})     // false
		
		+0 === -0   //true
		NaN === NaN // false

		Object.is(+0, -0) // false
		Object.is(NaN, NaN) // true

2.Object.assign():

(1)Object.assign方法用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target)

Object.assign方法的第一个参数是目标对象,后面的参数都是源对象

		const target = { a: 1 };

		const source1 = { b: 2 };
		const source2 = { c: 3 };

		Object.assign(target, source1, source2);
		target // {a:1, b:2, c:3}

(2)如果目标对象与源对象有同名属性,或多个源对象有同名属性,则后面的属性会覆盖前面的属性

(3)浅拷贝:

Object.assign方法实行的是浅拷贝,而不是深拷贝。

也就是说,如果源对象某个属性的值是对象,那么目标对象拷贝得到的是这个对象的引用

(4)同名属性的替换:

对于这种嵌套的对象,一旦遇到同名属性,Object.assign的处理方法是替换,而不是添加。

		const target = { a: { b: 'c', d: 'e' } }
		const source = { a: { b: 'hello' } }
		Object.assign(target, source)
		// { a: { b: 'hello' } }

(5)数组的处理:

Object.assign可以用来处理数组,但是会把数组视为对象

		Object.assign([1, 2, 3], [4, 5])
		// [4, 5, 3]

(6)取值函数的处理:

Object.assign只能进行值的复制,如果要复制的值是一个取值函数,那么将求值后再复制

(7)常见用途:

a.为对象添加属性

		class Point {
			 constructor(x, y) {
					Object.assign(this, {x, y});
				}
			}

b.为对象添加方法

c.克隆对象

d.合并多个对象

e.为属性添加默认值

3.Object.getOwnPropertyDescriptors():

(1)ES5 的Object.getOwnPropertyDescriptor()方法会返回某个对象属性的描述对象(descriptor)。

ES2017 引入了Object.getOwnPropertyDescriptors()方法,返回指定对象所有自身属性(非继承属性)的描述对象

(2)该方法的引入目的,主要是为了解决Object.assign()无法正确拷贝get属性和set属性的问题

(3)Object.getOwnPropertyDescriptors()方法配合Object.defineProperties()方法,就可以实现正确拷贝

(4)配合Object.create()方法,将对象属性克隆到一个新对象。这属于浅拷贝

(5)Object.getOwnPropertyDescriptors()方法可以实现一个对象继承另一个对象。以前,继承另一个对象

4.__proto__属性,Object.setPrototypeOf(),Object.getPrototypeOf():

(1)JavaScript 语言的对象继承是通过原型链实现的。ES6 提供了更多原型对象的操作方法

(2)__proto__属性(前后各两个下划线),用来读取或设置当前对象的prototype对象;

(3)Object.setPrototypeOf方法的作用与__proto__相同,用来设置一个对象的prototype对象,返回参数对象本身。它是 ES6 正式推荐的设置原型对象的方法。

(4)Object.getPrototypeOf()与Object.setPrototypeOf方法配套,用于读取一个对象的原型对象

5.Object.keys(),Object.values(),Object.entries():

(1)Object.keys方法,返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键名

		var obj = { foo: 'bar', baz: 42 };
		Object.keys(obj)
		// ["foo", "baz"]

(2)Object.values方法返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键值

		const obj = { foo: 'bar', baz: 42 };
		Object.values(obj)
		// ["bar", 42]

(3)Object.entries()方法返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键值对数组

		const obj = { foo: 'bar', baz: 42 };
		Object.entries(obj)
		// [ ["foo", "bar"], ["baz", 42] ]

6.Object.fromEntries():

(1)Object.fromEntries()方法是Object.entries()的逆操作,用于将一个键值对数组转为对象

		Object.fromEntries([
				['foo', 'bar'],
				 ['baz', 42]
				])
		// { foo: "bar", baz: 42 }

(2)该方法的主要目的,是将键值对的数据结构还原为对象,因此特别适合将 Map 结构转为对象

(3)该方法的一个用处是配合URLSearchParams对象,将查询字符串转为对象

		Object.fromEntries(new URLSearchParams('foo=bar&baz=qux'))
		// { foo: "bar", baz: "qux" }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值