阮一峰大神ECMAScript 6 入门|笔记整理

https://es6.ruanyifeng.com/

大家要是看不惯这边的排版,可以去我的语雀看看,语雀真的绝

https://www.yuque.com/isremya/vqgp35

let 和 const 命令

  • let声明的变量只在它所在的代码块有效。

 

  • 变量 i 是var命令声明的,在全局范围内都有效,所以全局只有一个变量i。
  • 变量 i 是let声明的,当前的 i只在本轮循环有效,所以每一次循环的i其实都是一个新的变量

 

  • 另外,for循环还有一个特别之处,就是设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域。
for (let i = 0; i < 3; i++) {
  let i = 'abc';
  console.log(i);
}
// abc
// abc
// abc
  • ES6 明确规定,如果区块中存在let和 const命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。即不存在变量提升。

 

  • 暂时性死区的本质就是,只要一进入当前作用域,所要使用的变量就已经存在了,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用该变量。

 

  • let不允许在相同作用域内,重复声明同一个变量。
function func(arg) {
  let arg;        //不能在函数内部重新声明参数。
}
func() // 报错

function func(arg) {
  {
    let arg;
  }
}
func() // 不报错
 
  • 允许在块级作用域内声明函数。
  • 函数声明类似于 var ,即会提升到全局作用域或函数作用域的头部。
  • 同时,函数声明还会提升到所在的块级作用域的头部。
// 块级作用域内部的函数声明语句,建议不要使用
{
  let a = 'secret';
  function f() {
    return a;
  }
}

// 块级作用域内部,优先使用函数表达式
{
  let a = 'secret';
  let f = function () {
    return a;
  };
}
 
  •  const一旦声明变量,就必须立即初始化,不能留到以后赋值。

 

  •  const 实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动。

 

  • ES6 一共有 6 种声明变量的方法。var命令和function 命令。let和const命令,import 命令和class命令。

 

  • ES6 一方面规定,为了保持兼容性,var命令和function命令声明的全局变量,依旧是顶层对象的属性;另一方面规定,let命令、const'命令、class命令声明的全局变量,不属于顶层对象的属性。也就是说,从 ES6 开始,全局变量将逐步与顶层对象的属性脱钩。

 

  • 全局环境中,this会返回顶层对象。但是,Node 模块和 ES6 模块中,this返回的是当前模块。
  • 函数里面的this,如果函数不是作为对象的方法运行,而是单纯作为函数运行,this 会指向顶层对象。但是,严格模式下,这时this 会返回 undefined。

 

变量的解构赋值

  • ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构。
  • 如果解构不成功,变量的值就等于 undefined

 

  • 数组的元素是按次序排列的,变量的取值由它的位置决定;
  • 而对象的属性没有次序,变量必须与属性同名,才能取到正确的值。

 

let { foo: baz } = { foo: 'aaa', bar: 'bbb' };
baz // "aaa"
let { foo: baz } = { foo: 'aaa', bar: 'bbb' };
baz // "aaa"
foo // error: foo is not defined
//上面代码中,foo是匹配的模式,baz才是变量。真正被赋值的是变量baz,而不是模式foo。
const node = {
  loc: {
    start: {
      line: 1,
      column: 5
    }
  }
};

let { loc, loc: { start }, loc: { start: { line }} } = node;
line // 1
loc  // Object {start: Object}
start // Object {line: 1, column: 5}
// 报错
let {foo: {bar}} = {baz: 'baz'};
//whywhywhy???
 
  • 对象的解构也可以指定默认值。
var {x = 3} = {};
x // 3

var {x, y = 5} = {x: 1};
x // 1
y // 5

var {x: y = 3} = {};
y // 3

var {x: y = 3} = {x: 5};
y // 5

var { message: msg = 'Something went wrong' } = {};
msg // "Something went wrong"
// 错误的写法
let x;
{x} = {x: 1};
// SyntaxError: syntax error

// 正确的写法
let x;
({x} = {x: 1});
//只有不将大括号写在行首,避免 JavaScript 将其解释为代码块,才能解决这个问题。
  • 字符串也可以解构赋值。
const [a, b, c, d, e] = 'hello';
a // "h"
b // "e"
c // "l"
d // "l"
e // "o"
  • 解构赋值的规则是,只要等号右边的值不是对象或数组,就先将其转为对象。由于undefined和null无法转为对象,所以对它们进行解构赋值,都会报错。

 

  • 函数也可以解构赋值。
[[1, 2], [3, 4]].map(([a, b]) => a + b);
// [ 3, 7 ]
  • 不得使用圆括号的情况
    • 变量声明语句
    • 函数参数
    • 赋值语句的模式
//以下三种模式全部报错
let [(a)] = [1];
let {x: (c)} = {};

function f([(z)]) { return z; }

({ p: a }) = { p: 42 };
([a]) = [5];
  • 只有赋值语句的非模式部分,可以使用圆括号。
[(b)] = [3]; // 正确
({ p: (d) } = {}); // 正确
[(parseInt.prop)] = [3]; // 正确

 

  • 变量的解构赋值用途
    • 交换变量的值
    • 从函数返回多个值
      • 函数如果要返回多个值,只能将它们放在数组或对象里返回。
    • 函数参数的定义
      • 方便地将一组参数与变量名对应起来。
    • 提取 JSON 数据
    • 函数参数的默认值 review
    • 遍历 Map 结构
      • 任何部署了 Iterator 接口的对象,都可以用 for...of 循环遍历。
      • Map 结构原生支持 Iterator 接口,配合变量的解构赋值,获取键名和键值就非常方便。
    • 输入模块的指定方法 review
//交换变量
let x = 1;
let y = 2;
[x, y] = [y, x];

// 返回一个对象
function example() {
  return {
    foo: 1,
    bar: 2
  };
}
let { foo, bar } = example();

//提取 JSON 对象中的数据
let jsonData = {
  id: 42,
  status: "OK",
  data: [867, 5309]
};
let { id, status, data: number } = jsonData;

//遍历 Map 结构
const map = new Map();
map.set('first', 'hello');
map.set('second', 'world');
for (let [key, value] of map) {
  console.log(key + " is " + value);
}
// first is hello
// second is world

// 获取键名
for (let [key] of map) {
  // ...
}

// 获取键值
for (let [,value] of map) {
  // ...
}

字符串的拓展

模板字符串

  • 用反引号(`)标识。它可以当作普通字符串使用,也可以用来定义多行字符串,或者在字符串中嵌入变量。
  • 如果在模板字符串中需要使用反引号,则前面要用反斜杠转义。
  • 所有模板字符串的空格和换行,都是被保留的,可以使用trim方法消除它。
  • 模板字符串中嵌入变量,需要将变量名写在${}之中。
  • 模板字符串之中还能调用函数。
  • 如果模板字符串中的变量没有声明,将报错。
$('#result').append(`
  There are <b>${basket.count}</b> items
   in your basket, <em>${basket.onSale}</em>
  are on sale!
`);

let greeting = `\`Yo\` World!`;

$('#list').html(`
<ul>
  <li>first</li>
  <li>second</li>
</ul>
`.trim());

function fn() {
  return "Hello World";
}

`foo ${fn()} bar`
// foo Hello World bar

实例:模板编译看不懂

标签模板    看不懂

 

字符串的新增方法

String.raw()

  • 该方法返回一个斜杠都被转义(即斜杠前面再加一个斜杠)的字符串
  • 如果原字符串的斜杠已经转义,那么 String.raw() 会进行再次转义。
String.raw`Hi
${2+3}!`
// 实际返回 "Hi\n5!",显示的是转义后的结果 "Hi
5!"

//why why why?
// `foo${1 + 2}bar`
// 等同于
String.raw({ raw: ['foo', 'bar'] }, 1 + 2) // "foo3bar"
 

确定一个字符串是否包含在另一个字符串中

  • includes():返回布尔值,表示是否找到了参数字符串。
  • startsWith():返回布尔值,表示参数字符串是否在原字符串的头部。
  • endsWith():返回布尔值,表示参数字符串是否在原字符串的尾部。

 

repeat()

返回一个新字符串,表示将原字符串重复n

参数如果是小数,会被取整。

参数是负数或者Infinity,会报错。

参数是 0 到-1 之间的小数,则等同于 0,这是因为会先进行取整运算。
参数NaN等同于 0。

参数是字符串,则会先转换成数字。

'x'.repeat(3) // "xxx"
'hello'.repeat(2) // "hellohello"
'na'.repeat(2.9) // "nana"
'na'.repeat(-0.9) // ""
'na'.repeat(NaN) // ""

//why why why?
'na'.repeat('na') // ""
'na'.repeat('3') // "nanana"

 

padStart(),padEnd()

  • 如果某个字符串不够指定长度,会在头部或尾部补全。padStart() 用于头部补全,padEnd() 用于尾部补全。
  • 如果原字符串的长度,等于或大于最大长度,则字符串补全不生效,返回原字符串。
  • 如果省略第二个参数,默认使用空格补全长度。
'x'.padStart(4, 'ab') // 'abax'
'x'.padEnd(5, 'ab') // 'xabab'

'xxx'.padStart(2, 'ab') // 'xxx'

'x'.padStart(4) // '   x'
'x'.padEnd(4) // 'x   '
 

 

trimStart(),trimEnd()

  • padStart() 消除字符串头部的空格,trimEnd() 消除尾部的空格。
  • 它们返回的都是新字符串,不会修改原始字符串。
const s = '  abc  ';

s.trim() // "abc"
s.trimStart() // "abc  "
s.trimEnd() // "  abc"

 

matchAll()

  • 返回一个正则表达式在当前字符串的所有匹配
原文地址:https://www.cnblogs.com/isremya/p/13428321.html