zoukankan      html  css  js  c++  java
  • 对象的深拷贝

    常见深拷贝

    JSON系列化

    JSON.parse(JSON.stringify())的确是一种很简单易用的方式呢,可惜的是,JSON是一个很有原则的男人,他可不会对你言听计从。在遇到不安全的JSON值会自动将其忽略,在数组中则会返回null(以保证单元位置不变)。

    不安全的 JSON 值: undefined 、 function 、 symbol (ES6+)和包含循环引用(对象之间相互引用,形成一个无限循环)的 对象 都不符合 JSON 结构标准,支持 JSON 的语言无法处理它们

    递归

    上一篇讲浅拷贝的时候,我们在开始引入了一个浅拷贝的例子,现在我们把它改成一件简单的深拷贝。

    function deepCopy (obj) {
      if (typeof obj !== 'object') {
        return
      }
      var newObj = obj instanceof Array ? [] : {}
      for (var key in obj) {
        if (obj.hasOwnProperty(key)) {
          newObj[key] = typeof obj[key] === 'object' ? deepCopy(obj[key]) : obj[key]
        }
      }
      return newObj
    }
    

    好像也还不错,简单易懂还能用,一般的场景的确是一种不错的方法呢,但是,今天我们来看看不一般的场景。

    我们先来挑挑毛病:

    • function类型没有处理(大概,或许,应该是真的没必要吧,下面我也并不打算讨论这货,有兴趣的去看看callapplybind
    • 循环引用
    • 类型判断用typeofinstanceof靠谱吗?(特别注意typeof null的坑)
    • 数组?[]:{},这么简单?不存在的

    循环引用

    上面多处说到了循环引用的问题,我们先来看看什么是循环引用:

    var a = {value: b}
    var b = {value: a}
    

    是的,就是这么一个反人类的存在,但是却是我们不能忽略的一个大问题。我们是应该返回空呢、undefined呢,还是它的引用,还是什么呢?好像没有标准答案呢,嗯,那就Follow Your Heart吧!

    类型判断

    思考一下:

    typeof null  // "object"
    null instanceof Object  // false
    

    进行类型判断是无可避免的,然而我们似乎并没有什么完美的方式得到我们需要的类型,我们先来看看几种常用的方式:

    • typeof: 返回一个表达式的数据类型的字符串,返回结果为js基本的数据类型,包括number,boolean,string,object,undefined,function,symbol
    • instanceof: 判断一个对象是否为某一数据类型,或一个变量是否为一个对象的实例;返回boolean类型。内建类型只有通过构造器才能用instanceof
    • constructor: 是每一个实例对象都拥有的属性,而这个属性也相当于是一个指针,它指向于创建当前对象的对象
    • Object.prototype.toString.call(obj).slice(8,-1): 返回的是类名

    typeof的问题就很明显了:

    typeof null  // "object"
    typeof function () {}  // "function"
    typeof []  // "object"
    

    instanceof考虑一下多全局对象(多个frame或多个window之间的交互),在浏览器中,我们的脚本可能需要在多个窗口之间进行交互。多个窗口意味着多个全局环境,不同的全局环境拥有不同的全局对象,从而拥有不同的内置类型构造函数。这可能会引发一些问题。比如,表达式 [] instanceof window.frames[0].Array 会返回false,因为 Array.prototype !== window.frames[0].Array.prototype

    constructor属性得到的仅仅是构造函数,而且是可以被手动更改的,constructor.name只是返回的构造函数的名字,它并不返回类名。

    Object.prototype.toString.call算是比较公认靠谱的方法了吧,然而,它同样有可能被人为仿造,鸭子类型嘛,但它还是比较安全的方式。

    鸭子类型: "如果它走起路来像鸭子,叫起来也是鸭子,那么它就是鸭子"。动态类型的语言倾向于你让它做什么它就是什么


    作者:Alvin_Liu
    链接:https://juejin.im/post/5a77ef85f265da4e8700a773
    来源:掘金
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
  • 相关阅读:
    实现镜面模糊效果
    在网页中单行以及多行内容超出之后隐藏
    利用xhsell登录到远程腾讯云服务器
    highcharts饼状图使用案例
    在利用xampp开发时候为apache设置多个项目目录
    Linux查找命令
    数字签名与数字证书
    数据库之闭包,范式
    利用PHP绘图函数实现简单验证码功能
    IC基础(二):设计中常见的时序问题
  • 原文地址:https://www.cnblogs.com/woniubushinide/p/8431754.html
Copyright © 2011-2022 走看看