重学ES6之出来混迟早要还的(二)

5

本系列博客为ES6基础语法的使用及总结,如有错误,欢迎指正。
重学ES6之出来混迟早要还的(二)主要包括默认参数值模板字符串解构赋值剩余参数扩展运算符等

默认参数值(Default parameters)

函数默认参数允许在没有值或undefined被传入时使用默认形参。

1.语法

function [name]([param1[ = defaultValue1 ][, ..., paramN[ = defaultValueN ]]]) { 
    statements 
}

2.使用
2.1 在ES6之前可以通过逻辑运算符来给形参指定默认值

格式: 条件A || 条件B
如果条件A成立, 那么就返回条件A
如果条件A不成立, 无论条件B是否成立, 都会返回条件B
 function getInfo(a, b) {
    a = a || "今天要少吃,";
    b = b || "明天也要少吃";
    console.log(a, b);
}
getInfo(); //打印默认值 --> 今天要少吃,明天也要少吃
getInfo("mss"); //相当于传递了参数a,未传参数b --> mss 明天也要少吃
getInfo(undefined,"mss"); //表示参数a是未知的,此时采用默认值 --> 今天要少吃, mss
getInfo(123, "abc"); //参数ab都是由外界传递的 --> 123 "abc"

2.2 从ES6开始直接通过变量=指定默认值即可给形参指定默认值

function getInfo(a = "今天要少吃", b = ", 明天也要少吃") {
    console.log(a, b);
};
getInfo(); //今天要少吃, 明天也要少吃
getInfo(123, "abc"); //123 "abc"

注意:① 如果只传递了一个参数,则代表第一个参数使用我们传递进来的,其他参数还是使用默认值。
② 如果需要给某一个参数指定内容,其他参数需要传递undefined
③ 问:给其他参数传递null可以吗?答:别问,问就是不可以,问就是让你自己回去试

function multiply(a = 3, b = 5) {
   return a * b;
}
console.log(multiply(5, 2)); // ab均为传递进来的值,为10
console.log(multiply(5)); // a是5,b是默认值5,结果为25
console.log(multiply(undefined,10)); //a是默认值3,b是10,结果为30

function test(a = 1,b = 2, c = 3, d = 4) {
    return a + b + c + d;
}
console.log(test(undefined, undefined, 4, undefined)); //11

2.3 ES6中的默认值还可以从其它的函数中获取

function getSum(a = "少吃,", b = getDefault()) {
    console.log(a, b);
}
getSum();
// getSum(123, "abc");
function getDefault() {
    return "零食";
}

模板字符串(Template literals (Template strings))

模板字面量 是允许嵌入表达式的字符串字面量。你可以使用多行字符串和字符串插值功能。
1.语法
将需要插入的内容放在一对反引号``里面

模板字符串使用反引号来代替普通字符串中的用双引号和单引号。模板字符串可以包含特定语法(${expression})的占位符。占位符中的表达式和周围的文本会一起传递给一个默认函数,该函数负责将所有的部分连接起来,如果一个模板字符串由表达式开头,则该字符串被称为带标签的模板字符串,该表达式通常是一个函数,它会在模板字符串处理后被调用,在输出最终结果前,你都可以通过该函数来对模板字符串进行操作处理。在模版字符串内使用反引号(`)时,需要在它前面加转义符()。
`string text` //单行

`string text line 1
 string text line 2` //多行

`string text ${expression} string text` //包含特定语法(${expression})的占位符

tag `string text ${expression} string text` //标签模板字符串

2.用法
2.1 在ES6之前可以通过加号实现字符串拼接,但有时创建标签时不能体现出html标签的层级结构,比较繁琐而且容易出错。

let name = 'ghk';
let age = 22;
let output = name + ' is ' + age;
console.log(output);

2.2 采用模板字符串简化操作,引入的变量用${}包裹起来,${expression}中的expression的内容可以是一个变量、对象的属性、也可以是一个函数、一个需要创建的标签

let name = 'ghk';
let age = 22;
let output2 = `${name} is ${age}`;
console.log(output2);

let output3 = `${name} is ${age * 3}`;
console.log(output3);

2.3 模板字符串书写上可以自由换行,而不用添加“\”反斜杠转义空格。模板字符串创建标签时,有时会保留标签前后的空格,不需要空格时可以用.trim()方法去除空格(模板字符串也是个字符串)。

let str = `<div>
    <p><img src="./images.test.jpg" alt=""></p>
</div>`
let str = `
<div>
    <p><img src="./images.test.jpg" alt=""></p>
</div>.trim()`
console.log(str);

2.4 模板字符串里面可嵌套模板字符串

let person = {
    name: 'mss',
    lists:[
        {task: 'reading'},
        {task: 'sleeping'},
        {task: 'eating'}
    ]
};
let template = `
    <ul>
         ${person.lists.map(list =>`
             <li>
                 ${list.task}
             </li>
         `).join('')}
    </ul>
`;
document.body.innerHTML = template;

标签模板字符串(Tagged templates)

标签模板字符串允许通过一个默认的函数对其中的插值进行运算和连接。

更高级的形式的模板字符串是带标签的模板字符串。标签使您可以用函数解析模板字符串。标签函数的第一个参数包含一个字符串值的数组。其余的参数与表达式相关。最后,你的函数可以返回处理好的的字符串(或者它可以返回完全不同的东西)。用于该标签的函数的名称可以被命名为任何名字。

1.用法
1.1 标签函数第一个参数(strings)是一个数组,是由字符串的字面量组成的一个数组;后面的参数是不定参数(即变量),一个参数代表一个表达式的计算结果。

function myTag(strings, ...values) {
   console.log(strings);
   console.log(values);
}
let name = 'ghk';
let task = 'learning English';
let output = myTag`${name} has planned to ${task}`;

image.png!
1.2 当然了,不定参数是可以分开写的,但是如果有多个参数的时候建议还是使用 ...values 来代替

function myTag(strings,name,task) {
   console.log(strings);
   console.log(name);
   console.log(task);
}
let name = 'ghk';
let task = 'learning English';
let output = myTag`${name} has planned to ${task}`;

image.png
2.注意点
2.1 当模板字符串是以变量开头或者结尾的时候,返回的数组前或者后会多一个空字符串
image.png
如果此时在模板字符串前后加上一些内容,前后就不会返回空字符串了

function myTag(strings,...values) {
   console.log(strings);
   console.log(values);
}
let name = 'ghk';
let task = 'learning English';
let output = myTag`the boy ${name} has planned to ${task}.`;

image.png
2.2 在上述中使用了标签函数创建的模版字符串,但没有在标签函数中return最终值,所以output是undefined。要想有最终结果需要在标签函数中将字符串字面量数组和表达式运算结果拼接起来返回。

function myTag(strings,...values) {
   //console.log(strings);
   //console.log(values);
   let arr = [];
   for (let i=0;i<strings.length;i++){
       arr.push(strings[i]);
       arr.push(values[i]);
   }
   return arr.join("");
}
let name = 'ghk';
let task = 'learning English';
let output = myTag`the boy ${name} has planned to ${task}.`;
console.log(output); //the boy ghk has planned to learning English.

3.原始字符串
3.1 在标签函数的第一个参数中,存在一个特殊的属性raw ,我们可以通过它来访问模板字符串的原始字符串,而不经过特殊字符的替换。
3.2 使用String.raw() 方法创建原始字符串和使用默认模板函数和字符串连接创建是一样的。

let name = 'ghk';
let task = 'learning English';
let str=String.raw`the boy ${name} has planned to ${task}.`;
console.log(str); //the boy ghk has planned to learning English.

解构赋值(Destructuring assignment)

解构赋值语法是一种 Javascript 表达式。通过解构赋值, 可以将属性/值从对象/数组中取出, 赋值给其他变量。
一句话:解构赋值是ES6中新增的一种赋值方式

解构数组(Array destructuring)

1.用法
1.1 解构数组就是在表达式左边定义了要从原变量中取出什么变量。如果想要取出非连续变量的值,需要用加上逗号,表示留出跳过的元素的位置。

let arr= [1,2,3,4,5];
let [a,b] = arr;
// 相当于以下两句
// let a = arr[0];
// let b = arr[1];
console.log(a); //1
console.log(b); //2

let [one,,three,four] = arr;
console.log(one); //1
console.log(three); //3
console.log(four); //4

1.2 在数组的解构赋值中, 还可以使用ES6中新增的剩余参数来打包剩余的数据;如果使用了剩余参数, 则只能写在最后一个变量的前面。

let [a, ...b] = [1, 3, 5];
console.log("a = " + a); //1
console.log("b = " + b);  //[3,5]

//SyntaxError: Rest element must be last element
let [a, ...b,c] = [1, 3, 5];
console.log("a = " + a);
console.log("b = " + b);
console.log("c = " + c);

2.注意点
2.1 在数组的解构赋值中, 等号左边的格式必须和等号右边的格式一模一样, 才能完全解构。

let [a, b, [c, d]] = [1, 3, [2, 4]]; //完全解构
console.log("a = " + a); //1
console.log("b = " + b); //2
console.log("c = " + c); //3
console.log("d = " + d); //4

let [a, b, c] = [1, 3, [2, 4]]; //未完全解构
console.log("a = " + a); //1
console.log("b = " + b); //3
console.log("c = " + c); //2,4

2.2 在数组的解构赋值中, 等号左边的变量个数可以和右边的个数不一样,右边的个数也可以和左边的个数不一样; 如果右边的个数和左边的个数不一样, 可以给左边指定默认值。

let [a, b] = [1, 3, 5];
console.log("a = " + a); //1
console.log("b = " + b); //3

let [a, b, c] = [1];
console.log("a = " + a); //1
console.log("b = " + b); //undefined
console.log("c = " + c); //undefined

let [a, b = 666] = [1, 3, 5];
console.log("a = " + a); //1
console.log("b = " + b); //3

3.应用场景
可以用作变量交换,在一个解构表达式中可以交换两个变量的值。
没有解构赋值的情况下,交换两个变量需要一个临时变量

let a = 1;
let b = 3;
[a, b] = [b, a];
console.log(a); // 3
console.log(b); // 1

解构对象(Object destructuring)

数组解构使用[],对象解构使用{},其他用法差别不大。
1.用法(基本赋值)

let obj = {
   name: 'ghk',
   age: 22,
   gender: 'male'
};

let {name, age,gender} = obj;
// 相当于下面几句代码
// let name = obj.name;
// let age = obj.age;
// let gender = obj.gender;
// let {name, age, gender} = {name: 'ghk',age: 22,gender: 'male'};
console.log(name, age, gender);

2.无声明赋值
一个变量可以独立于其声明进行解构赋值。

在使用对象字面量无声明解构赋值时,必须在赋值语句周围加上圆括号 ( ) 。
( ) 表达式之前需要有一个分号,否则它可能会被当成上一行中的函数执行。
//正确用法
let a, b;
({a, b} = {a: 1, b: 2});

//错误写法,运行也会报错
let a, b;
{a, b} = {a: 1, b: 2};
console.log(a);
console.log(b);

注:{a, b} = {a: 1, b: 2} 不是有效的独立语法,因为左边的 {a, b}被认为是一个块而不是对象字面量。
({a, b} = {a: 1, b: 2}) 是有效的,相当于var {a, b} = {a: 1, b: 2}

3.注意点
3.1 对象解构只会解构出等号左边出现过的属性名,且左边的变量名称必须和对象的属性名称一致, 才能解构出数据。

let {name} = {name: "ghk",age: 22};
console.log(name); //ghk
let {age} = {name: "ghk",age: 22};
console.log(age); // 34

let {a, b} = {name: 'ghk', age: 22,};
console.log(a, b); // undefined undefined

3.2 左边属性名可以多于右边,也可以给左边指定默认值

let {name, age, gender} = {name: "ghk",age: 22};
console.log(name, age, gender); // gender是undefined

let {name, age, gender = 'male'} = {name: "ghk",age: 22};
console.log(name, age, gender);

4.对象解构是可以嵌套的

const data = {
    name: 'ghk',
    age: 22,
    skill: {
        language: 'japanese',
        instrument: 'piano',
        hobby: 'hiking',
    }
};
let {language,instrument,hobby} = data.skill;
console.log(language, instrument, hobby);

剩余参数(rest parameter)

1.用法
剩余参数 语法允许我们将一个不定数量的参数表示为一个数组。
一句话:剩余参数是把很多参数整合成一个数组

function sum(...numbers) {
    //number是一个真数组,保存了传进来的所有的变量
    console.log(numbers); 
    //既然返回的是一个数组,那么就可以使用数组的各种方法了
    return numbers.reduce((prev,curr) => prev + curr,0)
}
console.log(sum(1, 2, 3, 4)); //10

2.使用 剩余参数 和使用 arguments 保存参数的区别?

  • 剩余参数保存参数返回的是一个真数组
  • 利用arguments保存参数返回一个类数组对象
function sum2() {
    console.log(arguments); //arguments返回一个类数组对象
}
sum2(1,2,3,4);

image.png
3.剩余参数应用场景
3.1 对函数参数的处理(箭头函数中使用),后续可以直接用数组的API处理
3.2 变量的解构,把剩余参数打包到一个数组中

//箭头函数中使用
let sum = (...args) => {
    return args.reduce((prevSum,curValue) => prevSum + curValue);
};
console.log(sum(1, 2, 3));

//把分数解构到score数组中
const player = ['ghk',22,5.4,5.6,7.8,9.9,4.4,6.8];
const [name, age, ...score] = player;
console.log(name);
console.log(age);
console.log(score);

扩展运算符(spread operator)

把一个可遍历对象转为一个用逗号分隔的新的参数序列,相当于剩余参数的逆运算

什么是可遍历对象
就是部署了iterator接口,可以用for of循环的数据类型。包括字符串、数组、arguments对象,DOM、NodeList对象,Generator对象等

1.用法

const arr1 = ['1','1','1','1'];
const arr2 = ['2','2','2'];
//连接数组的作用
let list = [...arr1,...arr2];
console.log(list);// ["1", "1", "1", "1", "2", "2", "2"]


//连接数组并在相应位置插入元素
let list2 = [...arr1,'separate',...arr2];
console.log(list2); // ["1", "1", "1", "1", "separate", "2", "2", "2"]
let list3 = [...arr1,...arr2,'end'];
console.log(list3);// ["1", "1", "1", "1", "2", "2", "2", "end"]
let list4 = ['start',...arr1,...arr2];
console.log(list4);// ["start", "1", "1", "1", "1", "2", "2", "2"]

2.rest parameter和spread operator的区别

Just as the spread operator allows you to expand an array into its individual elements, the rest parameter lets you bundle elements back into an array.

推荐看这篇,嘻嘻(龇牙笑)
An intro to the spread operator and rest parameter in JavaScript (ES6)

3.扩展运算符可以用来连接数组


本文章参考到的链接:
https://developer.mozilla.org...
http://webfront-js.com/artica...
https://www.freecodecamp.org/news/spread-operator-and-rest-parameter-in-javascript-es6-4416a9f47e5e/

你可能感兴趣的

载入中...