ES6的声明方式、字符串方法、模板字符串和解构赋值

ES6(一)

偶然看到自己的笔记里有以前学的node和ES6的笔记,记得有些散,这两天会好好整理一下,一次性把之前的笔记都更新成博客

let 和 const

在讲述这两个声明方式之前,需要先解释一下块级作用域的概念,这是es6种新加入的概念

块级作用域

块作用域由 { } 包括,if语句和 for语句里面的{ }也属于块作用域。

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
{
var a = 1;
console.log(a); // 1
}
console.log(a); // 1
// 通过var定义的变量可以跨块作用域访问到。

(function A() {
var b = 2;
console.log(b); // 2
})();
// console.log(b); // 报错,
// 可见,通过var定义的变量不能跨函数作用域访问到

if(true) {
var c = 3;
}
console.log(c); // 3
for(var i = 0; i < 4; i ++) {
var d = 5;
};
console.log(i); // 4 (循环结束i已经是4,所以此处i为4)
console.log(d); // 5
// if语句和for语句中用var定义的变量可以在外面访问到,
// 可见,if语句和for语句属于块作用域,不属于函数作用域。

块级作用域使外层作用域无法获取到内层作用域,非常安全明了。即使外层和内层都使用相同变量名,也都互不干扰。

var,let,const三者的区别

  1. var定义的变量,没有块的概念,可以跨块访问, 不能跨函数访问。
  2. let声明过的变量,可以重复赋值,但是不能重复定义,优点是可以防止变量泄露。let声明的变量仅仅在块级作用域中有效。
  3. const声明过的变量会成为一个常量,不可以被重复定义与赋值。
    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
    29
    30
    31
    32
    // 块作用域
    {
    var a = 1;
    let b = 2;
    const c = 3;
    // c = 4; // 报错
    var aa;
    let bb;
    // const cc; // 报错
    console.log(a); // 1
    console.log(b); // 2
    console.log(c); // 3
    console.log(aa); // undefined
    console.log(bb); // undefined
    }
    console.log(a); // 1
    // console.log(b); // 报错
    // console.log(c); // 报错

    // 函数作用域
    (function A() {
    var d = 5;
    let e = 6;
    const f = 7;
    console.log(d); // 5
    console.log(e); // 6
    console.log(f); // 7

    })();
    // console.log(d); // 报错
    // console.log(e); // 报错
    // console.log(f); // 报错

字符串

  1. codePointAt:codePointAt方法的参数,是字符在字符串中的位置(从 0 开始)。相比起charAt方法,它可以正确处理4个字节储存的字节,返回一个字符的码点(返回的结果和charCodeAt方法一样)。
  2. String.fromCodePoint:通过编码返回字符。例:String.fromCodePoint(//编码数)。如果有多个参数,则它们会被合并成一个字符串返回。(可以接收大于0xFFFF的码点)
  3. 字符串的遍历器:
    1
    2
    3
    4
    5
    6
    for (let codePoint of 'foo') {
    console.log(codePoint)
    }
    // "f"
    // "o"
    // "o"

字符串可以被for...of循环遍历。

  1. normalize:许多欧洲语言有语调符号和重音符号。为了表示它们,Unicode 提供了两种方法。一种是直接提供带重音符号的字符,比如Ǒ(\u01D1)。另一种是提供合成符号(combining character),即原字符与重音符号的合成,两个字符合成一个字符,比如O(\u004F)和ˇ(\u030C)合成Ǒ(\u004F\u030C)。
    normaliz()方法用来将这些字符的不同表示方法统一为同样的形式。如:
    1
    2
    '\u01D1'.normalize() === '\u004F\u030C'.normalize()
    // true

normalize方法可以接受一个参数来指定normalize的方式,参数的四个可选值如下。

- NFC,默认参数,表示“标准等价合成”,返回多个简单字符的合成字符。
- NFD,表示“标准等价分解”(,即在标准等价的前提下,返回合成字符分解的多个简单字符。
- NFKC,表示“兼容等价合成”(,返回合成字符。所谓“兼容等价”指的是语义上存在等价,但视觉上不等价,比如“囍”和“喜喜”。(这只是用来举例,normalize方法不能识别中文。)
- NFKD,表示“兼容等价分解”,即在兼容等价的前提下,返回合成字符分解的多个简单字符。
  1. reapeat:可以接收一个参数,为重复的次数。可以重复显示字符串,但是不会改变字符串本身。
  2. includes(), startsWith(), endsWith():传统上,JavaScript 只有indexOf方法,可以用来确定一个字符串是否包含在另一个字符串中。ES6 又提供了三种新方法。
  • includes():返回布尔值,表示是否找到了参数字符串。
  • startsWith():返回布尔值,表示参数字符串是否在原字符串的头部。
  • endsWith():返回布尔值,表示参数字符串是否在原字符串的尾部。

模板字符串

模板字符串(template string)是增强版的字符串,用反引号(`)标识。它可以当作普通字符串使用,也可以用来定义多行字符串,或者在字符串中嵌入变量。zhuytao

1
2
3
4
5
6
7
8
9
10
11
12
13
// 普通字符串
`In JavaScript '\n' is a line-feed.`

// 多行字符串
`In JavaScript this is
not legal.`

console.log(`string text line 1
string text line 2`);

// 字符串中嵌入变量
let name = "Bob", time = "today";
`Hello ${name}, how are you ${time}?`

ES6的模板字符串实现起来就容易好多。关键语法${},其中可以插入任何的 js 表达式。

1
2
3
4
5
let name = 'xixi';
let age = 27;

let info = `my name is ${name}, my age is ${age}. just a test ${1 + 10}!`;
console.log(info);// my name is xixi, my age is 27. just a test 11!

解构赋值

  • 变量于后面的结构一致可完成赋值,如let[a,b,c] = [10,20,30]
  • 一般用于传参.
  • 解构赋值本质是模式匹配,只要等号两边的模式相同,左边的变量就会被赋予对应的值,如果不匹配,则只有匹配的几个变量会被赋值,其他变量默认为undefined。

数组结构

1
2
3
4
5
let [a, b, c] = [1, 2, 3] // a=1, b=2, c=3
let [d, [e], f] = [1, [2], 3] // 嵌套数组解构 d=1, e=2, f=3
let [g, ...h] = [1, 2, 3] // 数组拆分 g=1, h=[2, 3]
let [i,,j] = [1, 2, 3] // 不连续解构 i=1, j=3
let [k,l] = [1, 2, 3] // 不完全解构 k=1, l=2

对象结构

1
2
3
4
5
6
let {a, b} = {a: 'aaaa', b: 'bbbb'} // a='aaaa' b='bbbb'
let obj = {d: 'aaaa', e: {f: 'bbbb'}}
let {d, e:{f}} = obj // 嵌套解构 d='aaaa' f='bbbb'
let g;
(g = {g: 'aaaa'}) // 以声明变量解构 g='aaaa'
let [h, i, j, k] = 'nice' // 字符串解构 h='n' i='i' j='c' k='e'

对象的解构赋值的内部机制,是先找到同名属性,然后再赋值给对应的变量,真正被赋值的是后者,而不是前者。可以看看下面这个例子

1
2
3
4
5
6
7
8
9
10
11
12
13
const node = {
grand : {
father : {
line : 1,
column : 5
}
}
}

let {grand,grand : { father},grand : {father : {column}}} = node;
console.log(father); // {line : 1, column : 5}
console.log(column); // 5
// grand、fahter、column 分别对这三个属性解构赋值,grand、father是模式,只有column 是变量

要实现这样子的解构赋值,需要保证变量名和模式名都是匹配的

默认值

1
2
3
4
5
6
7
8
let [x,y='b'] = ['a'];
console.log(y); //b

let [x,y = 'b'] = ['a',undefined];
console.log(y); //b ,数组成员为undefined时,默认值仍会生效(因为在ES6内部使用严格相等运算符‘===‘,判断一个位置是否有值,所以当一个数组成员严格等于undefined,默认值才会生效)

let [x,y = 'b'] = ['a',null];
console.log(y); //null,如果一个数组成员是null,默认值就不会生效,因为null不严格等于undefined

字符串的解构赋值

1
2
3
4
5
6
7
8
9
const [a,b,c,d,e] = 'hello';
console.log(a); //h
console.log(b); //e
console.log(c); //l
console.log(d); //l
console.log(e); //o

let { length : len} = 'yahooa';
console.log(len); //6,类似数组的对象都有一个length属性,还可以对这个属性解构赋值

函数的解构赋值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function move({x = 0,y = 0} = { }){
return [x,y];
}
console.log(move({x : 3,y : 4})); //[3,4]
console.log(move({x : 3})); //[3,0]
console.log(move({})); //[0,0]
console.log(move()); //[0,0]
//move()的参数是一个对象,通过对这个对象进行解构,得到变量x、y的值,如果解构失败,x和y 等于默认值
function move2({x,y} = {x : 1, y : 2 }){
return [x,y];
}
console.log(move2({x : 6,y : 8})); //[6,8]
console.log(move2({})); //[undefined,undefined]
console.log(move2()); //[1,2]
//move2() 是为函数move的参数指定默认值,而不是为变量x和y指定默认值,所以与前一种写法的结果不太一样,undefined 就会触发函数的默认值

用途

交换变量的值
1
2
3
4
5
6
7
let x = 1;
let y = 2;

[x, y] = [y, x];
```
上面代码交换变量x和y的值
##### 从函数返回参数

function example(){
return {
foo : ‘a’,
bar : ‘b’
}
}
let {foo,bar} = example();
console.log(foo); //a
console.log(bar); //b

1
##### 函数参数的定义

//参数是一组有次序的值
function example([x,y,z]){
return x + y + z;
}
example([1,2,3])
console.log(example([1,2,3])); //6
//参数是一组无次序的值
function f({x,y,z}){
return x + y + z;
}
f({x : ‘a’, z : ‘b’, y : ‘c’ });

console.log(f({x : ‘a’, z : ‘b’, y : ‘c’ })); //acb

1
2
##### 提取json的数据
个人觉得这是解构赋值最泛用的地方了,在前后端的交互中,前端从后台获取的数据多为json格式的数据,这时候解构赋值就能方便前端对这些的利用了

let jsonData = {
id: 42,
status: “OK”,
data: [867, 5309]
};

let { id, status, data: number } = jsonData;

console.log(id, status, number);
// 42, “OK”, [867, 5309
`