飞道的博客

ES6新增特性总结

356人阅读  评论(0)

目录

let和const命令

模板字符串

扩展运算符

解构赋值

对象解构

数组解构

扩展的函数

带参数默认值的函数

剩余参数表示不定参

箭头函数

扩展的对象

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

新增Object.is()/Object.assign()/Object.keys/Object.value/Object.entries/Object.getOwnPropertyDescriptors方法

扩展的数值

Symbol

Map和Set

Set

Map

迭代器和生成器/Proxy对象

Promise

类class

模块化实现


let和const命令

es6新增了两个声明变量的关键字:let和const

  • var声明存在变量提升问题,let和const不存在变量提升

  
  1. console. log(a); // undefined 变量提升了 实际代码变为 var a; console.log(a)
  2. console. log(b); // 报错 Uncaught ReferenceError: Cannot access 'b' before initialization
  3. console. log(c); // 报错 Uncaught ReferenceError: Cannot access 'c' before initialization
  4. var a = 120;
  5. let b = 'false';
  6. const c = 100;
  • let和const只能在块作用域里访问

  
  1. // 使用var
  2. var arr = [];
  3. for ( var i = 0; i < 10; i++) {
  4. arr[i] = function( ) {
  5. return i
  6. };
  7. }
  8. console. log(arr[ 5]()); // 10
  9. // 使用let或const
  10. const arr = [];
  11. for ( let i = 0; i < 10; i++) {
  12. arr[i] = function( ) {
  13. return i
  14. };
  15. }
  16. console. log(arr[ 5]()); // 5

  
  1. if( true) {
  2. var a = 120;
  3. let b = 'false';
  4. const c = 100;
  5. }
  6. console. log(a); // 120
  7. console. log(b); // 报错:Uncaught ReferenceError: b is not defined
  8. console. log(c); // 报错:Uncaught ReferenceError: c is not defined
  •  同一作用域下let和const不能声明同名变量,而var可以

  
  1. var a = 120;
  2. let b = 'false';
  3. const c = 100;
  4. var a = 130;
  5. let b = 'true'; // Uncaught SyntaxError: Identifier 'b' has already been declared
  6. const c = 200; // Uncaught SyntaxError: Identifier 'c' has already been declared
  7. console. log(a); // 130
  • const只能定义常量,而且不能修改 

  
  1. const b = false;
  2. b = 12;
  3. console. log(b); // Uncaught TypeError: Assignment to constant variable
  • 不会污染全局变量

  
  1. console. log( window. RegExp); // ƒ RegExp() { [native code] }
  2. let RegExp = 10;
  3. console. log( RegExp); // 10
  4. console. log( window. RegExp); // ƒ RegExp() { [native code] }

模板字符串

使用反引号``来创建模板字符串,插入变量时使用${变量名};


  
  1. let name = '小明';
  2. let age = '12';
  3. console. log(name + '今年'+ age + '岁啦!'); // 小明今年12岁啦!
  4. console. log( `${name}今年${age}岁啦!`); // 小明今年12岁啦!

使用该方法可避免了大量+ 和 ' '的配合使用;

扩展运算符

扩展运算符是指...,用于扩展可迭代类型或数组;

  • 使用扩展运算符合并数组

  
  1. const arry1 = [ '小明', '小红'];
  2. const arry2 = [...arry1, '小李', '小强'];
  3. console. log(arry2); // ['小明', '小红', '小李', '小强']
  • 使用扩展运算符拷贝数组

  
  1. const arry1 = [ '小明', '小红'];
  2. const arry2 = [...arry1];
  3. console. log(arry2); // ['小明', '小红']
  4. arry2[ 2] = '小强';
  5. console. log(arry1, arry2); // ['小明', '小红'] ['小明', '小红', '小强']

使用扩展运算符拷贝的结果不是简单拷贝的引用地址,因此改变不会受影响; 

  • 带对象的扩展运算符

  
  1. const obj1 = { name: '小明', age: 12};
  2. const obj2 = { hobby: '踢足球'};
  3. const obj3 = {...obj1, ...obj2}
  4. console. log(obj3); // {name: '小明', age: 12, hobby: '踢足球'}

对象扩展运算符,层数是1的话为深拷贝。二级以上的层级则不是深拷贝;


  
  1. const obj1 = { name: '小明', age: 12};
  2. const obj2 = {
  3. project: {
  4. English: 20,
  5. huaxue: 30,
  6. }
  7. };
  8. const obj3 = {...obj1, ...obj2}
  9. console. log(obj3); // {name: '小明', age: 12, hobby: '踢足球'}
  10. obj3. project. huaxue = 90
  11. console. log(obj2); // project: {English: 20, huaxue: 90} obj2的huaxue属性也被改变了
  12. console. log(obj3); // {name: '小明', age: 12, project: {English: 20, huaxue: 90}

解构赋值

解构赋值是对赋值运算符的一种扩展,它是一种针对数组或对象进行模式匹配,然后对其中的变量进行赋值,可使代码简洁易读;

对象解构


  
  1. let student = {
  2. name: '小凡',
  3. age: 18
  4. }
  5. let {name, age} = student
  6. console. log(name, age); // 小凡 18

 对象解构时左侧变量名要与对象中key值对应,用{}


  
  1. let student = {
  2. name: '小凡',
  3. age: 18
  4. }
  5. let {name, age, sex} = student
  6. console. log(name, age, sex); // 小凡 18 undefined

也可以进行非完全解构;


  
  1. let student = {
  2. name: '小凡',
  3. age: 18,
  4. sex: '男'
  5. }
  6. let {name} = student
  7. console. log(name); // 小凡

可与扩展运算符搭配使用;


  
  1. let student = {
  2. name: '小凡',
  3. age: 18,
  4. sex: '男'
  5. }
  6. let {name, ...attribute} = student
  7. console. log(name, attribute); // 小凡 {age: 18, sex: '男'}

所有的变量都放到扩展变量中;


  
  1. let student = {
  2. name: '小凡',
  3. age: 18,
  4. sex: '男',
  5. school: {
  6. name: '一中',
  7. location: '村里'
  8. }
  9. }
  10. let {name, school, ...attribute} = student
  11. console. log(name,school, attribute); // 小凡 {name: '一中', location: '村里'} {age: 18, sex: '男'}

数组解构

数组解构使用[ ],左侧变量名任意;


  
  1. let student = [ '小凡', 18, '男'];
  2. [name, age, sex] = student
  3. console. log(name, age, sex); // 小凡 18 男

其它与对象解构一样; 

扩展的函数

带参数默认值的函数

ES6添加了参数默认值,所以不用在函数内部编写容错代码;


  
  1. // es5的写法
  2. function add( a,b) {
  3. a = a || 10; // 若无定义a,则默认为10
  4. b = b || 20; // 若无定义b,则默认为20
  5. return a+b
  6. }
  7. console. log( add()); // 30
  8. // es6的写法
  9. function add( a = 10, b = 20) {
  10. return a + b
  11. }
  12. console. log( add()); // 30

剩余参数表示不定参

不定参功能和es5的arguments一样;


  
  1. // es5写法
  2. function pick( obj) {
  3. let result = {};
  4. for( let i = 1; i < arguments. length; i++) {
  5. result[ arguments[i]] = obj[ arguments[i]]
  6. }
  7. return result;
  8. }
  9. let book = {
  10. name: '活着',
  11. author: '余华',
  12. pages: 400
  13. }
  14. let bookData = pick(book, 'name', 'author', 'pages');
  15. console. log(bookData); // {"name": "活着", "author": "余华","pages": 400}

  
  1. function pick( obj, ...keys) {
  2. let result = {};
  3. for( let i = 0; i < keys. length; i++) {
  4. result[keys[i]] = obj[keys[i]];
  5. }
  6. return result;
  7. }
  8. let book = {
  9. name: '活着',
  10. author: '余华',
  11. pages: 400
  12. }
  13. let bookData = pick(book, 'name', 'author', 'pages');
  14. console. log(bookData); // {"name": "活着", "author": "余华","pages": 400}

箭头函数

在箭头函数中没有arguments,也没有prototype属性,箭头函数不是一个对象,所以不能用new关键字来实例化箭头函数;

它使用=>来定义,function() {} 等价于 () => {}

箭头函数的this指向用于指向其父级对象的this

扩展的对象

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


  
  1. // es6写法
  2. const name = "活着";
  3. const author = "余华";
  4. const book = {
  5. name,
  6. author,
  7. sayName( ) {
  8. console. log( '这是一本很好看的书籍');
  9. }
  10. }
  11. book. sayName() // 这是一本很好看的书

 上面简写方式name,只能在属性和属性值相同的情况下简写~


  
  1. // es5写法
  2. const name = "活着";
  3. const author = "余华";
  4. const book = {
  5. name: name,
  6. author: author,
  7. sayName: function( ) {
  8. console. log( '这是一本很好看的书籍');
  9. }
  10. }
  11. book. sayName() // 这是一本很好看的书

新增Object.is()/Object.assign()/Object.keys/Object.value/Object.entries/Object.getOwnPropertyDescriptors方法

  • Object.is()

Object.is()方法用来判断两个值是否严格相等,返回布尔值;与===区别在于对于NaN和+0、-0的处理结果不一样;


  
  1. object1 = {
  2. name: '小明',
  3. age: 12
  4. }
  5. object2 = {
  6. name: '小明',
  7. age: 12
  8. }
  9. console. log(object2. name === object2. name); // true
  10. console. log( Object. is(object1. name, object2. name)); // true
  11. console. log( null === null); // true
  12. console. log( Object. is( null, null)); // true
  13. console. log( NaN === NaN); // false
  14. console. log( Object. is( NaN, NaN)); // true
  15. console. log( Object. is(+ 0,- 0)); // false
  16. console. log(+ 0 === - 0); // true

  
  1. // 补充几个烦人的比较
  2. console. log( null instanceof Object); // false,但null也是个对象
  3. console. log( null === undefined); // false
  4. console. log( null == undefined); // true
  5. console. log( NaN == NaN); // false
  6. console. log( undefined == undefined); // true
  7. var x = new Boolean( false);
  8. console. log(x); // Boolean {false}
  9. var y = Boolean( 0);
  10. console. log(y); // false
  • Object.assign()

Object.assign()方法用于合并多个对象中的所有可枚举属性,并返回目标对象;是个浅拷贝方法~


  
  1. object1 = {
  2. name: '小明',
  3. age: 12
  4. }
  5. object2 = {
  6. sex: 'male'
  7. }
  8. console. log( Object. assign(object1, object2)); // {name: '小明', age: 12, sex: 'male'}
  • Object.keys()

Object.keys()用于返回对象中的所有属性,返回一个数组


  
  1. object1 = {
  2. name: '小明',
  3. age: 12
  4. }
  5. console. log( Object. keys(object1)); // ['name', 'age']
  • Object.values()

Object.values()用于返回对象中所有属性值,返回一个数组


  
  1. object1 = {
  2. name: '小明',
  3. age: 12
  4. }
  5. console. log( Object. values(object1)); // [['小明', 12]
  •  Object.entries()

Object.entries()用于返回多个数组,每个数组都由key-value组成


  
  1. object1 = {
  2. name: '小明',
  3. age: 12,
  4. classes: [ '语文', '数学', '英语']
  5. }
  6. console. log( Object. entries(object1)); // [ "name","小明"],["age",12],["classes",["语文","数学","英语"] ] ]
  • Object.getOwnPropertyDescriptors

该方法返回指定对象所有自身属性的描述对象;


  
  1. <script>
  2. const obj = {
  3. name: 'xiaoming'
  4. }
  5. console. log( Object. getOwnPropertyDescriptors(obj));
  6. </script>

通过字面量创建出来的对象,默认可枚举属性enumerable为true,可配置属性configurable(是否可删除等属性)为true,writable属性为true;

补充:通过Object.creat()方法创建一个对象,使用现有的对象来作为新创建对象的原型prototype。

扩展的数值

  • Number.EPSILON表示最小精度,一般用于判断小数是否相等
  • Number.isFinite 用于检测一个数值是否为有限数值
  • Number.isNaN 用于检测一个数值是否为NaN
  • Number.parseInt 用于将字符串整数部分取出 Number.parseFloat将字符串中浮点数取出
  • Number.isInteger 判断一个数值是否为整数
  • Math.trunc 用于将数字的小数部分抹掉
  • Math.sign 用于判断一个数到底为正数/负数还是0,正数返回1,负数返回-1,0返回0

  
  1. console. log( 0.1+ 0.2 === 0.3); // false
  2. // 但是可以写个函数 判断如果0.1+0.2 与0.3相差小于Number.EPSILON,则表明0.1+0.2 与0.3相等
  3. console. log( Number. isFinite( 100)); // true
  4. console. log( Number. isFinite( 100/ 0)); // false
  5. console. log( Number. isFinite( Infinity)); // false
  6. console. log( Number. isNaN( NaN)); // true
  7. console. log( Number. isNaN( 0)); // false
  8. console. log( Number. parseInt( '321flos3')); // 321
  9. console. log( Number. parseInt( '3.21flos3')); // 3
  10. console. log( Number. parseFloat( '3.21flos3')); // 3.21
  11. console. log( Number. parseFloat( '3.2.1flos3')); // 3.2
  12. console. log( Number. isInteger( 3.21)); // false
  13. console. log( Number. isInteger( '3')); // false
  14. console. log( Number. isInteger( 3)); // true
  15. console. log( Math. trunc( 3.45)); // 3
  16. console. log( Math. sign( 3.45)); // 1
  17. console. log( Math. sign(- 3.45)); // -1
  18. console. log( Math. sign( 0)); // 0

Symbol

新增一种基本数据类型symbol,表示独一无二的值。特点如下:

symbol的值是唯一的,用来解决命名冲突的问题;

Symbol值不能与其他数据进行运算;

通过Symbol()或Symbol.for()创建Symbol值;

Symbol定义的对象属性不能使用for...in循环遍历,但是可以使用Reflect.ownKeys来获取对象的所有键名;


  
  1. <script>
  2. let s1 = Symbol();
  3. console. log(s1, typeof s1); // Symbol() 'symbol'
  4. // 带有标识的创建
  5. let name = Symbol( '小明');
  6. console. log(name, typeof name); // Symbol(小明) 'symbol'
  7. // 使用Symbol.for创建
  8. let project = Symbol. for( '英语');
  9. console. log(project, typeof project); // Symbol(英语) 'symbol'
  10. </script>

 一般在创建对象的某个属性唯一时,使用Symbol


  
  1. <script>
  2. const project = Symbol()
  3. const number = Symbol()
  4. let school = {
  5. name: '一中',
  6. location: '这里',
  7. [project]: function( ) {
  8. console. log( '我喜欢英语');
  9. },
  10. [number]: 200
  11. }
  12. school[project](); // 我喜欢英语
  13. console. log(school[number]); // 200
  14. </script>

Symbol是JavaScript中的第六种基本数据类型,与undefined、null、Number、String、Boolean并列~

Map和Set

Set

ES6提供了新的数据结构Set(集合),但成员的值都是唯一的,集合实现了iterator接口,所以可以使用扩展运算符for...of...进行遍历

Set对象的属性和方法主要有:

        size: 返回集合的元素个数(相当于数组中的length属性);

        add:增加一个新元素,返回当前集合;

        delete:删除元素,返回布尔值;

        has:检测集合中是否包含某个元素,返回布尔值;


  
  1. let newSet = new Set([ 1, 3]);
  2. console. log(newSet); // Set(2) {1, 3}
  3. console. log(newSet. add([ 4, 5])) // Set(3) {1, 3, [4, 5]}
  4. console. log(newSet. delete( 3)) // true
  5. console. log(newSet. delete( 4)) // false
  6. console. log(newSet. has( 1)) // true
  7. console. log(newSet. size); // 2
  • 利用Set对象唯一性的特点,可实现数组的去重~

  
  1. let newSet = [... new Set([ 1, 3, 3, 5, 4, 4, 6, 7])];
  2. console. log(newSet); //  [1, 3, 5, 4, 6, 7]
  • 实现数组的交集~

  
  1. let arr1 = [ 1, 2, 3, 4, 5];
  2. let arr2 = [ 1, 4, 6, 7];
  3. let arr3 = [... new Set(arr1)]. filter( item => new Set(arr2). has(item))
  4. console. log(arr3); //  [1, 4]
  • 实现数组的差集~

  
  1. let arr1 = [ 1, 2, 3, 4, 5];
  2. let arr2 = [ 1, 4, 6, 7];
  3. let arr3 = [... new Set(arr1)]. filter( item => !( new Set(arr2). has(item)))
  4. console. log(arr3); //  [2,3,5]
  • 实现数组的并集~

  
  1. let arr1 = [ 1, 2, 3, 4, 5];
  2. let arr2 = [ 1, 4, 6, 7];
  3. let arr3 = [... new Set([...arr1, ...arr2])]
  4. console. log(arr3); //  [1, 2, 3, 4, 5, 6, 7]

Map

ES6提供了Map数据结构,是键值对的集合,键的定义不再像对象一样仅局限于字符串,而是包含各种类型的值(包括对象)。同时,因为Map实现了iterator接口,所以可以使用for...of进行遍历;

Map的属性和方法主要有:

        size: 返回Map的元素个数

        set:增加一个新元素,返回当前Map;

        get:返回键值对象的键值;

        has:检测当前Map中是否包含某个元素,返回布尔值;

        clear:清空集合,返回undefined


  
  1. let newMap = new Map();
  2. newMap. set( 'name', '小明');
  3. newMap. set( 'classes', [ '语文', '数学', '英语']);
  4. console. log(newMap); //  Map(2) {'name' => '小明', 'classes' => Array(3)}
  5. console. log(newMap. size); // 2
  6. console. log(newMap. has( 'name')); // true
  7. for ( const item of newMap) {
  8. console. log(item); // (2) ['name', '小明'] (2) ['classes', Array(3)]
  9. }
  10. console. log(newMap. delete( 'classes')); // true
  11. console. log(newMap. size); // 1
  12. console. log(newMap. get( 'name')); // 小明

迭代器和生成器/Proxy对象

回头详细讲

Promise

2023年了,你还在为Promise头疼?_迷糊的小小淘的博客-CSDN博客

类class

类的本质依然是一个函数

JavaScript高级教程(面向对象编程)_迷糊的小小淘的博客-CSDN博客

模块化实现

模块化是为了将复杂的程序按照一定的规则拆分成单个文件,并最终组合在一起,可以降低代码复杂度,避免命名冲突,提高复用性;

ES6中的模块化功能主要由两个命令构成:export和import,export命令用于暴露模块的对外接口,import命令用于引入其它模块提供的功能;

导出模块有三种不同的暴露方式

  • 分别暴露方式

如果导出模块采用分别暴露的方式,如:


  
  1. // test.js文件
  2. // 通用暴露
  3. export let name = '小明';
  4. export function exam( ) {
  5. console. log( '明天又要考试~');
  6. }
  • 统一暴露

如果导出模块采用统一暴露的方式,如:


  
  1. // test.js文件
  2. // 统一暴露
  3. let name = '小明';
  4. function exam( ) {
  5. console. log( '明天又要考试~');
  6. };
  7. export {name, exam};

注意此处{name, exam}并不是表示解构赋值,只是表示一种写法~

则导入模块时要使用:


  
  1. <script type= "module">
  2. // 通用暴露
  3. import * as m1 from './test.js'
  4. // 给*起了别名m1
  5. console. log(m1); // m1中包含name属性和exam方法
  6. </script>
  • 默认暴露

如果导出模块采用默认暴露的方式,该种方式一般应用于一个文件中只有一个暴露,如:


  
  1. // test.js文件
  2. // 默认暴露
  3. export default {
  4. name : '小明',
  5. exam: function( ) {
  6. console. log( '明天又要考试~');
  7. }
  8. };

根据暴露模块的方法不同,引入模块也有不同的导入方式

  • 通用的引入方式

上述三种暴露方式都可使用该种方法:


  
  1. <script>
  2. // 通用暴露
  3. import * as m1 from 'm1.js'
  4. // 给*起了别名m1
  5. console. log(m1); // 对于前两种暴露方式m1中包含name属性和exam方法,
  6. // 对于默认暴露方式,m1中包含default 取m1.default.name才可
  7. </script>
  • 解构赋值方式

对于前两种暴露方式,可直接通过下述代码拿到name或exam


  
  1. <script type= "module">
  2. // 通用暴露
  3. import { name,exam } from './test.js'
  4. // 或
  5. import { name as xingming,exam as kaoshi } from './test.js'
  6. // 给name/exam起了别名
  7. </script>

但是对于默认暴露来说,要采用如下:


  
  1. <script type= "module">
  2. import { default as m1 } from './test.js'
  3. // 一般要给default取个别名,通过别名.name或别名.exam拿到
  4. </script>
  • 针对于默认暴露的简便导入方式

  
  1. <script type= "module">
  2. import m3 from './test.js'
  3. // 通过m3.name或m3.exam拿到
  4. </script>

以上三种暴露方式可同时在另一个文件中引入,不会产生覆盖

此处,简单补充下另一个重要的模块化规范方式CommonJs:

CommonJs方式模块化的代码既可在服务器端,如nodejs中运行,又可以在浏览器端运行(需借助工具Browserify编译),他仅有两种暴露方式:

  • exports.xxx = value, value是要暴露的数据,xxx是命名
  • module.exports = value, value是要暴露的数据

原理是在服务端exports===module.exports={ },它俩都指向同一个空对象;

这两种方式不能混用,如果混用,则以module.exports暴露的为主,value是啥,module.exports暴露的就是啥;

显示并没有englishName这一属性,

引入方式也仅有两种,

  • 引入第三方模块,require(xxx),xxx是模块名
  • 引入自定义模块,require(xxx), xxx是模块文件路径


转载:https://blog.csdn.net/ks795820/article/details/127750467
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场