zoukankan      html  css  js  c++  java
  • null == null 或者 [] == [] 或者{} == {} 或者alert(1|| 2) 或者alert(1&& 2) 结果及原理

    相信面试的小伙伴们都会遇到此头大的问题,是不是很想骂一句面试官:你白痴啊,鬼都用不着的东西拿来问,你还别说,这些看似用不着的东西却包含着最基础的原理,那我们来理一理。

    1.alert(1||2)和 alert(1&& 2)

    话不多说,实践是检验真理的唯一标准

    非0 即true ,|| 是一真为真,即弹出1;

    alert(1&& 2)结果为什么弹个2 呢?
    1)只要 ‘&&’ 前面是false ,无论 ‘&&’ 后面是true 还是false,结果都返回 ‘&&’前面的值
    2)只要 ‘&&’前面是true ,无论 ‘&&’ 后面是true 还是false ,结果返回 ‘&&’后面的值。
    如果实在记不住,就跟|| 运算相反好了。!(一真为真 ) 为&& 结果。

    2. null == null 或者 [] == [] 或者{} == {} ?

    结果是 null == null true ; [] == [] 或者{} == {} false;

    先来了解两个概念:栈 stack 和 堆 heap
    栈(stack):1) 先进后出; 2) 自动分配内存空间,3) 由系统自动释放;4) 使用的是一级缓存,他们通常都是被调用时处于存储空间中,调用完立即释放。
    堆(heap):队列优先,1) 先进先出;2) 动态分配内存,大小不定也不会自动释放;3)存放在二级缓存中,生命周期由虚拟机的垃圾回收算法来决定;一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收。
    基本类型:存放在栈内存中的简单数据段,数据大小确定,内存空间大小可以分配。
    Undefined / Null / Boolean / Number / String,它们是直接按值存放的,可以直接访问
    当我们需要访问引用数据类型 (对象 / 数组 / 函数) 的值时,首先从栈中获得该对象的地址指针,然后再从堆内存中取得所需的数据。
    变量a实际保存的是指向堆内存中对象的一个指针,而b保存的是指向堆内存中另一个对象的一个指针;虽然这两个对象的值是一样的,但它们是独立的2个对象,占了2份内存空间;所以 ab 为 false。
    如果 var a = {}; var b = a; 这时变量b复制了变量a保存的指针,它们都指向堆内存中同一个对象;所以 a
    b 为 true。
    到这里问题已经解决了,但我们需要深入学习一下;

    3. 传值与传址?

    基本类型与引用类型最大的区别实际就是 传值与传址的区别。
    var a = [1,2,3,4,5];
    var b = a;
    var c = a[0];
    console.log(b); // [1,2,3,4,5]
    console.log(c); // 1
    b[4] = 6;
    c = 7;
    console.log(a[4]); //6
    console.log(a[0]); //1
    从上面代码可以得知,当改变b中的数据时,a也发生了变化;但是当我们改变c的数值时,a却没有发生改变。
    这就是传值与传址的区别。因为a是数组,属于引用类型,所以a给b传的是栈中的地址,而不是堆内存中的对象。而c仅仅是从a堆内存中获取的一个数值,并保存在栈中。所以b修改的时候,会根据地址回到a堆内存中修改;c则直接在栈中修改,并且不能指向a堆内存中

    4. 浅拷贝

    var a = {name: 'zyj'};
    function Copy(q) {
    var m = {};
    for(var i in q) {
    m[i] = q[i];
    }
    return m;
    }
    a.hobby = ['reading', 'coffee'];
    var b = Copy(a);
    b.age = 18;
    console.log(b.name); //zyj
    console.log(b.hobby); //['reading', 'coffee']
    console.log(b.age); //18
    console.log(a.age); //undefined
    a对象中的name属性值为字符串,hobby为数组。a拷贝到b,两个属性均能顺利拷贝。 给b对象新增一个number类型的属性age时,b能够正常修改,而a中无定义。说明 子对象 b 的 age 并没有关联到 父对象 a 中,所以为undefined。
    b.hobby.push('dancing');
    console.log(b.hobby); //['reading', 'coffee', 'dancing']
    console.log(a.hobby); //['reading', 'coffee', 'dancing']
    原因是 age的值属于基本类型,所以拷贝的时候传递的是该数据值;但hobby的值是堆内存中的对象,所以hobby在拷贝的时候传递的是指向hobby对象的地址,无论复制多少hobby,其值始终是指向父对象的hobby对象的内存空间。

    5. 深拷贝

    在实际编码中,我们不希望父子对象之间产生关联,这时就用到深拷贝。既然属性值类型是数组或对象时只会传址,那么就可以用递归来解决这个问题,把父对象中所有属于对象的属性类型遍历赋给子对象即可。代码如下:

    var a = {name: 'zyj'};
    function Copy(q, m) {
    var m = m || {};
    for(var i in q) {
    if(typeof q[i] === 'object') {
    m[i] = (q[i].constructor === Array)?[]:{};
    Copy(q[i], m[i]);
    }else {
    m[i] = q[i];
    }
    }
    return m;
    }
    a.hobby = ['reading', 'coffee'];
    var b = {};
    b = Copy(a, b);
    b.hobby.push('dancing');
    console.log(b.hobby); //['reading', 'coffee', 'dancing']
    console.log(a.hobby); //['reading', 'coffee']
    修改b子对象的hobby数组时,没有使a父对象中的hobby数组新增一个值,即子对象没有影响到父对象a中的hobby

  • 相关阅读:
    ZZZZ
    linux expect, spawn用法小记
    小议common lisp程序开发流程
    解决编译apache出现的问题:configure: error: APR not found . Please read the documentation
    SMART原则_百度百科
    心态不够青春,所以身上的技术也容易衰老
    What is tradebit?
    About VirtualBoxImages.com
    ssh-copy-id -i ~/.ssh/id_rsa.pub admin@172.17.42.66
    香港mtmit真皮休闲商务双用时尚浮点手拿包1018 烟灰色-大号 均码【图片 价格 品牌 报价】-京东商城
  • 原文地址:https://www.cnblogs.com/panax/p/10549685.html
Copyright © 2011-2022 走看看