美文网首页
阮一峰ES6教程读书笔记(五)对象的扩展

阮一峰ES6教程读书笔记(五)对象的扩展

作者: 前端艾希 | 来源:发表于2019-09-18 20:23 被阅读0次

1. 属性的简洁表示法

ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法。这样的书写更加简洁。

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

// 等同于
const baz = {foo: foo};

当然,除了属性可以简写,方法也可以简写,比如:

const obj = {
    print (param) {
        console.log(param)
    }
}

2. 属性名表达式

我们知道,读取对象的属性时可通过obj.key或者obj[key]这两种方式,不同的是第一种方式key必须是一个确定的键名,而第二种方法的key可以是确定的键名也能使一个表达式

let [key, age] = ['name', 23]

let obj = {
    [key]: 'bing',
    age: age
}
obj // {name: "bing", age: 23}

let obj = {
    [key]: 'bing',
    [age]: age
}
obj // {name: "bing", 23: 23}

通过上面的代码可以看出来,如果给给对象的键名加上[],对象的键名就会变成一个JavaScript表达式,表达式计算出来的值就是对象的键名,如果上述例子不能很好理解,看下面这个例子:

let lastWord = 'last word';

const a = {
  'first word': 'hello',
  [lastWord]: 'world'
};

a['first word'] // "hello"
a[lastWord] // "world"
a['last word'] // "world"

a[lastWord]a['last word']的值是一样的,因为lastWord变量的值就是last word,所以这两个值其实是一个对象的同一个键名对应的值。
需要注意的是如果表达式是一个对象,默认情况下会自动将对象转为字符串[object Object]

const keyA = {a: 1};
const keyB = {b: 2};

const myObject = {
  [keyA]: 'valueA',
  [keyB]: 'valueB'
};

myObject // Object {[object Object]: "valueB"}

3. 方法的 name 属性

对象的方法也是函数,因此也有name属性

const obj = {
    print () {
        console.log('hello world')
    }
}

obj.print.name // print

如果对象的方法使用了取值函数(getter)和存值函数(setter),则name属性不是在该方法上面,而是该方法的属性的描述对象的getset属性上面,返回值是方法名前加上getset

const obj = {
  get foo() {},
  set foo(x) {}
};

obj.foo.name
// TypeError: Cannot read property 'name' of undefined

const descriptor = Object.getOwnPropertyDescriptor(obj, 'foo');

descriptor.get.name // "get foo"
descriptor.set.name // "set foo"

有两种特殊情况:bind方法创造的函数,name属性返回bound加上原函数的名字;Function构造函数创造的函数,name属性返回anonymous

(new Function()).name // "anonymous"

var doSomething = function() {
  // ...
};
f = doSomething.bind(this)
f.name // "bound doSomething"

4. 属性的可枚举性

对象的每个属性都有一个描述对象,用来控制该属性的行为。Object.getOwnPropertyDescriptor方法可以获取该对象的属性描述对象,描述对象的enumerable竖向称为可枚举性,如果该属性值为false,那么就说明该属性不可枚举,即某些操作或忽略该属性,目前有四个操作会忽略不可枚举的属性。

  • for...in循环:只遍历对象自身的和继承的可枚举的属性。
  • Object.keys():返回对象自身的所有可枚举的属性的键名。
  • JSON.stringify():只串行化对象自身的可枚举的属性。
  • Object.assign(): 忽略enumerablefalse的属性,只拷贝对象自身的可枚举的属性。

引入可枚举属性的目的就在于让某些属性可以规避某些遍历操作。
由此引发思考,当拷贝对象时,我们如果仅仅使用for...in遍历了对象的可枚举属性,那么不可枚举属性就会被遗漏,那么对象拷贝就变得不严谨,所以我使用Object.getOwnPropertyNames方法来替代```for...in``直接遍历对象:

function deepCopy(obj) {
  if (obj instanceof Date) { return new Date(obj) }
  if (obj instanceof RegExp) { return new RegExp(obj)}  
  let result = new obj.__proto__.constructor()  
  for (let key of Object.getOwnPropertyNames(obg) {
    if (obj.hasOwnProperty(key) && obj[key] !== obj) { 
      if (typeof obj[key] === 'object' && obj[key] !== null) {
        result[key] = deepCopy(obj[key]);
      } else {
        result[key] = obj[key];
      }
    }
  }
  return result;
}

5. super 关键字

ES6 新增了关键字super,指向当前对象的原型对象。

const proto = {
  foo: 'hello'
};

const obj = {
  foo: 'world',
  find() {
    return super.foo;
  }
};

Object.setPrototypeOf(obj, proto);
obj.find() // "hello"

值得注意的是super关键字只能用在对象的方法中,用在其他任何地方都会报错。

// 报错
const obj = {
  foo: super.foo
}

// 报错
const obj = {
  foo: () => super.foo
}

// 报错
const obj = {
  foo: function () {
    return super.foo
  }
}

上面三种super的用法都会报错,因为对于 JavaScript 引擎来说,这里的super都没有用在对象的方法之中。第一种写法是super用在属性里面,第二种和第三种写法是super用在一个函数里面,然后赋值给foo属性。目前,只有对象方法的简写法可以让 JavaScript 引擎确认,定义的是对象的方法。

6. 对象的扩展运算符

之前在数组的扩展中介绍了扩展运算符(...),ES2018将这个运算符引入了对象,因为数组是一种特殊的对象,所以理论上,扩展运算符本就应该应用于对象中。

6.1 使用扩展运算符解构赋值

let obj = {
    name: 'bing',
    age: 23,
    id: 007
}

let {name, ...rest} = obj
name // 'bing'
rest // {age: 23, id: 7}

6.2 使用扩展运算符浅拷贝对象

对象的扩展运算符用于取出参数对象的所有可遍历属性,拷贝到当前对象之中。

let foo = { ...['a', 'b', 'c'] };
foo
// {0: "a", 1: "b", 2: "c"}

如果扩展运算符后面是字符串,它会自动转成一个类似数组的对象,因此返回的不是空对象。

{...'hello'}
// {0: "h", 1: "e", 2: "l", 3: "l", 4: "o"}

跟数组一样,扩展运算符还可以合并两个对象

let ab = { ...a, ...b };
// 等同于
let ab = Object.assign({}, a, b);

如果对象中有重复的键值,那么后面的会覆盖前面的,相当于重复赋值。

let obj1 = {name:'bing'}
let obj2 = {name: 'yan'}
let obj = {...obj1, ...obj2}

obj // {name: "yan"}


参考链接

作者:阮一峰
链接:http://es6.ruanyifeng.com/#docs/destructuring

相关文章

  • 阮一峰ES6教程读书笔记(五)对象的扩展

    1. 属性的简洁表示法 ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法。这样的书写更加简洁。 ...

  • 前端学习资料整理

    JS教程 阮一峰JS教程廖雪峰JS教程MDN JS教程阮一峰ES6教程 Node 从零开始nodejs系列文章Ko...

  • 阮一峰ES6教程读书笔记(一)解构赋值、let和const

    About 读完阮一峰大神ES5教程后自觉获益匪浅,遂拜读其ES6教程。为记录所感所得,打算写《阮一峰ES6教程读...

  • 4.字符串的扩展(学习笔记)

    所有内容基于阮一峰的ECMAScript 6 入门 ES6加强了对Unicode 的支持,并且扩展了字符串对象。 ...

  • Promise

    什么是 Promise 参考阮一峰 ES6教程。 Promise 是一个对象,对象里存储一个状态,这个状态是可以随...

  • 学习资料

    js相关 阮一峰JS教程 阮一峰es6教程 JS原型与闭包 正则表达式 canvas学习 插件库相关 babel ...

  • React学习笔记(7)ES6语法知识

    这两天学习ES6参考大佬的教程,稍微加深自己的理解。阮一峰ES6入门教程

  • ES6数值扩展

    阮一峰大神的ES6数值篇已经写的很好很全,下边贴出链接,然后斗胆写一点自己学习的总结。阮一峰ES6数值扩展我准备从...

  • ES6扩展归纳

    ES6扩展归纳 介绍ES6相比与ES5在原有对象上的扩展,包括字符串、正则、数值、函数、数组、对象等扩展,本文是阮...

  • 资料参考

    sass用法指南--阮一峰ES6入门Flex布局教程Javascript标准参考教程css网格布局

网友评论

      本文标题:阮一峰ES6教程读书笔记(五)对象的扩展

      本文链接:https://www.haomeiwen.com/subject/vgwayctx.html