ES6 笔记

Bable的Es6 2 Es5工具

let与const

let

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

{
  let a = 10;
  var b = 1;
}
a  //Uncaught ReferenceError: a is not defined
b  //1

let声明的i只在for循环中有效

// let
for(let i=0;i<3;i++){}  //let声明的i只在for循环中有效
console.log(i);  // ReferenceError: a is not defined
// var
for(var i=0;i<3;i++){}  //for循环中的i是全局变量
console.log(i);   //3  变量i只用来控制循环,但是循环结束后,它并没有消失,泄露成了全局变量。
// let
let a = [];
for (let i = 0; i < 10; i++) {
  a[i] = function () {
    console.log(i);
  };
}
a[6](); // 6
// var
var a = [];
for (var i = 0; i < 10; i++) {
  a[i] = function () {
    console.log(i);    //i是全局变量
  };
}
a[6](); // 10
// 改进版 var  
var a = [];
for (var i = 0; i < 10; i++) {
  (function(j) {        //用一个闭包把里面的i与
      a[j] = function () {     
        console.log(j)
      }
  })(i)   //每一次循环的i其实都是一个新的变量
}
a[6](); 

for循环还特别之处,设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域

for (let i = 0; i < 3; i++) {
  let i = 'abc';
  console.log(i);
}
// abc
// abc
// abc

let不存在变量提升

//let
console.log(bar); // 报错ReferenceError
let bar = 2;
//var
console.log(foo); // 输出undefined
var foo = 2;
// var相当于
var foo;  //变量声明默认值为undefined
console.log(foo); // 输出undefined
foo = 2;   //先声明再调用

“暂时性死区”(temporal dead zone,简称 TDZ)

var tmp = 123;
if (true) {
  tmp = 'abc'; // ReferenceError
  let tmp;
}

let不允许在相同作用域内,重复声明同一个变量
let实际上为 JavaScript 新增了块级作用域
ES5 只有全局作用域和函数作用域,没有块级作用域

// let
function f1() {
  let n = 5;
  if (true) {
    let n = 10;
  }
  console.log(n); // 5 外层代码块不受内层代码块的影响
}
// var 10
// IIFE 写法
(function () {
  var tmp = ...;
  ...
}());
// 块级作用域写法
{
  let tmp = ...;
  ...
}

ES5 规定,函数只能在顶层作用域和函数作用域之中声明,不能在块级作用域声明
应该避免在块级作用域内声明函数

const

const声明一个只读的常量
常量的值就不能改变

const PI = 3.1415;
PI // 3.1415
PI = 3;
// TypeError: Assignment to constant variable.

const一旦声明变量,就必须立即初始化,只声明不赋值,就会报错。
const的作用域与let命令相同:只在声明所在的块级作用域内有效。
const命令声明的常量也不存在提升
const同样存在暂时性死区
const只能在声明后使用
const不可重复声明
const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址不得改动。

变量的解构赋值

数组解构赋值

如果解构不成功,变量的值就等于undefined
解构赋值允许指定默认值

let [foo = true] = [];    //foo=true
let [x, y = 'b'] = ['a']; // x='a', y='b'
let [x, y = 'b'] = ['a', undefined]; // x='a', y='b'

ES6 内部使用严格相等运算符(===),判断一个位置是否有值。所以,只有当一个数组成员严格等于undefined,默认值才会生效
默认值可以引用解构赋值的其他变量,但该变量必须已经声明

let [x = 1, y = x] = [];     // x=1; y=1
let [x = 1, y = x] = [2];    // x=2; y=2
let [x = 1, y = x] = [1, 2]; // x=1; y=2
let [x = y, y = 1] = [];     // ReferenceError: y is not defined

对象解构赋值

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

let { foo} = { foo: 'aaa', bar: 'bbb' };
foo// "aaa"
let { foo:foo} = { foo: 'aaa', bar: 'bbb' };
foo// "aaa"
let { foo: baz } = { foo: 'aaa', bar: 'bbb' };
baz // "aaa"

对象的解构也可以指定默认值
默认值生效的条件是,对象的属性值严格等于undefined
如果解构失败,变量的值等于undefined
如果要将一个已经声明的变量用于解构赋值,会报错,因为 JavaScript 引擎会将{x}理解成一个代码块

// 错误的写法
let x;
{x} = {x: 1};   // SyntaxError: syntax error
// 正确的写法
let x;
({x} = {x: 1});

字符串解构赋值

数值和布尔值解构赋值

函数的参数解构赋值

函数参数的解构也可以使用默认值

字符串的扩展

字符的 Unicode

charCodeAt()

能够正确处理 4 个字节储存的字符,返回一个字符的码点。

String.fromCodePoint()

字符串的遍历

for (let codePoint of 'foo') {
  console.log(codePoint)
}
// "f"
// "o"
// "o"

at()

normalize()

includes(),startsWith(),endsWith()

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

repeat()

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

padStart(),padEnd()

padStart()用于头部补全,padEnd()用于尾部补全

模板字符串

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

// 普通字符串
`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}?`

使用模板字符串表示多行字符串,所有的空格和缩进都会被保留在输出之中,如果你不想要这个换行,可以使用trim方法消除它

标签模板

String.raw()

正则的扩展

数值的扩展

二进制和八进制

Number.isFinite(),Number.isNaN()

只对数值有效

Number.parseInt(),Number.parseFloat()

Number.isInteger()

Number.isInteger()用来判断一个数值是否为整数
由于 JavaScript 采用 IEEE 754 标准,数值存储为64位双精度格式,数值精度最多可以达到 53 个二进制位(1 个隐藏位与 52 个有效位)。如果数值的精度超过这个限度,第54位及后面的位就会被丢弃,这种情况下,Number.isInteger可能会误判。

Number.EPSILON

极小的常量Number.EPSILON。根据规格,它表示 1 与大于 1 的最小浮点数之间的差

Number.EPSILON === Math.pow(2, -52)
0.1 + 0.2 === 0.3 // false

Number.isSafeInteger()

JavaScript 能够准确表示的整数范围在-253到253之间(不含两个端点),超过这个范围,无法精确表示这个值,Number.MAX_SAFE_INTEGER和Number.MIN_SAFE_INTEGER这两个常量,用来表示这个范围的上下限,Number.isSafeInteger()则是用来判断一个整数是否落在这个范围之内

Math.trunc()

Math.trunc方法用于去除一个数的小数部分,返回整数部分

Math.sign()

Math.sign方法用来判断一个数到底是正数、负数、还是零。对于非数值,会先将其转换为数值

Math.cbrt()

Math.cbrt方法用于计算一个数的立方根

指数运算符(**)

2**2  //4
a **= 2;  // 等同于 a = a * a;

函数的扩展

ES6 允许为函数的参数设置默认值,即直接写在参数定义的后面

function log(x, y = 'World') {
  console.log(x, y);
}

参数变量是默认声明的,所以不能用let或const再次声明
使用参数默认值时,函数不能有同名参数
参数默认值不是传值的,而是每次都重新计算默认值表达式的值。也就是说,参数默认值是惰性求值的
定义了默认值的参数,应该是函数的尾参数
如果传入undefined,将触发该参数等于默认值,null则没有这个效果

函数的length属性

函数的length属性,将返回没有指定默认值的参数个数。也就是说,指定了默认值后,length属性将失真
因为length属性的含义是,该函数预期传入的参数个数。

作用域

参数会形成一个单独的作用域(context)。等到初始化结束,这个作用域就会消失。这种语法行为,在不设置参数默认值时,是不会出现的

参数默认值设为undefined,表明这个参数是可以省略的

rest参数

用于获取函数的多余参数,这样就不需要使用arguments对象了
rest 参数搭配的变量是一个数组,该变量将多余的参数放入数组中。
arguments对象不是数组,而是一个类似数组的对象。所以为了使用数组的方法,必须使用Array.prototype.slice.call先将其转为数组。rest 参数就不存在这个问题,它就是一个真正的数组
rest 参数之后不能再有其他参数(即只能是最后一个参数),否则会报错
函数的length属性,不包括 rest 参数

name属性

函数的name属性,返回该函数的函数名。
bind返回的函数,name属性值会加上bound前缀

箭头函数

使用一个圆括号代表参数部分
如果箭头函数的代码块部分多于一条语句,就要使用大括号将它们括起来,并且使用return语句返回
由于大括号被解释为代码块,所以如果箭头函数直接返回一个对象,必须在对象外面加上括号,否则会报错

箭头函数中的this

函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。
箭头函数中,this是固定的
this指向的固定化,并不是因为箭头函数内部有绑定this的机制,实际原因是箭头函数根本没有自己的this,导致内部的this就是外层代码块的this。正是因为它没有this,所以也就不能用作构造函数

箭头函数嵌套

数组的扩展

扩展运算符

扩展运算符(spread)是三个点(...)。它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列

console.log(...[1, 2, 3])  // 1 2 3

Array.from()

Array.from方法用于将两类对象转为真正的数组:类似数组的对象(array-like object)和可遍历(iterable)的对象

let arrayLike = {
    '0': 'a',
    '1': 'b',
    '2': 'c',
    length: 3
};
// ES5的写法
var arr1 = [].slice.call(arrayLike); // ['a', 'b', 'c']
// ES6的写法
let arr2 = Array.from(arrayLike); // ['a', 'b', 'c']

Array.of()

Array.of方法用于将一组值,转换为数组

数组实例的 copyWithin()

数组实例的 find() 和 findIndex()

数组实例的 fill()

fill方法使用给定值,填充一个数组

数组实例的 entries(),keys() 和 values()

数组实例的 includes()

Array.prototype.includes方法返回一个布尔值,表示某个数组是否包含给定的值

数组的空位

对象的扩展

ES6 允许在对象之中,直接写变量。这时,属性名为变量名, 属性值为变量的值
属性简写

const foo = 'bar';
const baz = {foo};     // {foo: "bar"}
const baz = {foo: foo};

方法简写

const o = {
  method() {
    return "Hello!";
  }
};
// 等同于
const o = {
  method: function() {
    return "Hello!";
  }
};

属性名表达式

let obj = {
[lastWord]: 'world',
  ['h' + 'ello']() {
    return 'hi';
  }
};
const foo = 'bar';
const baz = { [foo]: 'abc'};   //{bar: "abc"}
const a={foo}   //{foo: "bar"}

方法的 name 属性

Object.is()

Object.assign()

属性的可枚举性和遍历

Object.getOwnPropertyDescriptors()

super 关键字

关键字super,指向当前对象的原型对象
super关键字表示原型对象时,只能用在对象的方法之中,用在其他地方都会报错。

Object.keys(),Object.values(),Object.entries()

Symbol

作为属性名的 Symbol

Symbol 值作为对象属性名时,不能用点运算符
点运算符后面总是字符串,所以不会读取mySymbol作为标识名所指代的那个值
使用 Symbol 值定义属性时,Symbol 值必须放在方括号之中。

Symbol.for(),Symbol.keyFor()

Set 和 Map 数据结构

set

Set类似于数组,但是成员的值都是唯一的,没有重复的值。
Set 本身是一个构造函数,用来生成 Set 数据结构

WeakSet

WeakSet结构与 Set 类似,也是不重复的值的集合。但是,它与 Set 有两个区别。

首先,WeakSet 的成员只能是对象,而不能是其他类型的值

Map


es6

Generator 函数的含义与用法

Thunk 函数的含义和用法

co 函数库的含义和用法

async 函数的含义和用法

ES6 的功能侦测库 ES-Checker

你可能感兴趣的:(ES6 笔记)