第七天2019-01-07

碎碎念

最近发现写代码的速度有提升,这说明写业务代码基础都差不多了,接下来就应该深究其内容了,该向代码底层的一些原理进行深入探究了,当然还是得夯实基础。之前看过一点Lodashjs的基础,但是有些关联性太强,没办法一下子联系起来,得慢慢的来看内容。今早上看了js中一个Object.assign()中的一些原理,发现其实并没有想象的那么难,但是手写起来可是非常考验功底,需要真正理解才能去写出浅拷贝的Objecr.assign()。下面来浅谈下。

笔记-Object.assign()–上

  • 描述

    如果目标对象中的属性具有相同的键,则属性将被源中的属性覆盖。后来的源的属性将类似地覆盖早先的属性。
    这里应该讲的是

    的**陷阱**。

    #### 拷贝问题

    ```javascript?linenums
    // 1. 浅拷贝
    let obj1 = { a: 0 , b: { c: 0}}; // 源对象

    let obj2 = Object.assign({}, obj1); // 目标对象
    console.log(JSON.stringify(obj2)); // { a: 0, b: { c: 0}}
    // 2. 改变源对象的属性值,拷贝的值并不会改变
    obj1.a = 1;
    console.log(JSON.stringify(obj1)); // { a: 1, b: { c: 0}} ,
    console.log(JSON.stringify(obj2)); // { a: 0, b: { c: 0}}
    // 3. 修改目标对象的属性
    obj2.a = 2;
    console.log(JSON.stringify(obj1)); // { a: 1, b: { c: 0}}
    console.log(JSON.stringify(obj2)); // { a: 2, b: { c: 0}}
    // 4. 改变了目标对象的值,因为复制了对源对象的引用,对目标对象属性的修改也能改源对象,如何解决这种问题?
    obj2.b.c = 3;
    console.log(JSON.stringify(obj1)); // { a: 1, b: { c: 3}}
    console.log(JSON.stringify(obj2)); // { a: 2, b: { c: 3}}
    // 5. 常用的深拷贝JSON.parse(JSON.stringify()),这个方法也有缺点
    obj1 = { a: 0 , b: { c: 0}};
    let obj3 = JSON.parse(JSON.stringify(obj1));
    obj1.a = 4;
    obj1.b.c = 4;
    console.log(JSON.stringify(obj3)); // { a: 0, b: { c: 0}}

合并对象(常用)

以下代码引自MDN

var o1 = { a: 1 };
var o2 = { b: 2 };
var o3 = { c: 3 };

var obj = Object.assign(o1, o2, o3);
console.log(obj); // { a: 1, b: 2, c: 3 }
console.log(o1); // { a: 1, b: 2, c: 3 }
  • 注意目标对象自身也会改变。

合并具有相同属性的对象

以下代码引自MDN

var o1 = { a: 1, b: 1, c: 1 };
var o2 = { b: 2, c: 2 };
var o3 = { c: 3 };

var obj = Object.assign({}, o1, o2, o3);
console.log(obj); // { a: 1, b: 2, c: 3 }
  • 注意后续参数覆盖问题

拷贝 symbol 类型的属性

  • 描述

    Object.assign 方法只会拷贝源对象自身的并且可枚举的属性到目标对象。该方法使用源对象的[[Get]]和目标对象的[[Set]],所以它会调用相关 getter 和 setter。因此,它分配属性,而不仅仅是复制或定义新的属性。如果合并源包含getter,这可能使其不适合将新属性合并到原型中。为了将属性定义(包括其可枚举性)复制到原型,应使用Object.getOwnPropertyDescriptor()和Object.defineProperty() 。String类型和 Symbol 类型的属性都会被拷贝。

以下代码引自MDN

var o1 = { a: 1 };
var o2 = { [Symbol('foo')]: 2 };

var obj = Object.assign({}, o1, o2);
console.log(obj); // { a : 1, [Symbol("foo")]: 2 } (cf. bug 1207182 on Firefox)
Object.getOwnPropertySymbols(obj); // [Symbol(foo)]

先探究到这里吧

针对深拷贝,需要使用其他方法,因为 Object.assign()拷贝的是属性值。假如源对象的属性值是一个指向对象的引用,它也只拷贝那个引用值。常用的可能是JSON.parse(JSON.stringify()),这个方法也有缺点。

知识扩展-简单对比

  1. Object.assign()
  2. JSON.parse(JSON.stringify())
  • 2,不适合复制循环引用对象,不适合复制对象方法

参考

[1]. Object.assign()–MDN
[2]. JavaScript 中的对象拷贝
–end

文章作者: lmislm
文章链接: http://lmislm.com/2019/01/07/2019-01-07/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 LMISLMのBlog