Review a JS method every day - the Object.assign method on the first day

1.Description Object.assign_

Object.assign()Method copies all enumerable ( Object.propertyIsEnumerable()returns true) own ( Object.hasOwnProperty()returns true) properties from one or more source objects to the target object, returning the modified object

1.1 Grammar

Object.assign(target, ...sources) // 返回合并后的target的对象
  • target

The target object, the object that receives the properties of the source object, is also the modified return value

  • source

The source object containing the properties to be merged.

2.Application Object.assign_

2.1 Basic example

let target = {
    
     a: 1 };
let source = {
    
     b: 1, c: 1 };
const final = Object.assign(target, source);
console.log(final); // {a: 1, b: 1, c: 1}

// 我们输出target 看看
console.log(target); // {a: 1, b: 1, c: 1}

It is found that the target object has also changed. How to avoid this? deep copy

let target = {
    
     a: 1 };
let source = {
    
     b: 1, c: 1 };
const final = Object.assign(JSON.parse(JSON.stringify(target)), source);
console.log(final);// {a: 1, b: 1, c: 1}

console.log(target);// {a: 1} 这样就不会改变target了

2.2 When the same attributes exist in the merged objects

// 一个 source 时
let target = {
    
     a: 1 };
let source = {
    
     a: 100, b: 1, c: 1 };
const final = Object.assign(target, source);
console.log(final); // {a: 100, b: 1, c: 1}

// 两个source 时
let target = {
    
     a: 1 };
let source = {
    
     a: 100, b: 1, c: 1 };
let source1 = {
    
     c: 100, d: 1 };
const final = Object.assign(target, source, source1);
console.log(final); // {a: 100, b: 1, c: 100, d: 1}

It can be found that the properties will be overwritten by other objects with the same properties in subsequent parameters.

2.3 Assignment reference problem

let source = {
    
    
    a: 1,
    b: {
    
    
        c: 1,
    },
};
const final = Object.assign({
    
    }, source);
console.log(final); // { a: 1, b: { c: 1 } }
console.log(source);// { a: 1, b: { c: 1 } }

source.a = 2;
console.log(final);// { a: 1, b: { c: 1 } }  不变
console.log(source);// { a: 2, b: { c: 1 } } 变了

source.b.c = 2;
console.log(final); // { a: 1, b: { c: 2 } }  变了
console.log(source);// { a: 2, b: { c: 2 } }  变了

It can be found that the source object is a reference to an object, and it only copies its reference value. If the source object embeds an object and its value is changed in the source object, the merged value will also change.

How to avoid it? JSON.parse(JSON.stringify(Object.assign({}, source))Just adopt it

2.4 Exceptions will interrupt subsequent copy tasks

let target = Object.defineProperty({
    
    }, 'a', {
    
    
	value: 1,
	writable: false, // 不可写
});
try {
    
    
	Object.assign(target, {
    
     b: 1 }, {
    
     a: 3 }, {
    
     c: 1 });
} catch (e) {
    
    
	console.log(e);
}
console.log(target.b); // 1
console.log(target.a); // 1
console.log(target.c); // undefined

If an error occurs during assignment, for example if the property is not writable, this will be thrown TypeError; if any properties were added before the exception was thrown, targetthe object will be modified

2.5 Object.assign()will not throw an error when sourcethe object value is nullorundefined

const final = Object.assign({
    
    }, {
    
     a: 1 }, undefined, {
    
     b: 1 }, null);
console.log(final); // {a: 1, b: 1}

2.6 Properties and non-enumerable properties on the prototype chain cannot be copied

//摘自MDN
const obj = Object.create(
	{
    
     foo: 1 },
	{
    
    
	// foo 在obj的原型链上
	bar: {
    
    
		value: 2, // bar 是一个不可枚举属性
	},
	baz: {
    
    
		value: 3,
		enumerable: true, // baz 是一个枚举属性
		},
	}
);

const copy = Object.assign({
    
    }, obj);
console.log(copy); // { baz: 3 }

2.7 Basic types will be packaged as objects

const obj = Object.assign({
    
    }, 'happy');
console.log(obj); // {0: 'h', 1: 'a', 2: 'p', 3: 'p', 4: 'y'}

const obj = Object.assign({
    
    }, 'happy', 'good', true, 10);
console.log(obj); // {0: 'g', 1: 'o', 2: 'o', 3: 'd', 4: 'y'} 注意与上面输出的前四个区别

Note: Only strings can have their own enumerable properties.

2.8 Copy accessor

// 摘自MDN
const obj = {
    
    
  foo: 1,
  get bar() {
    
    
    return 2;
  }
};

let copy = Object.assign({
    
    }, obj);
console.log(copy); // { foo: 1, bar: 2 }

// 这是一个复制完整描述符的赋值函数
function completeAssign(target, ...sources) {
    
    
  sources.forEach(source => {
    
    
    let descriptors = Object.keys(source).reduce((descriptors, key) => {
    
    
      descriptors[key] = Object.getOwnPropertyDescriptor(source, key);
      return descriptors;
    }, {
    
    });

    // 默认情况下,对象,也分配可枚举符号的副本
    Object.getOwnPropertySymbols(source).forEach(sym => {
    
    
      let descriptor = Object.getOwnPropertyDescriptor(source, sym);
      if (descriptor.enumerable) {
    
    
        descriptors[sym] = descriptor;
      }
    });
    Object.defineProperties(target, descriptors);
  });
  return target;
}

copy = completeAssign({
    
    }, obj);
console.log(copy); // { foo:1, get bar() { return 2 } }

3. Ending

Refer to
the first day of MDN to review a JS method every day: Object.assign method

Guess you like

Origin blog.csdn.net/News777/article/details/127106288