ES6学习笔记(三)【函数,对象】

绝地灬酷狼 2021-06-26 16:06 498阅读 0赞

简介

ES6对函数的扩展比较多,主要有三点:新的书写方式,参数,扩展运算符

另外还有关于严格模式和性能优化的变动,初学者暂时可以跳过这些,这里不做详细说明

这一章节的知识点非常重要,可能是ES6中最常用的知识点之一

正文

ES6中我们可以使用“箭头”(=>)定义函数。

  1. var f = v => v

箭头左侧是参数,右侧是函数要执行的代码

如果要执行的代码只有一条语句,这条语句的运行结果就是函数的返回值,上面的例子相当于:

  1. var f = function(v) {
  2. return v
  3. }

如果箭头函数的代码块部分多于一条语句,就必须使用大括号将它们括起来,并使用return语句返回。

如果箭头函数的参数不是一个(没有参数或大于一个),需要使用一个圆括号包裹参数

  1. (num1, num2) => {
  2. let num3 = 3
  3. return num1 + num2 + num3
  4. }

需要注意的是,箭头函数没有arguments对象

并且箭头函数内部的this被绑定为它定义时所在的对象,而不是随着调用方式不同而改变

箭头函数中取消了arguments对象,是因为ES6中有了更好的替代方式:扩展运算符

之前我们在数组一节提到过扩展运算符,用来展开一个可遍历的对象

如果扩展运算符写在函数的参数中,则称作rest参数,是扩展运算符的逆运算

  1. let foo = (...values) => console.log(values)
  2. foo(1, 2, 3)
  3. // [1, 2, 3]

显然我们输入的参数是逗号分隔的序列,被...操作符合成了一个数组,以此可以替代arguments对象

注意,只有...操作符写在函数的参数中,才是合并的效果,写在其他地方都是展开的效果

  1. let foo = (...values) => console.log(...values)
  2. foo(1, 2, 3)
  3. // 1 2 3

显然参数中的...把参数合并为一个数组,函数代码块中的...又把数组展开为逗号分隔序列

注意在console.log方法中,逗号将打印为空格,所以你不会在输出中看见逗号

在ES6中,我们可以直接给函数参数设置默认值

  1. let log = (x, y = 'World') => console.log(x, y)
  2. log('Hello') // Hello World
  3. log('Hello', 'China') // Hello China
  4. log('Hello', '') // Hello

注意这种默认值的声明方式与let类似,函数代码块中不能用letconst再次声明同一个参数

  1. let foo = (x = 5) => {
  2. let x = 1 // error
  3. const x = 2 // error
  4. }

思考

这部分内容希望你都可以手动敲一遍,独立思考

如果箭头函数要返回一个对象,可以这样简写吗?

  1. var getTempItem = id => { id: id, name: "Temp" }

如何改正写法?


箭头函数书写的都是匿名函数,用来写回调函数特别简洁

试着用箭头函数改写常用的参数包含回调函数的方法,比如:

  1. // 普通函数写法
  2. [1, 2, 3].map(function (x) {
  3. return x * x
  4. })
  5. // 箭头函数写法
  6. [1, 2, 3].map(x => x * x)

如果箭头函数内部嵌套箭头函数怎么写?


试着写出一个例子说明箭头函数的this与普通函数的this的不同


  1. let foo = (a, ...b, c) => console.log(a, b, c)

运行结果是什么? 试着猜测为什么会这样


  1. let foo = (x = 5) => {
  2. var x = 1
  3. let x = 1
  4. }
  5. foo()

先不运行这段代码,猜测它会在哪一行报错?

对于这段代码的运行结果,试着想出一个自己满意的解释


ES6对于对象的扩展不多,只有一些常用的简洁写法和一些新增API

在ES8中新增了对象的扩展运算符 ... 不过我们可以在Babel转译后使用它

正文

ES6中,对象的属性可以使用简洁表示法来简写

  1. let foo = 'bar'
  2. let baz = { foo}
  3. // 等同于
  4. let baz = { foo: foo}
  5. let obj = {
  6. method () { }
  7. }
  8. // 等同于
  9. let obj = {
  10. method: () => { }
  11. }

上面例子表明,在对象中,可以直接写变量,属性名为变量名, 属性值为变量的值,方法也同理

ES6中,对象的属性名可以使用表达式

  1. let obj = {
  2. ['a' + 'bc']: 123,
  3. ['h' + 'ello']() {
  4. return 'hello world!';
  5. }
  6. }
  7. console.log(obj.abc)
  8. // 123
  9. console.log(obj.hello())
  10. // hello world!

很好理解,js解析器会先执行属性名表达式,得到的结果作为真正的属性名,这个表达式必须用方括号包裹

ES6对象中新增了一些API,正常工作中用到的很少,这里只介绍两个最常见的

Object.assign 方法用于对象的合并,接收的参数是任意个对象,会依次把第2,3,4…个对象

合并到第一个对象上,如果有重复的属性名,后来的会覆盖先前的。

  1. let target = { a: 1, b: 1 }
  2. let source1 = { b: 2, c: 2 }
  3. let source2 = { c: 3 }
  4. Object.assign(target, source1, source2);
  5. target // {a:1, b:2, c:3}

Object.is 方法用于判断两个值是否相等

以前我们判断两个值相等可以用=====

不过==会发生隐式转换,===无法判断NaN

Object.is===不同之处只有两个:一是+0不等于-0,二是NaN等于自身。

  1. +0 === -0 //true
  2. NaN === NaN // false
  3. Object.is(+0, -0) // false
  4. Object.is(NaN, NaN) // true

ES8中将会支持对象的扩展运算符,这是一个还未发布的版本

不过我们早已可以使用Babel转译来使用它,并且在工作中也经常用到

  1. let z = { a: 3, b: 4 }
  2. let n = { ...z }
  3. n // { a: 3, b: 4 }

注意这段代码无法在浏览器运行,目前没有浏览器支持ES8

对象的扩展运算符通常和解构赋值配合使用,关于解构赋值,我们会在后面的章节介绍

思考

这部分内容希望你都可以手动敲一遍,独立思考

  1. const keyA = { a: 1}
  2. const keyB = { b: 2}
  3. const obj = {
  4. [keyA]: 'aaa',
  5. [keyB]: 'bbb'
  6. }

输出一下obj,并试着解释这个结果


Object.assign可以拷贝原型链上继承来的属性吗?可以拷贝不可枚举的属性吗?

for...in可以遍历原型链上继承来的属性吗?可以遍历不可枚举的属性吗?

发表评论

表情:
评论列表 (有 0 条评论,498人围观)

还没有评论,来说两句吧...

相关阅读