ES6标准---【一】【学习ES6看这一篇就够了!!】

目录

顶层对象的属性

ES5中的顶层对象

ES6中的顶层对象

数组的解构赋值

默认值

对象的解构赋值

默认值

注意点:

字符串的解构赋值

数值和布尔值的解构赋值

函数参数的解构赋值

ES6中的圆括号问题

不能使用圆括号的情况

变量声明语句

函数参数

赋值语句的模式

可以使用圆括号的情况

变量解构赋值的用途【重要】

1.交换变量的值

2.从函数返回多个值

3.函数参数的定义

4.提取JSON数据

5.遍历MAP结构

顶层对象的属性

ES5中的顶层对象

顶层对象,在浏览器环境指的是window对象,ES5中顶层对象的属性与全局变量是等价的

window.a = 1;
console.log(a);
a = 2;
console.log(window.a)

 

对顶层对象的属性赋值与全局变量的赋值,是同一件事

ES6中的顶层对象

在ES6中:

“var”和“function”命令声明的全局变量,依旧是顶层变量的属性;

“let”命令、“const”命令、“class”命令声明的全局变量,不属于顶层的对象属性

var a = 1;
window.a // 1
let b = 1;
window.b // undefined

数组的解构赋值

ES6允许按照一定模式,从数组和对象中提取值,并对变量赋值,这被称为“解构

以前,为变量赋值,只能直接指定值

let a = 1;
let b = 2;
let c = 3;

ES6中允许写成下面这个样子

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

上面代码表示,可以从数组中提取值,按照对应位置,对变量赋值

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

let [foo,[[bar],baz]] = [1,[[2],3]]
foo // 1
bar // 2
baz // 3

let [,,third] = ["foo","bar","baz"]
third // "baz"

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

let [head,...tail] = [1,2,3,4]
head // 1
tail // [2,3,4]

//注意区别...tail 与 tail的区别
let [head,tail] = [1,2,3,4]
head // 1
tail // 2

let [x,y,...z] = ['a']
x // 'a'
y // undefined
z // []
// ...变量名 模式匹配一个数组

如果解构不成功,变量的值就等于 undefined

let [foo] = [];

let [a,b] = [1];

let [...c] = [];

foo // undefined

a // 1

b // undefined

c // []

不完全解构,只匹配一部分等号右边的数组:

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不严格等于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

上面最后一个表达式报错,是因为y变量在后面,还没有声明,改为下面格式:

let [y=1,x=y] = [];

x // 1

y // 1

就不会报错

对象的解构赋值

解构不仅可以用于数组,还可以用于对象

解构的是对象属性值,而不是对象属性名

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

对象的属性没有次序,变量必须与属性同名,才能取到正确的值

即:“对象的解构赋值与次序无关

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

如果解构失败,变量的值等于undefined

let {foo} = {bar: 'baz'};
foo // undefined

对象的解构赋值,可以很方便的将对象的方法,赋值给某个变量,以后直接使用这个变量即可

// 例一
let { log, sin, cos } = Math;
// 例二
const { log } = console;
log('hello') // hello

上面将Math对象的对数、正弦、余弦三个方法,赋值到对应的变量上,使用起来就会方便很多。

例二将console.log赋值到log变量

如果变量名与属性名不一致,必须写成下面这样:

let { foo: baz } = { foo: 'aaa', bar: 'bbb' };
baz // "aaa"
let obj = { first: 'hello', last: 'world' };
let { first: f, last: l } = obj;
f // 'hello'
l // 'world'

对象的解构赋值,实际上是下面形式的简写:

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

即,对象的解构赋值是先找到同名属性,然后再赋值给对应的变量,真正被赋值的是后者,而不是前者

let { foo: baz } = { foo: 'aaa', bar: 'bbb' };
baz // "aaa"
foo // error: foo is not defined

上面代码中,foo是匹配的模式,baz才是变量,真正被赋值的是变量baz,而不是模式foo

解构也可以用于嵌套解构的对象:

let obj = {
  p: [
    'Hello',
    { y: 'World' }
  ]
};
let { p: [x, { y }] } = obj;
x // "Hello"
y // "World"

一个嵌套赋值的例子:

let obj = {};
let arr = [];
({ foo: obj.prop, bar: arr[0] } = { foo: 123, bar: true });
obj // {prop:123}
arr // [true]

如果结构模式是嵌套的对象,而且子对象所在的父属性不存在,那么将会报错:

// 报错
let {foo: {bar}} = {baz: 'baz'};

foo是一个子对象,该子对象的bar属性解构时会报错,原因是foo等于“undefined

对象的解构赋值可以取到继承的属性:

const obj1 = {};
const obj2 = { foo: 'bar' };
Object.setPrototypeOf(obj1, obj2);
const { foo } = obj1;
foo // "bar"

对象obj1的原型对象是obj2foo属性不是obj1自身的属性,而是继承自obj2的属性。

解构赋值可以取到这个属性

默认值

对象的结构也可以指定默认值

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"

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

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

注意点:

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

// 错误的写法
let x;
{x} = {x: 1};
// SyntaxError: syntax error
  • 上面的代码写法会报错,因为JavaScript会将“x”理解成一个代码块,从而引发错误。只有不将大括号写在行首,避免JavaScript将其解释为代码块,才能解决这个问题:
// 正确的写法
let x;
({x} = {x: 1});

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

因此可以写出非常古怪的赋值表达式,但没有什么卵用,不过可以执行

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

可以对数组进行对象属性的解构

let arr = [1, 2, 3];
let {0 : first, [arr.length - 1] : last} = arr;
first // 1
last // 3
  • 数组arr的0键对应的值是1[arr.length-1]就是2键,对应的值是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

数值和布尔值的解构赋值

解构赋值时,如果等号右边是数值和布尔值,则会先转为对象

let {toString: s} = 123;
s === Number.prototype.toString // true
let {toString: s} = true;
s === Boolean.prototype.toString // true
  • 数值布尔值的包装对象都有“toString”属性,因此变量“s”都能取到值

函数参数的解构赋值

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

function add([x, y]){
  return x + y;
}
add([1, 2]); // 3

上面代码中,函数add的参数表面是一个数组,但在传入参数的那一刻,数组参数就被解构为“x”和“y”变量

另一个例子:

[[1, 2], [3, 4]].map(([a, b]) => a + b);
// [ 3, 7 ]
  • 函数参数的解构也可以使用默认值:
function move({x = 0, y = 0} = {}) {
  return [x, y];
}
move({x: 3, y: 8}); // [3, 8]
move({x: 3}); // [3, 0]
move({}); // [0, 0]
move(); // [0, 0]
  • 下面的写法会得到不一样的结果:
function move({x, y} = { x: 0, y: 0 }) {
  return [x, y];
}
move({x: 3, y: 8}); // [3, 8]
move({x: 3}); // [3, undefined]
move({}); // [undefined, undefined]
move(); // [0, 0]

ES6中的圆括号问题

ES6对于圆括号的规则是:“只要有可能导致解构的歧义,都不得使用圆括号

不能使用圆括号的情况

变量声明语句

// 全部报错
let [(a)] = [1];
let {x: (c)} = {};
let ({x: c}) = {};
let {(x: c)} = {};
let {(x): c} = {};
let { o: ({ p: p }) } = { o: { p: 2 } };

函数参数

// 报错
function f([(z)]) { return z; }
// 报错
function f([z,(x)]) { return x; }

赋值语句的模式

// 全部报错
({ p: a }) = { p: 42 };
([a]) = [5];
// 报错
[({ p: a }), { x: c }] = [{}, {}];

可以使用圆括号的情况

[(b)] = [3]; // 正确
({ p: (d) } = {}); // 正确
[(parseInt.prop)] = [3]; // 正确
  • 首先三条语句都是赋值语句,不是声明语句
  • 其次它们的圆括号都不属于模式的一部分
    • 第一行语句中,模式是取数组的第一个成员,跟圆括号无关
    • 第二行语句中,模式是p,而不是d
    • 第三行语句与第一行语句性质一致

变量解构赋值的用途【重要

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数据

解构赋值对提取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]

5.遍历MAP结构

任何部署了“Iterator”接口的对象,都可以用“for...of”循环遍历,Map结构原生支持Iterator接口,配合变量的解构赋值,获取键名和键值就非常方便

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) {
  // ...
}

学习webpack是为了掌握前端代码打包工具的使用。随着前端工程化的发展,webpack已经成为了前端开发中最常用的打包工具之一。学习webpack可以帮助我们对项目的模块化管理、代码压缩与优化、资源加载等方面进行更加灵活和高效的处理。 这篇文章主要介绍了webpack的基础知识和使用方法。首先,它解释了webpack的基本概念,如入口和出口文件、loader和plugin等。然后,它详细介绍了如何配置webpack的各个参数和插件,包括如何使用Babel处理ES6语法,如何使用Less或Sass处理CSS,如何使用图片压缩插件等。 接着,文章讲解了webpack的打包原理和优化技巧。它介绍了webpack的模块化加载机制,以及如何使用Code Splitting和Dynamic Import等功能来提高页面加载速度。同时,它还提到了如何使用webpack进行代码分割和缓存优化,以及如何使用Tree Shaking和代码压缩插件来减小项目的体积。 最后,文章介绍了webpack的常见问题和解决方法。它列举了一些常见的错误和警告信息,并提供了相应的解决方案。此外,它还提供了一些常用的webpack插件和工具的推荐,帮助我们更好地进行前端开发。 总的来说,这篇文章提供了一个很好的入门教程,可以帮助我们快速掌握webpack的基本概念和使用方法。但是,要想在实际项目中灵活应用webpack,还需要深入学习官方文档和相关资料,并结合实际项目进行实践。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

是洋洋a

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值