ECMAScript 6+ 新特性 ( 一 )

2.1.let关键字

为了解决之前版本中 var 关键字存在存在着越域, 重复声明等多种问题, 在 ES6 以后推出 let 这个新的关键字用来定义变量

//声明变量
let a;
let b,c,d;
let e = 100;
let f = 123, g = 'hello javascript', h = [];

let 关键字用来声明变量,使用 let 声明的变量有几个特点:

  1. 不允许重复声明

    var s = "王小二";
    var s = "李小三";
    
    let name = '王小二';
    let name = '李小三';  // Uncaught SyntaxError: Identifier 'name' has already been declared
    
  2. 块儿级作用域

    if else while for 语句 都可以定义代码块

    // for(var i = 0;i < 5; i++){
    //     console.log(i)
    // }
    // console.log( "i:", i ) // i 越域
    
    
    {
        let girl = '赵静子';
    }
    console.log(girl); // Uncaught ReferenceError: girl is not defined
    
  3. 不存在变量提升

    // console.log(s) // undefined
    // var s = "abc"
    // console.log(s) // abc
    
    console.log(song); //Uncaught ReferenceError: Cannot access 'song' before initialization
    let song = '最炫民族风';
    console.log(song)  // 不会再执行到这行
    

2.2. const 关键字

定义常量, 不能修改

//声明常量
const GOODS = '书包';

const 关键字用来声明常量,const 声明有以下特点

  1. 声明必须赋初始值

    const A;  // Uncaught SyntaxError: Missing initializer in const declaration
    
  2. 标识符一般为大写(潜规则, 不是必须的)

  3. 不允许重复声明

    const GOODS = '书包';
    const GOODS = '钢笔'; // Uncaught SyntaxError: Identifier 'GOODS' has already been declared
    
  4. 块儿级作用域

    {
        const NAME = '王小二';
    }
    console.log(NAME); // Uncaught ReferenceError: NAME is not defined
    
  5. 值不允许修改

    const BOOK = '三体';
    BOOK = '西游记'; // Uncaught TypeError: Assignment to constant variable.
    

    特别要注意 : 对于数组和对象的元素修改, 不算做对常量的修改, 不会报错

    const TEAM = ['王小二','李小三'];
    TEAM.push('赵小四');
    
    const STU = {
        name: '王小二',
        age: 18
    }
    STU.name = '赵小四';
    

应用场景:声明对象类型使用const,非对象类型声明选择 let

2.3.变量的解构赋值

ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构赋值。

2.3.1.数组的解构赋值

const F4 = ['王小二','李小三','赵小四','张不开'];
// let wang = F4[0];
// let li = F4[1];
// let zhao = F4[2];
// let zhang = F4[3];

let [ wang, li, zhao, zhang ] = F4;
console.log(wang);
console.log(li);
console.log(zhao);
console.log(zhang);
2.3.1.1.可嵌套
let [a,[b,c]] = [1,[2,3]];
console.log(a,b,c);
2.3.1.2.解构默认值
let [h=2]=[3]; //[] [undefined]
console.info(h);     // 3
let [i = 3, j = i] = [];
console.info(i,j);   // 3   3
let [k = 3, l = k] = [1];
console.info(k, l);   // 1   1
let [m = 3, n = m] = [1, 2];
console.log(m, n);   // 1   2
2.3.1.3.剩余运算符
let [p, ...q] = [1,2,3];
console.log(p,q);  // 1   [  2,  3]
2.3.1.4.字符串
let [s1, s2, s3, s4, s5] = "hello";
console.log( s1, s2, s3, s4, s5 );  //  h   e   l   l   o

2.3.2.对象的解构赋值

const STU = {
    name: '王小二',
    age: 18,
    sayHello: function(){
        console.log("Hello, 我是" + this.name);
    }
};

// let name = STU.name
// let age = STU.age;
// let sayHello = STU.sayHello;

// let { name : name , age : age ,  sayHello : sayHello } = STU;
let { name, age, sayHello } = STU;
console.log(name);
console.log(age);
// console.log(sayHello);
sayHello();

// let { sayHello } = STU;
// sayHello();

// let { name : abc  } = STU;
// console.log(abc)
2.3.2.1.解构默认值
let { h=2}={ h : 3 }; //[] [undefined]
console.info(h);     // 3
let { i = 3, j = i } ={ };
console.info(i,j);   // 3   3
let { k = 3, l = k } = { k : 1 };
console.info(k, l);   // 1   1
let { m = 3, n = m } = { m : 1, n : 2 };
console.info(m, n);   // 1   2

2.3.3.复杂解构

先定义对象

let wang = {
    hobby: ['运动','美食','音乐'],
    study:[
        { name: 'java', info:'啥都能干'},
        { name: 'HTML', info: '挺好学的'},
        { name: 'javascript', info: '也啥都能干'}
    ]
}
2.3.3.1.解构方式1
let {  hobby, study } = wang;
console.log( hobby);
console.log( hobby[0] );
console.log( hobby[1] );
console.log( hobby[2] );
console.log( study );
console.log( study[0].name );
console.log( study[0].info );
2.3.3.2.解构方式2

one , two, three, java, html, js 才是解构出来的变量

let {  hobby: [ one, two, three ] , study : [ java, html, js ] } = wang;
// console.log( hobby); // 使用报错 :  Uncaught ReferenceError: hobby is not defined
console.log( one );
console.log( two );
console.log( three );

console.log(java.name);
console.log(html.info);
console.log( js )
console.log( js.name )

注意:频繁使用对象方法、数组元素,就可以使用解构赋值形式

2.4.字符串优化

2.4.1.模板字符串

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

  1. 字符串中可以出现换行符
  2. 可以使用 ${xxx} 形式输出变量
2.4.1.1.定义字符串
let s = `我也是一个字
        符
        串
        哦!`;
        console.log(s, typeof s);

let str = `<ul>
          	<li>王小二</li>
            <li>李小三</li>
            <li>赵小四</li>
           </ul>`;
console.log(str, typeof str);
2.4.1.2.输出变量
let zhao = '赵静子';
let out = `${zhao}是个大美女!!`;
console.log(out);

注意:当遇到字符串与变量拼接的情况使用模板字符串

2.4.1.3.插入函数结果
function fn() {
    return "函数返回结果!";
}
let str = `调用函数得到结果: ${fn()}`;
console.log(str);

2.4.2.新增方法

  1. startsWith():判断字符串是否以特定的字符开头。

  2. endsWith():判断字符串是否以特定的字符结尾。

  3. includes():判断字符串是否包含特定的字符。

  4. repeat():重复生成指定次数的字符串。

    let str = "hello.vue";
    console.log(str.startsWith("hello"));  //true
    console.log(str.endsWith(".vue"));  //true
    console.log(str.includes("e"));  //true
    console.log(str.includes("hello"));   //true
    let ss = str.repeat(3);    //hello.vuehello.vuehello.vue
    console.log(ss)
    
  5. ( ES 10 ) trimStart()trimEnd()

    let str = '   hello world   ';
    
    console.log(str);            // "   hello world   "
    console.log(str.trim() );    // "hello world"
    console.log(str.trimStart()); // "hello world   "
    console.log(str.trimEnd());   // "   hello world"
    

2.5. 数值扩展

2.5.1.Number新增方法

2.5.1.1.Number.EPSILON

Number.EPSILON 是 JavaScript 表示的最小精度
EPSILON 属性的值接近于 2.2204460492503130808472633361816E-16

function equal(a, b){
    if(Math.abs(a-b) < Number.EPSILON){
        return true;
    }else{
        return false;
    }
}
console.log(0.1 + 0.2 === 0.3);
console.log(equal(0.1 + 0.2, 0.3))
2.5.1.2.二进制和八进制

ES6 提供了二进制和八进制数值的新的写法,分别用前缀 0b 和 0o 表示。

let b = 0b1010;  // 二进制
let o = 0o777;   // 八进制
let d = 100;     // 十进制
let x = 0xff;    // 十六进制
console.log(x);
2.5.1.3.Number.isFinite()

Number.isFinite() 用来检查一个数值是否为有限的

console.log(Number.isFinite(100));       // true
console.log(Number.isFinite(100/0));     // false
console.log(Number.isFinite(Infinity));  // false
2.5.1.4.Number.parseInt() 与 Number.parseFloat()

ES6 将全局方法 parseInt 和 parseFloat,移植到 Number 对象上面,使用不变。

console.log(Number.parseInt('5211314love'));   // 5211314
console.log(Number.parseFloat('3.1415926神奇'));  // 3.1415926
2.5.1.5.Number.isInteger

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

console.log(Number.isInteger(5));  // true
console.log(Number.isInteger(2.5));  // false

2.5.2.Math新增方法

2.5.2.1.Math.sign

判断一个数到底为正数 负数 还是零

console.log(Math.sign(100));  // 1
console.log(Math.sign(0));    // 0
console.log(Math.sign(-20000));  // -1
2.5.2.2.Math.trunc

用于去除一个数的小数部分,返回整数部分。

console.log(Math.trunc(3.5)); // 3
2.5.2.3.( ES 7 )幂运算新写法

在 ES7 中引入指数运算符「**」,用来实现幂运算,功能与 Math.pow 结果相同

 console.log(2 ** 10);// 
 console.log(Math.pow(2, 10));

2.5.3.( ES 11 ) BigInt

更大的数据范围, 只能是整数

//大整形
let n = 521n;
console.log(n, typeof(n)); // 521n 'bigint'

//函数
// let n = 123;
console.log(BigInt(n)); // 123n
console.log(BigInt(1.2)); // Uncaught RangeError: The number 1.2 cannot be converted to a BigInt because it is not an integer

//大数值运算
let max = Number.MAX_SAFE_INTEGER; // 9007199254740991
console.log(max); // 9007199254740991
console.log(max + 1); // 9007199254740992
console.log(max + 2); // 9007199254740993

console.log(BigInt(max)) // 9007199254740991n
console.log(BigInt(max) + BigInt(1)) // 9007199254740992n
console.log(BigInt(max) + BigInt(2)) // 9007199254740993n

2.6. ( ES 9 ) 正则表达式

2.6.1.( ES 9 ) 命名捕获组

同时 匹配多个信息, 之前的处理方式

//声明一个字符串
let str = '<a href="http://www.baidu.com">百度</a>';

//提取 url 与 『标签文本』
const reg = /<a href="(.*)">(.*)<\/a>/;

//执行
const result = reg.exec(str);

console.log(result); 
// 输出:
// [
// '<a href="http://www.baidu.com">百度</a>',
// 'http://www.baidu.com', 
// '百度',
// index: 0, 
// input: '<a href="http://www.baidu.com">百度</a>', 
// groups: undefined
// ]
console.log(result[1]); // http://www.baidu.com
console.log(result[2]); // 百度

ES 9 允许命名捕获组使用符号 ?<name> ,这样获取捕获结果可读性更强

let str = '<a href="http://www.baidu.com">百度</a>';
//分组命名
const reg = /<a href="(?<url>.*)">(?<text>.*)<\/a>/;

const result = reg.exec(str);
console.log(result)
// 输出:
// [
// '<a href="http://www.baidu.com">百度</a>',
// 'http://www.baidu.com',
// '百度',
// index: 0,
// input: '<a href="http://www.baidu.com">百度</a>',
// groups:{ text:"百度", url:"http://www.baidu.com" },
// length : 3
// ]
console.log(result.groups.url); // http://www.baidu.com
console.log(result.groups.text); // 百度

2.6.2.( ES 9 )反向断言

ES9 支持反向断言,通过对匹配结果前面的内容进行判断,对匹配进行筛选。

//声明字符串
// let str = '电话号码13123456789年龄23岁';
let str = '电话号码13987654321年龄45岁';
//正向断言
const reg1 = /\d+(?=岁)/;
const result1 = reg1.exec(str);
console.log(result1);

//反向断言
const reg2 = /(?<=年龄)\d+/;
const result2 = reg2.exec(str);
console.log(result2);

2.6.3.( ES 9 )dotAll 模式

正则表达式中点.匹配除回车外的任何单字符,标记s改变这种行为,

允许行终止符出现

//dot  .  元字符  除换行符以外的任意单个字符
let str = `
        <ul>
            <li>
                <a>热辣滚烫</a>
                <p>上映日期: 2024-02-10</p>
            </li>
            <li>
                <a>你好, 李焕英</a>
                <p>上映日期: 2021-02-12</p>
            </li>
        </ul>`;
//声明正则
// const reg = /<li>\s+<a>(.*?)<\/a>\s+<p>(.*?)<\/p>/;
const reg = /<li>.*?<a>(.*?)<\/a>.*?<p>(.*?)<\/p>/gs;
//执行匹配
// const result = reg.exec(str);
let result;
let data = [];
while(result = reg.exec(str)){
    data.push({title: result[1], time: result[2]});
}
//输出结果
console.log(data);

2.6.4.( ES 11 ) String.prototype.matchAll

得到 正则批量匹配结果

let str = `<ul>
            <li>
                <a>肖生克的救赎</a>
                <p>上映日期: 1994-09-10</p>
            </li>
            <li>
                <a>阿甘正传</a>
                <p>上映日期: 1994-07-06</p>
            </li>
        </ul>`;

//声明正则
const reg = /<li>.*?<a>(.*?)<\/a>.*?<p>(.*?)<\/p>/sg

//调用方法
const result = str.matchAll(reg);

// for(let v of result){
//     console.log(v);
// }

const arr = [...result];

console.log(arr);

2.7.数组Array 扩展

在 ES6(ECMAScript 2015)中,JavaScript 对 Array 对象进行了多个重要扩展和改进,以增强数组操作的便利性和性能。

2.7.1.主要的 新特性

2.7.1.1.扩展运算符 (...)

可用于解构赋值、复制数组以及将数组转换为参数序列。

let arr1 = [1, 2, 3];
let arr2 = [...arr1]; // 复制数组:[1, 2, 3]
let combined = [0, ...arr1, 4]; // 合并数组:[0, 1, 2, 3, 4]
function logArgs(...args) {
  console.log(args);
}
logArgs(...arr1); // 输出:[1, 2, 3]
2.7.1.2.Array.from()

将类数组对象或可迭代对象转换为真正的数组。

let arrayLike = { 0: 'a', 1: 'b', length: 2 };
let arr = Array.from(arrayLike); // 转换为:['a', 'b']
2.7.1.3.Array.of()

根据传入的参数创建一个新数组。

let arr = Array.of(1, 2, 3); // 创建:[1, 2, 3]
2.7.1.4.( ES 7 )Array.prototype.includes()

检查数组是否包含某个指定的值。

let arr = [1, 2, 3];
console.log(arr.includes(2)); // 输出:true
2.7.1.5…参数与展开语法在数组方法中的应用

例如,在 Math.max()Math.min() 中可以使用剩余参数来替代 apply() 方法。

let maxNumber = Math.max(...arr); // 获取数组中的最大值
2.7.1.6.fill()

填充数组的方法,用给定值填充数组的一部分或全部。

let filledArr = new Array(5).fill('hello');
console.log(filledArr); // 输出:['hello', 'hello', 'hello', 'hello', 'hello']
2.7.1.7.( ES 10 ) flat() / flatMap()

将嵌套数组拉平为一维数组。

let arrs = [ [1,2,3], [4,5,6,7], [8,9,10] ];
console.log(arrs.length) //3

// 将嵌套数组拉平为一维数组。
let arrs1 = arrs.flat()
console.log(arrs1.length) // 10
console.log(arrs1) // 10

// 先对数组中的每个元素执行映射函数,然后将结果拉平为一维数组。
let arrs2 = arrs.flatMap( item => Math.max(...item) )
console.log(arrs2) 
2.7.1.8.copyWithin()

在数组内部的一个位置复制数组的一部分到另一个位置。

let copyArr = [1, 2, 3, 4, 5];
copyArr.copyWithin(0, 3); // 把从下标3开始的元素复制到下标0开始的位置:[4, 5, 3, 4, 5]
2.7.1.9.包含includes()
// 参数1:包含的指定值
console.log( [1, 2, 3].includes(1)  );  // true
// 参数2:可选,搜索的起始索引,默认为0
console.log( [ 1, 2, 3 ].includes(1, 2) ); // false
// NaN 的包含判断
console.log( [ 1, NaN, 3].includes(NaN) ); //true

2.7.2.结合箭头函数

2.7.2.1.map()

map() 方法对数组中的每个元素执行给定的回调函数,并将回调函数的返回值组成一个新数组返回。

它可以用于对原始数组中的每个元素进行处理,并返回一个处理后的新数组。

let numbers = [1, 2, 3, 4, 5];
let squared = numbers.map(n => n * n); // 映射:[1, 4, 9, 16, 25]
2.7.2.2.reduce()

reduce() 为数组中的每一个元素依次执行回调函数,不包括数组中被删除或从未被赋值的元素,

arr.reduce(callback,[initialValue])

callback () 的参数

1、previousValue (上一次调用回调返回的值,或者是提供的初始值(initialValue))
2、currentValue (数组中当前被处理的元素)
3、index (当前元素在数组中的索引)
4、array (调用 reduce 的数组)

let arr = [2, 40, -10, 6]
let result = arr.reduce( (a,b)=>{
    console.log("上一次处理后:" + a);
    console.log("当前正在处理:" + b);
    return a + b;
},100 );
console.log(result)

//   运行结果

// 上一次处理后:100
// 当前正在处理:2
// 上一次处理后:102
// 当前正在处理:40
// 上一次处理后:142
// 当前正在处理:-10
// 上一次处理后:132
// 当前正在处理:6
// 138
2.7.2.3.filter()

方法用于过滤数组中的元素,返回满足给定条件的新数组。

它可以通过指定一个回调函数来筛选出需要的元素,该方法返回一个新数组。

// 筛选出数组中偶数
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9];
let evenNumbers = numbers.filter(number => number % 2 === 0);
console.log(evenNumbers); // 输出:[2, 4, 6, 8]

// 从用户对象列表中筛选出年龄大于等于18岁的用户
let users = [
    { id: 1, name: '王小二', age: 20 },
    { id: 2, name: '李小三', age: 17 },
    { id: 3, name: '赵小四', age: 22 },
    { id: 4, name: '张不开', age: 16 }
];
let adults = users.filter(user => user.age >= 18);
console.log(adults);
// 输出:
// [
//   { id: 1, name: '王小二', age: 20 },
//   { id: 3, name: '赵小四', age: 22 }
// ]


// 筛选非空字符串
let strings = ['apple', '', '张不开', null, undefined , '123'];
let nonEmptyStrings = strings.filter(str => str && str.trim().length > 0);
console.log(nonEmptyStrings);
// 输出:['apple', '张不开', '123']
2.7.2.4.find()

find(): 返回数组中满足提供的测试函数的第一个元素的值,否则返回 undefined。

let arr = [ 1, 2, 3, 4, 5, 6]
let found = arr.find(item => item > 3); // 返回第一个大于3的元素
console.log( found )

let foundIndex = arr.findIndex(item => item > 3); // 返回第一个大于3的元素
console.log( foundIndex )
2.7.2.5.迭代器方法

entries(), keys(), values() 提供了迭代器接口。

let arr = [ 1, 2, 3, 4, 5, 6]
for (let [index, value] of arr.entries()) {
  console.log(index, value);
}

2.8. 扩展Set

ES6 提供了新的数据结构 Set(集合)。

它类似于数组,但成员的值都是唯一的,

集合实现了 iterator 接口,所以可以使用『扩展运算符』和『for…of…』进行遍历,

2.8.1.集合的常用属性和方法

  1. size 返回集合的元素个数

  2. add 增加一个新元素,返回当前集合

  3. delete 删除元素,返回 boolean 值

  4. has 检测集合中是否包含某个元素,返回 boolean 值

  5. clear 清空集合,返回 undefined

//声明一个 空 set
let s = new Set();
let s2 = new Set(['王小二','李小三','赵小四','张小三','李小三']);
console.log(s2);
// //元素个数
console.log(s2.size);
// //添加新的元素
s2.add('刘小六');
s2.add('王小二')
console.log(s2);
// //删除元素
s2.delete('张小三');
console.log(s2);
// //检测
console.log(s2.has('赵小四'));
// //清空
// s2.clear();
// console.log(s2);
//
for(let v of s2){
    console.log(v);
}

2.8.2.应用

let arr = [1,2,3,4,5,4,3,2,1];
//1. 数组去重
// let result = [...new Set(arr)];
// console.log(result);

//2. 交集 has()
let arr2 = [4,5,6,5,6];
// let result = [...new Set(arr)].filter(item => {
//     let s2 = new Set(arr2);// 4 5 6
//     if(s2.has(item)){
//         return true;
//     }else{
//         return false;
//     }
// });
// // let result = [...new Set(arr)].filter(item => new Set(arr2).has(item));
// console.log(result);

//3. 并集
// let union = [...new Set([...arr, ...arr2])];
// console.log(union);

//4. 差集
// let diff = [...new Set(arr)].filter(item => !(new Set(arr2).has(item)));
// console.log(diff);

2.9.对象Object优化

2.9.1.对象新的方法

2.9.1.1.( ES 8 ) 结构分析
  1. Object.values()方法返回一个给定对象的所有可枚举属性值的数组

  2. Object.entries()方法返回一个给定对象自身可遍历属性 [key,value] 的数组

    //声明对象
    const STU = {
        name : "王小二",
        study : ['java','html','js']
    };
    
    //获取对象所有的键
    console.log(Object.keys(STU)); // ['name', 'study']
    //获取对象所有的值
    console.log(Object.values(STU)); // ['王小二', ['java', 'html', 'js']]
    //entries
    console.log(Object.entries(STU)); // [['name', '王小二'], ['study', ['java', 'html', 'js']]]
    
    //创建 Map
    const m = new Map(Object.entries(STU));
    console.log(m.get('study'));
    
2.9.1.2.判断完全相等
// Object.is 判断两个值是否完全相等 
console.log(Object.is(120, 120));// true
console.log(Object.is(120, '120'));// false
console.log(Object.is(NaN, NaN));// true
console.log(NaN === NaN);// false
console.log(NaN == NaN);// false
2.9.1.3.合并
const STU1 = {
    name : '王小二',
    age : 18,
    birth : '2001-01-01',
    info1: '一个好学生'
};
const STU2 = {
    name : '李小三',
    age : 22,
    sex : '女',
    info2: '也是一个好学生'
}

Object.assign(STU1, STU2) // 将STU1和STU2合并到 STU1

console.log( STU1 );
// 结果是合并结果
// {
//     age : 22,
//     birth : "2001-01-01",
//     info1 : "一个好学生",
//     info2 : "也是一个好学生",
//     name : "李小三",
//     sex : "女"
// }

console.log( STU2 ); // 不变化
2.9.1.4.拷贝
// 1、拷贝对象
let s1 = { name: "王小二", age: 15 }
let s2 = { ...s1 }
console.log( s2 ) //{ name:"王小二", age:15 }

// 2、合并对象
let age1 = { age: 15 }
let name1 = { name: "王小二" }
let s3 = { name : "李小三" }
s3 = { ...age1, ...name1 }
console.log( s3 ) // {age: 15, name: '王小二'}
2.9.1.5.( ES 9 )Object.fromEntries

从 二维数组 / Map 创建对象

//二维数组
const result1 = Object.fromEntries([
    ['name','王小二'],
    ['study', 'Java,html,js']
]);
console.log(result1) //{name: "王小二", study: "Java,html,js"}

//Map
const m = new Map();
m.set('name','李小三');
m.set('hobby', ['电影','美食','旅游'] )
const result2 = Object.fromEntries(m);
console.log(result2); //{name: "李小三", hobby: Array(3)}

也可以在创建时 指定这些属性

const obj = Object.create(null, {
    name: {
        //设置值
        value: '李小三',
        //属性特性
        writable: true,
        configurable: true,
        enumerable: true
    }
});
console.log(obj)

2.9.2.简化对象写法

ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法。这样的书写更加简洁。

let name = '王小二';
let sayHello = function(){
    console.log('大家好!!');
}

// const STU = {
//     name : name,
//     sayHello : sayHello,
//     study: function(){
//         console.log("我们一起学 js");
//     }
// }

const STU = {
    name,
    sayHello,
    study(){
        console.log("我们一起学 js");
    }
}

console.log(STU);
STU.sayHello()

几种对象函数的写法:

let person3 = {
    name: "王小二",
    // 以前:
    eat: function (food) {
        console.log(this.name + "在吃" + food);
    },
    //箭头函数this不能使用,对象.属性
    eat2: food => console.log(person3.name + "在吃" + food),
    // 匿名
    eat3(food) {
        console.log(this.name + "在吃" + food);
    }
}

person3.eat("香蕉");

person3.eat2("苹果")

person3.eat3("橘子");

2.9.3.( ES 9 )Rest/Spread 属性

Rest 参数与 spread 扩展运算符在 ES6 中已经引入,不过 ES6 中只针对于数组,在 ES9 中为对象提供了像数组一样的 rest 参数和扩展运算符

//rest 参数
function connect({host, port, ...user}){
    console.log(host);  // 127.0.0.1
    console.log(port);  // 3306
    console.log(user);  // { username: 'root', password: 'root', type: 'master' }
}

connect({
    host: '127.0.0.1',
    port: 3306,
    username: 'root',
    password: 'root',
    type: 'master'
});
//对象合并
const teamOne = {
    a : '王小二',
    b : '李小三'
}

const teamTwo = {
    c : '赵小四',
    d : '张不开',
    e : '刘小六'
}

const team = {
    ...teamOne,
    ...teamTwo
}

console.log(team) //{a: '王小二', b: '李小三', c: '赵小四', d: '张不开', e: '刘小六'}

2.10. 扩展Map

ES6 提供了 Map 数据结构。

它类似于对象,也是键值对的集合。但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。

Map会按照插入的顺序来迭代元素,而对象中的键值对没有固定的顺序。

Map 也实现了iterator 接口,所以可以使用『扩展运算符』和『for…of…』进行遍历。

2.10.1.创建和初始化

// 创建一个空 Map
let map1 = new Map();

// 使用数组形式初始化 Map
let map2 = new Map([
  ['name', '王小二'],
  [123, 'abc'],
  [{ key: 'objectKey' }, 'Value for object key']
]);
console.log(map2);
// 使用可迭代对象(如另一个 Map 或 Set)初始化
let obj = { a: 1, b: 2 };
let entries = Object.entries(obj);
let map3 = new Map(entries);

console.log(map3); // Map(2) { 'a' => 1, 'b' => 2 }

2.10.2.Map 的属性和方法

  1. size 返回 Map 的元素个数

  2. set 增加一个新元素,返回当前 Map

  3. get 返回键名对象的键值对数组

  4. has 检测 Map 中是否包含某个元素,返回 boolean 值

  5. clear 清空集合,返回 undefined

//声明 Map
let m = new Map();

//添加元素
m.set('name','王小二');
m.set('sayHello', function(){
    console.log("大家好!!");
});
let key = {
    study : 'JAVA'
};
m.set(key, ['spring','mybatis','springmvc']);

//size
console.log(m.size);

//删除
m.delete('name');
//获取
console.log(m.get('name'));
console.log(m.get('sayHello'));
console.log(m.get(key));

//清空
// m.clear();

//遍历
for(let v of m){
    console.log(v);
}

console.log(m);

2.11.函数优化

2.11.1.箭头函数

ES6 允许使用「箭头」(=>)定义函数。

let fn1 = function(){
    console.log('function')
}
fn1()

let fn2 = ()=>{
    console.log('=>')
};
fn2()
2.11.1.1.写法
// 声明一个函数
let fn = (a,b) => {
    return a + b;
}
// 调用函数
let result = fn(1, 2);
console.log(result);


// 如果形参只有一个,则小括号可以省略
let fn3 = num => {
 return num * 10;
};

// 函数体如果只有一条语句,则花括号可以省略
let fn4 = ()=>console.log('hello')

// 函数的返回值为该条语句的执行结果
let fn5 = score => score * 20;
let result = fn5(10);
console.log(result)


// 当箭头函数要返回对象的时候,为了区分于代码块,要用 () 将对象包裹起来
let f = (id,name) => ({id:id,name:name});
console.log( f(1,'王小二') )  // {id: 1, name: '张三'}

箭头函数+解构

const person = {
    name: "王小二",
    age: 21,
    language: ['java', 'js', 'css']
}

function hello(person){
    console.log("hello," + person.name)
}

//箭头函数+解构
var hello2 = ({name}) => console.log("hello," + name);
hello2(person);
2.11.1.2.this ***

this 指向声明时所在作用域中 this的值

// 设置 window 对象的 name 属性
window.name = '王小二';
let name = '赵静子';
console.log( this )
function getName(){
    console.log(this.name);
}

let getName2 = () => {
    console.log(this.name);
}

//直接调用
getName();  // 王小二
getName2();  // 王小二

注意:this 是静态的 , 箭头函数不会更改 this 指向,用来指定回调函数会非常合适

箭头函数适合与 this 无关的回调. 定时器, 数组的方法回调
箭头函数不适合与 this 有关的回调. 事件回调, 对象的方法

const STU = {
    name: "李小三"
}

//call 方法调用
getName.call(STU); // 李小三
getName2.call(STU); // 王小二
2.11.1.3.不能作为构造函数

箭头函数不能作为构造函数实例化

let Sss = function (name, age) {
    this.name = name;
    this.age = age;
}
let wang = new Sss('王小二',12); 
console.log(wang);

let Stu = (name, age) => {
    this.name = name;
    this.age = age;
}
let li = new Stu('李小三',13); //Uncaught TypeError: Stu is not a constructor
console.log(li);
2.11.1.4.不能使用 arguments
let fn6 = function () {
    console.log(arguments); 
}
fn6(1,2,3);

let fn7 = () => {
    console.log(arguments);
}
fn7(1,2,3); //Uncaught ReferenceError: arguments is not defined

2.11.2. rest 参数(不定参数)

ES6 引入 rest 参数,用于获取函数的实参,用来代替 arguments

// ES5 获取实参的方式
// function getName1(){
//     console.log(arguments);
// }
// getName1('王小二','李小三','赵小四');

// rest 参数
// function getName2(...args){
//     console.log(args);// filter some every map
// }
// getName2('王小二','李小三','赵小四');
// getName2('王小二','李小三');


// rest 参数必须要放到参数最后
function fn(a,b,...args){
    console.log(a);
    console.log(b);
    console.log(args);
    console.log(args.length);
}
fn(1,2,3,4,5,6);

注意:rest 参数非常适合不定个数参数函数的场景

2.11.3. spread 扩展运算符

扩展运算符(spread)也是三个点(…)。

它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列,对数组进行解包。

// 声明一个数组 
const names = ['王小二','李小三','赵小四'];

// 声明一个函数
function getName(){
    console.log(arguments);
}

getName(...names); // getName('王小二','李小三','赵小四')

2.11.4.参数设置默认值

//在ES6以前,我们无法给一个函数参数设置默认值,只能采用变通写法:
function add(a, b) {
    // 判断b是否为空,为空就给默认值1
    b = b || 1;
    return a + b;
}
// 传一个参数
console.log(add(10));


//现在可以这么写:直接给参数写上默认值,没传就会自动使用默认值
function add2(a, b = 1) {
    return a + b;
}
console.log(add2(20));

2.11.5.( ES 11 )可选链操作符

使用参数之前 先判断参数有效性, 否则使用未传入的参数会报错

使用 ?. 运算符, 可以自动根据参数有效性进行判断, 如果参数无效, 不报错, 返回 undefined

// ?.
function main(config){
    // const dbHost = config && config.db && config.db.host;
    const dbHost = config?.db?.host;

    console.log(dbHost);
}

// main({
//     db: {
//         host:'192.168.1.100'
//     }
// })
main();
  • 10
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值