对象扩展

作者: 好奇男孩 | 来源:发表于2018-05-13 03:00 被阅读23次

ES6 允许直接写入变量和函数,作为对象的属性和方法

属性简写

var name = 'xiaohui’'
var age = 3
var people = {name, age} //{name:'xiaohui', age:3}
function f(x, y) {
  return {x, y};
}

// 等同于

function f(x, y) {
  return {x: x, y: y};
}

f(1, 2) // Object {x: 1, y: 2}

方法简写

let app = {
selector: '#app',
init function(){
},
bind function(){
}
}
app.init()
let app = {
selector: '#app',
init() {
},
bind() {
}
}
app.init()

某个方法的值是一个 Generator 函数,前面需要加上星号

const obj = {
  * m() {
    yield 'hello world';
  }
};

定义对象的属性: 可把表达式放在方括号内。

ES6 允许字面量定义对象时,用(表达式)作为对象的属性名,即把表达式放在方括号内。

let propKey = 'foo';

let obj = {
  [propKey]: true,
  ['a' + 'bc']: 123
};

函数的name属性,返回函数名

const person = {
  sayName() {
    console.log('hello!');
  },
};

person.sayName.name   // "sayName"
  • bind方法创造的函数,name属性返回bound加上原函数的名字;
  • Function构造函数创造的函数,name属性返回anonymous。
  • 如果对象的方法是一个 Symbol 值,那么name属性返回的是这个 Symbol 值的描述。
(new Function()).name // "anonymous"

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

const key1 = Symbol('description');
const key2 = Symbol();
let obj = {
  [key1]() {},
  [key2]() {},
};
obj[key1].name // "[description]"
obj[key2].name // ""

Object.is

它用来比较两个值是否严格相等,与严格比较运算符(===)的行为基本一致

Object.is('foo', 'foo')
// true
Object.is({}, {})
// false

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

+0 === -0 //true
NaN === NaN // false

Object.is(+0, -0) // false
Object.is(NaN, NaN) // true

Object.assign

用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target)

const target = { a: 1 };

const source1 = { b: 2 };
const source2 = { c: 3 };

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

若参数不是对象,则会先转成对象,然后返回

undefined和null无法转成对象,所以如果它们作为参数,就会报错

typeof Object.assign(5) // "object"
Object.assign(undefined) // 报错
Object.assign(null) // 报错

其他类型的值(即数值、字符串和布尔值)不在首参数,也不会报错。但是,除了字符串会以数组形式,其他类型不会合并,这是因为只有字符串的包装对象,会产生可枚举属性。

const v1 = 'abc';
const v2 = true;
const v3 = 10;

const obj = Object.assign({}, v1, v2, v3);
console.log(obj); // { "0": "a", "1": "b", "2": "c" }

注意

Object.assign方法实行的是浅拷贝,而不是深拷贝。

也就是说,如果源对象某个属性的值是对象,那么目标对象拷贝得到的是这个对象的引用

const obj1 = {a: {b: 1}};
const obj2 = Object.assign({}, obj1);

obj1.a.b = 2;
obj2.a.b // 2

同名属性的替换

const target = { a: { b: 'c', d: 'e' } }
const source = { a: { b: 'hello' } }
Object.assign(target, source)
// { a: { b: 'hello' } }

可以用来处理数组,但是会把数组视为对象

Object.assign([1, 2, 3], [4, 5])
// [4, 5, 3]

如果要复制的值是一个取值函数,那么将求值后再复制。

const source = {
  get foo() { return 1 }
};
const target = {};

Object.assign(target, source)
// { foo: 1 }

所有 Class 的原型的方法都是不可枚举的

for...in会返回继承的属性,操作中引入继承的属性会让问题复杂化,大多数时候,我们只关心对象自身的属性。所以,尽量不要用for...in循环,而用Object.keys()代替。

proto属性

Object.setPrototypeOf()(写操作)、Object.getPrototypeOf()(读操作)、Object.create()(生成操作)

super 关键字

我们知道,this关键字总是指向函数所在的当前对象,ES6 又新增了另一个类似的关键字super,指向当前对象的原型对象

const proto = {
  foo: 'hello'
};

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

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

ES5 引入了Object.keys方法,返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键名。

Object.values

返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键值。

const obj = { foo: 'bar', baz: 42 };
Object.values(obj)
// ["bar", 42]

Object.values会过滤属性名为 Symbol 值的属性

Object.entries

返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键值对数组

const obj = { foo: 'bar', baz: 42 };
Object.entries(obj)
// [ ["foo", "bar"], ["baz", 42] ]

原对象的属性名是一个 Symbol 值,该属性会被忽略。

for...of 循环

一个数据结构只要部署了Symbol.iterator属性,就被视为具有 iterator 接口,就可以用for...of循环遍历它的成员。也就是说,for...of循环内部调用的是数据结构的Symbol.iterator方法。

for...of循环可以使用的范围包括数组、Set 和 Map 结构、某些类似数组的对象(比如arguments对象、DOM NodeList 对象)、 Generator 对象,以及字符串。

注意

对于普通的对象,for...of结构不能直接使用,会报错,必须部署了 Iterator 接口后才能使用

对象的扩展运算符

  • 解构赋值
let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
x // 1
y // 2
z // { a: 3, b: 4 }
  • 由于解构赋值要求等号右边是一个对象,所以如果等号右边是undefined或null,就会报错,因为它们无法转为对象
  • 解构赋值必须是最后一个参数,否则会报错。
  • 解构赋值的拷贝是浅拷贝

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

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

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

深拷贝

// 写法一
const clone1 = {
  __proto__: Object.getPrototypeOf(obj),
  ...obj
};

// 写法二
const clone2 = Object.assign(
  Object.create(Object.getPrototypeOf(obj)),
  obj
);

// 写法三
const clone3 = Object.create(
  Object.getPrototypeOf(obj),
  Object.getOwnPropertyDescriptors(obj

合并两个对象

let ab = { ...a, ...b };
// 等同于
let ab = Object.assign({}, a, b);
  • 如果用户自定义的属性,放在扩展运算符后面,则扩展运算符内部的同名属性会被覆盖掉。
  • 如果把自定义属性放在扩展运算符前面,就变成了设置新对象的默认属性值
  • 如果扩展运算符后面是一个空对象,则没有任何效果。
  • 如果扩展运算符的参数是null或undefined,这两个值会被忽略,不会报错

相关文章

  • JQuery插件

    类扩展: 对象扩展:

  • 对象扩展

    ES6 允许直接写入变量和函数,作为对象的属性和方法 属性简写 方法简写 某个方法的值是一个 Generator ...

  • 对象扩展

    Object.is(v1, v2) 判断2个数据是否完全相等 Object.assign(target, sour...

  • 对象扩展

    简洁表示## 属性: 方法: 属性表达式## [a]取变量a的值 Object.is## Object.assig...

  • 对象扩展

    1.方法也可以简写 ES6 允许字面量定义对象时,用方法二(表达式)作为对象的属性名,即把表达式放在方括号内 Ob...

  • 对象扩展

    1. 创建对象 1.1 通过对象字面量的形式创建对象 1.2 通过new Object()创建对象 1.3 通过构...

  • 《ECMAScript 6 入门》笔记

    变量的解构赋值 字符串的扩展 正则的扩展 数值的扩展 函数的扩展 数组的扩展 对象的扩展 对象的新增方法 表单验证...

  • 解构赋值,函数扩展默认值

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

  • ES6扩展

    字符串的扩展正则的扩展数值的扩展数组的扩展函数的扩展对象的扩展

  • ES6之扩展运算符-对象

    Spread扩展运算符 (1) 复制对象(深拷贝) 拷贝了对象实例的属性对象的扩展运算符(...)用于取出参数对象...

网友评论

    本文标题:对象扩展

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