zoukankan      html  css  js  c++  java
  • 由js深拷贝引起的对内存空间的一些思考

    数据类型

    js常用数据类型分为基本类型和引用类型

    • 基本类型:null、undefined、数值型、字符串型、布尔型
    • 引用类型:数组、对象

    内存空间

    var a = [1, 2, 3];
    var b = a;
    b[2] = 4;
    a;  // ??

    我们都知道结果是[1, 2, 4],因为b和a指向了同一个引用对象所以都可以改变该对象的值,我们用内存空间来深入理解一下。

    我们知道在内存中存在两块区域,一个是栈stack,一个是堆heap。 通常我们的基本数据类型存储在栈中,而我们的引用数据类型存于堆中。栈中会有一个指针指向存在于堆中的数据以便于引用。

    var arr = [1, 2, 3];

    内存图应该是这样:

    arr是一个基本类型的变量,该变量内部存储着数组的地址/指针,通过该地址可以找到存在于heap中的Array对象。通常我们说arr是一个引用类型我觉得是不严谨的,应该说:变量arr指向一个引用类型。

    这时候会出现一个问题:允许两个指针指向同一个堆数据,这意味着通过其中一个指针篡改了数值那么会影响另一个指针。

    var a = [1, 2, 3];
    var b = a;

    以上变量在内存中的图是这样的:

    解决该问题的方法就是重新在heap中创建一个与a指向的引用对象一模一样的对象,然后让b指向它,
    像这样:
    这样一个b改变了就不会影响a了。

    说个题外话:了解这一机制对理解prototype是有很大好处的

    function Person(name) {
        this.name = name;
    }
    Person.prototype = {
        sayHi() {
            console.log("hi, " + this.name);
        }
    };
    
    var p1 = new Person('lan');
    p1.sayHi();  // 'hi, lan'

    内存图如下,可以自己理解一下,找一找哪些存在于stack哪些存在于heap:

    接上述,直接将a赋值为b这样为浅拷贝,而上上图中则为深拷贝。

    js实现深拷贝思路:

    • 先判断所赋值的类型,如果为基本类型则直接拷贝,若为对象类型则在heap中重新生成一个对象,再递归的将值赋值过去。
    function deepCopy(obj) {
        var result = '';
        
        // 为基本类型
        if(obj == null || obj == undefined || typeof obj != 'object')
            return obj;
    
        // 为引用类型,判断为数组还是为对象
        if(obj instanceof Array) 
            result = [];
        else 
            result = {};  
    
        for(var key in obj) {
            var current = obj[key];
            if(current == null || current == undefined || typeof current != 'object')
                result[key] = current;
            else
                // 不直接调用deepCopy而用arguments.callee
                // 以避免函数被赋值给其他变量而出现错误
                result[key] = arguments.callee(current); 
         }
    
         return result;
    }
    
    var a = {
        name: 'lan',
        age: 20,
        birth: [1,2,3,4],
        like: {
            food: 'fruit',
            color: ['pink', 'blue']
        }
    };
    
    var b = deepCopy(a);
    b.birth[2] = 5;
    a.birth;  // [1, 2, 3, 4]

    以上为自己对于指针的一点思考,欢迎指正与扩展。

  • 相关阅读:
    哈尔滨理工大学第六届程序设计团队 H-Permutation
    哈尔滨理工大学第六届程序设计团队 E-Mod
    哈尔滨理工大学第六届程序设计团队 I-Team
    HDU Today
    最短路
    Pseudoforest(伪最大生成树)
    Connect the Cities(prim)用prim都可能超时,交了20几发卡时过的
    Jungle Roads(最小生成树)
    linux读取yaml文件的某个属性值
    dos查看电脑配置
  • 原文地址:https://www.cnblogs.com/wind-lanyan/p/8533885.html
Copyright © 2011-2022 走看看