JS笔记《对象扩展》

102 阅读4分钟

属性的简洁表示

  • ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法。
// 属性简写
const foo = 'bar';
const baz = {foo};
baz // {foo: "bar"}  属性名就是变量名,属性值就是变量值
// 等同于
const baz = {'foo': foo};

// 方法简写
const o = {
  method() {
    return "Hello!";
  }
};
// 等同于
const o = {
  method: function() {
    return "Hello!";
  }
};
  • 简写的对象方法不能用于构造函数,会报错。
const obj = {
  f() {
    this.foo = 'bar';
  }
};

new obj.f() //  obj.f is not a constructor

属性名表达式

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

let lastWord = 'last word';

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

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


// 表达式还可以定义方法名
let obj = {
  ['h' + 'ello']() {
    return 'hi';
  }
};

obj.hello() // hi

super

  • ES6 新增super关键字指向当前对象的原型对象。
const proto = {
  foo: 'hello'
};

const obj = {
  foo: 'world',
  find() {
    return super.foo;  // 返回的是原型对象上的foo属性
  }
};

Object.setPrototypeOf(obj, proto);  // 将obj的原型对象修改为 proto
obj.find() // "hello"
  • super表示原型对象时,只能用在对象方法的简写法之中,其他地方都会报错。
// 报错
const obj = {
  foo: super.foo
}

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

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

// 正确
const obj = {
  foo(){
    super.foo;
  }
}

扩展运算符

  • 用于取出参数对象的所有可遍历属性,拷贝到当前对象之中。
let z = { a: 3, b: 4 };
let n = { ...z };
n // { a: 3, b: 4 }

// 数组也是特殊的对象
let foo = { ...['a', 'b', 'c'] };
foo  // {0: "a", 1: "b", 2: "c"}
  • 扩展运算符可以用于合并两个对象。
let ab = { ...a, ...b };
  • 如果将扩展运算符作为对象赋值必须是最后一个参数,否则会报错。
let { ...x, y, z } = {x: 1, y: 2, a: 3, b: 4};    // 句法错误
let { x, ...y, ...z } = {x: 1, y: 2, a: 3, b: 4}; // 句法错误

let { x, y, ...z } = {x: 1, y: 2, a: 3, b: 4};    // 正确
z // {a: 3, b: 4}

静态方法

Object.is()

  • 用来比较两个值是否严格相等,与严格比较运算符(===)的行为基本一致。
Object.is('foo', 'foo') // true
Object.is({}, {})  // false

+0 === -0  // true
Object.is(+0, -0)  // false 与严格相等的区别
NaN === NaN  // false
Object.is(NaN, NaN) // true  与严格相等的区别

Object.assign()

  • 用于对象的合并,将源对象的所有可枚举、自身属性复制到目标对象。参数一是目标对象,后面的参数都是源对象。
const obj1 = {a: 1};
const obj2 = {b: 2};
const obj3 = {c: 3};

Object.assign(obj1, obj2, obj3);
obj1  // {a: 1, b: 2, c: 3}
  • 如果源对象某个属性的值是对象,那么目标对象拷贝的是这个对象引用浅拷贝
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' } }

常见用法

  • 为对象添加属性。
class Point {
  constructor(x, y) {
    Object.assign(this, {x, y});
  }
}
  • 为对象添加方法。
// 给原型对象添加方法
Object.assign(SomeClass.prototype, {
  someMethod(arg1, arg2) {
    ···
  },
  anotherMethod() {
    ···
  }
});
  • 克隆对象。
// 克隆对象自身值,不包含原型对象的值
function clone(origin){
  return Object.assign({}, origin);
}

// 包含原型对象的值
function clone(origin){
   let originProto = Object.getPrototypeOf(origin);
   return Object.assign(Object.create(originProto), origin);
}
  • 合并多个对象。
const merge = (target, ...sources) => Object.assign(target, ...sources);
  • 为属性指定默认值。
const DEFAULTS = {
  logLevel: 0,
  outputFormat: 'html'
};

function processContent(options) {
  options = Object.assign({}, DEFAULTS, options);
  console.log(options);
}

processContent({logLevel: 1})  // {logLevel: 1, outputFormat: 'html'}
// DEFAULTS是默认值,但如果options有与之同名的属性,则options会覆盖

Object.values()

  • 返回一个数组,成员是参数对象自身的所有可遍历的属性的值。
const obj = { foo: 'bar', baz: 42 };
Object.values(obj)  // ["bar", 42]

Object.entries()

  • 返回一个数组,成员是i参数对象自身的所有可遍历的属性的键值对。
const obj = { foo: 'bar', baz: 42 };
Object.entries(obj)  // [ ["foo", "bar"], ["baz", 42] ]

Object.fromEntries()

  • 此方法是Object.entries的逆操作,用于将一个键值对数组转为对象。
let entries = [['name', '张三'], ['age', 18]];
Object.fromEntries(entries);   // {name: '张三', age: 18}

Object.hasOwn()

  • 用于判断某个属性是否为自身属性。参数一为要判断的对象;参数二为属性名。
const foo = Object.create({ a: 123 });
foo.b = 456;

Object.hasOwn(foo, 'a') // false  a为foo继承的属性
Object.hasOwn(foo, 'b') // true   b为原生的属性
  • 此方法与hasOwnProperty的区别是,对于不继承Object.prototype的对象不会报错,后者是会报错的。
const obj = Object.create(null);

obj.hasOwnProperty('foo') // 报错
Object.hasOwn(obj, 'foo') // false