node-02-ECMAScript6

二、ECMAScript6

01-let命令

1.特征
1.不能进行变量提升
// var 的情况
console.log(foo); // 输出undefined
var foo = 2;

// let 的情况
console.log(bar); // 报错ReferenceError
let bar = 2;
2.不能重复声明
// 报错
function func() {
  let a = 10;
  var a = 1;
}

// 报错
function func() {
  let a = 10;
  let a = 1;
}
3.有块级作用域

ES6 的块级作用域必须有大括号,如果没有大括号,JavaScript 引擎就认为不存在块级作用域

{
  let a = 10;
  var b = 1;
  //let声明的变量只在它所在的代码块有效。
}

a // ReferenceError: a is not defined.
b // 1
for循环的计数器,就很合适使用let命令

使用var

var a = [];
for (var i = 0; i < 10; i++) {
  a[i] = function () {
    console.log(i);
  };
}
a[6](); // 10

上面代码中,变量ivar命令声明的,在全局范围内都有效,所以全局只有一个变量i。每一次循环,变量i的值都会发生改变,而循环内被赋给数组a的函数内部的console.log(i),里面的i指向的就是全局的i。也就是说,所有数组a的成员里面的i,指向的都是同一个i,导致运行时输出的是最后一轮的i的值,也就是 10。

使用let

var a = [];
for (let i = 0; i < 10; i++) {
  a[i] = function () {
    console.log(i);
  };
}
a[6](); // 6

变量ilet声明的,当前的i只在本轮循环有效,所以每一次循环的i其实都是一个新的变量,所以最后输出的是6

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

块级作用域拓展

考虑到环境导致的行为差异太大,应该避免在块级作用域内声明函数。如果确实需要,也应该写成函数表达式,而不是函数声明语句。

// 块级作用域内部的函数声明语句,建议不要使用
{
  let a = 'secret';
  function f() {
    return a;
  }
}

// 块级作用域内部,优先使用函数表达式
{
  let a = 'secret';
  let f = function () {
    return a;
  };
}
4.可以重新赋值
//var 的情况
var food = '红烧肉';
food = "青椒肉丝";
console.log(food);//"青椒肉丝"

//let 的情况
let food = '红烧肉';
food = "青椒肉丝";
console.log(food);//"青椒肉丝"
5.暂时性死区

ES6 明确规定,如果区块中存在letconst命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。

if (true) {
  // TDZ开始
  tmp = 'abc'; // ReferenceError
  console.log(tmp); // ReferenceError

  let tmp; // TDZ结束
  console.log(tmp); // undefined

  tmp = 123;
  console.log(tmp); // 123
}

02-const(常量)命令

1.特点
1.不能进行变量提升
if (true) {
  console.log(MAX); // ReferenceError
  const MAX = 5;
}

2.不能重复声明
var message = "Hello!";
let age = 25;

// 以下两行都会报错
const message = "Goodbye!";
const age = 30;

3.有块级作用域
if (true) {
  const MAX = 5;
}

MAX // Uncaught ReferenceError: MAX is not defined

4.一旦声明,需要立刻赋值
const foo;
// SyntaxError: Missing initializer in const declaration

5.无法重新赋值
const food = "哈哈";
food = "嘻嘻";//报错
console.log(food);

6.暂时性死区
if (true) {
  console.log(MAX); // ReferenceError
  const MAX = 5;
}

2.本质

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

const foo = {};

// 为 foo 添加一个属性,可以成功
foo.prop = 123;
foo.prop // 123

// 将 foo 指向另一个对象,就会报错
foo = {}; // TypeError: "foo" is read-only

总结

  1. 能用const 不用let
  2. 能用let 不用 var

03-解构

1.对象解构

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

基本用法
//对象解构
const obj = {
    name:'玉川',
    age:19,
    gender:"男"
};

//把对象中对应的值 赋值给对应的变量
// const {name,age,gender } = obj;
// console.log(name,age,gender);

const {name,skin} = obj;
console.log(name,skin); //"玉川"  undefined

默认值
var {x = 3} = {x: undefined};
x // 3

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

默认值生效的条件是,对象的属性值严格等于undefined

2.数组解构

本质上,这种写法属于“模式匹配”,只要等号两边的模式相同,左边的变量就会被赋予对应的值。

let [a, b, c] = [1, 2, 3];

不完全解构
//数组的解构.
const arr1 = [1,2,3,4,5];

//声明num1,num2变量,  他们的值是arr1数组里对应的值.
const [num1,num2,num3,num4,num5,num6] = arr1;
console.log(num1,num2,num3,num4,num5,num6); //num6没有值就是undefined

let [x, y] = [1, 2, 3];
x // 1
y // 2

let [a, [b], d] = [1, [2, 3], 4];
a // 1
b // 2
d // 4

// 报错
let [foo] = 1;
let [foo] = false;
let [foo] = NaN;
let [foo] = undefined;
let [foo] = null;
let [foo] = {};

默认值
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] = [undefined];
x // 1

let [x = 1] = [null];
x // null

如果一个数组成员是null,默认值就不会生效,因为null不严格等于undefined

注意

1.如果要将一个已经声明的变量用于解构赋值,必须非常小心。

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

因为 JavaScript 引擎会将{x}理解成一个代码块,从而发生语法错误。

// 正确的写法
let x;
({x} = {x: 1});

只有不将大括号写在行首,避免 JavaScript 将其解释为代码块,才能解决这个问题。

2.解构赋值允许等号左边的模式之中,不放置任何变量名。

({} = [true, false]);
({} = 'abc');
({} = []);

3.由于数组本质是特殊的对象,因此可以对数组进行对象属性的解构

let arr = [1, 2, 3];
let {0 : first, [arr.length - 1] : last} = arr;
first // 1
last // 3

3.字符串解构

字符串被转换成了一个类似数组的对象

const [a, b, c, d, e] = 'hello';
a // "h"
b // "e"
c // "l"
d // "l"
e // "o"

类似数组的对象都有一个length属性

let {length : len} = 'hello';
len // 5

4.数值和布尔值的解构赋值

只要等号右边的值不是对象或数组,就先将其转为对象。由于undefinednull无法转为对象,所以对它们进行解构赋值,都会报错。

let {toString: s} = 123;
s === Number.prototype.toString // true

let {toString: s} = true;
s === Boolean.prototype.toString // true

let { prop: x } = undefined; // TypeError
let { prop: y } = null; // TypeError

5.函数参数的解构赋值
function add([x, y]){
  return x + y;
}

add([1, 2]); // 3

用途
1.交换变量的值
let x = 1;
let y = 2;

[x, y] = [y, x];

2.从函数返回多个值
// 返回一个数组

function example() {
  return [1, 2, 3];
}
let [a, b, c] = example();

// 返回一个对象

function example() {
  return {
    foo: 1,
    bar: 2
  };
}
let { foo, bar } = example();

3.函数参数的定义
// 参数是一组有次序的值
function f([x, y, z]) { ... }
f([1, 2, 3]);

// 参数是一组无次序的值
function f({x, y, z}) { ... }
f({z: 3, y: 2, x: 1});

4.提取 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]

04-箭头函数

简写匿名函数

//1.无参无返回值的函数.
 const test = function(){
    console.log('呵呵');
 }

1.将关键字function省略,在()和{}之间加=>
//funciton不写,改成=>
const test = ()=>{
     console.log('呵呵');
 }
test();

2.形参只有一个,则可以省略括号
//函数体只有一句话,可以省略大括号
const test = ()=> console.log('呵呵');
 test();

3.形参没有或者为多个,则括号不能省略
const test = (name,age) => {
    console.log('你好哦'+name+",年龄是"+age);
    return 100;
}
 console.log(test('玉川',18));

4.函数体只有一句话,可以省略大括号
const test = name => console.log('你好哦,'+name);
test("玉川");

5.函数体只有一句话,并且是返回值那句,那在省略大括号的同时也要省略return.
const test  = name => 100;
test();
6.函数体不止一句,则不能省略大括号
const test = (name,age) => {
    console.log('你好哦'+name+",年龄是"+age);
    return 100;
}
 console.log(test('玉川',18));
箭头函数中this的指向
  1. 箭头函数在创建时,this就会固定,和箭头函数平级的this一样

  2. 箭头函数在创建时,内部的this会自动确定为,当前 上下文 中的this

  3. 原理,用变量将this保存下来

    let _this = this
    
  4. 适用场景

    node.js中使用没问题

    dom中最好不要使用,此时this会被改变
    5.当在一个对象的方法中使用箭头函数时,此时this的指向是对象所在的作用域

05-扩展运算符

1.写法

三个点(…)

2.用途
1.替代函数的apply方法

a.取代apply方法展开数组,简化求出一个数组最大元素的写法

// ES5 的写法
Math.max.apply(null, [14, 3, 77])

// ES6 的写法
Math.max(...[14, 3, 77])

// 等同于
Math.max(14, 3, 77);

b.push方法的参数不能是数组,所以只好通过apply方法变通使用push方法

// ES5的 写法
var arr1 = [0, 1, 2];
var arr2 = [3, 4, 5];
Array.prototype.push.apply(arr1, arr2);

// ES6 的写法
let arr1 = [0, 1, 2];
let arr2 = [3, 4, 5];
arr1.push(...arr2);

2.复制数组

数组是复合的数据类型,直接复制的话,只是复制了指向底层数据结构的指针,而不是克隆一个全新的数组。

const a1 = [1, 2];
// 写法一
const a2 = [...a1];
// 写法二
const [...a2] = a1;

3.合并数组
const arr1 = ['a', 'b'];
const arr2 = ['c'];
const arr3 = ['d', 'e'];

// ES5 的合并数组
arr1.concat(arr2, arr3);
// [ 'a', 'b', 'c', 'd', 'e' ]

// ES6 的合并数组
[...arr1, ...arr2, ...arr3]
// [ 'a', 'b', 'c', 'd', 'e' ]

3.拓展-对象展开
const obj1 = {
    name:'玉川',
    age:18,
    sayHi:()=>{
        console.log('呵呵');
    }
}

//对象展开
//如果有同名的属性,后面的会把前面的给覆盖.
const obj2 = {
    age:19,
    ...obj1,
    skin:"黄色"
}


console.log(obj2)

06-模板字符串

  1. 定义的符号 反引号`` 1的左边
  2. 挖坑:${表达式}
  3. 注意点
    1. 坑不变色
    2. 十有八九写错了,检查两边的符号是否为反引号
//模板字符串.
//1.换行不用拼接,保留我们的格式
//2.可以占位.填坑
const name = '玉川';
const str = `
    静夜思
       唐.李白
    床前明月光
    床下鞋两双
    举头望明月
    低头吻${name}
`;
console.log(str);

07-ES6兼容问题

1.新的浏览器都是兼容es6的.

2.babel网站, 这个网站可以把新语法转成es5

https://www.babeljs.cn/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值