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份内存空间;所以 a==b 为 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
null == null 或者 [] == [] 或者{} == {} 或者alert(1|| 2) 或者alert(1&& 2) 结果及原理的更多相关文章
- 数据库中is null(is not null)与=null(!=null)的区别
在标准SQL语言(ANIS SQL)SQL-92规定的Null值的比较取值结果都为False,既Null=Null取值也是False.NULL在这里是一种未知值,千变万化的变量,不是“空”这一个定值! ...
- unity, Graphics.Blit (null, null, mat,0);
我使用 Graphics.Blit (null, finalRT, mat); 合成出一张finalRT,然后将finalRT用在editor脚本的OnInspector中使用 Graphics.Dr ...
- PHP中的逻辑判断函数empty() isset() is_null() ==NULL ===NULL
1.empty() header("Content-type: text/html; charset=utf-8"); if(!empty($data)){ //empty() 未 ...
- 如何解决数据库中,数字+null=null
如何解决数据库中,数字+null=null 我使用SQLServer,做一个 update 操作,累计一个数.在数据库中,为了方便,数据库中这个字段我设为允许为空,并且设置了默认值为 0 .但是在新增 ...
- SSIS ->> Null & Null Functions
SSIS不支持值为NULL的变量.每种类型的变量都有自己的默认值. 做了一个测试,用一个Execute SQL Task输出一个NULL值给A变量,然后把A变量传到到另外一个Execute SQL T ...
- iOS解析数据判断nil NULL Null的方法
+ (BOOL)isNil:(NSObject*)obj { if (obj == nil || obj == NULL) { return YES; } if ([obj isKindOfClass ...
- Convert.ToString(null) => null
{ string str0 = Convert.ToString(null); Console.WriteLine("0,{0}", str0); if (str0==" ...
- 【编程技巧】alert vs Ext.Msg.alert
alert会阻塞程序的运行. Ext.Msg.alert是异步的,它的调用并不会停止浏览器中代码的执行.
- js 重写alert 兼容iphone使得alert 不带src
<script> window.alert = function(name){ var iframe = document.createElement("IFRAME" ...
随机推荐
- redis zset 介绍
$key = 'key'; //新增 zadd($key,分数,标识) //删除某个标识 zrem($key,标识) //查询某个标识的排名(从0开始的 所有在输出的时候要加一) zrevrank($ ...
- Cocos2d之运行Test项目
| 版权声明:本文为博主原创文章,未经博主允许不得转载. 1. 打开Test项目 路径为 C:\Dev\cocos2d-x-3.8.1\build 2.设定cpp-tests为启动项(当cpp ...
- js基本函数和基本方法
日期时间函数(需要用变量调用): var b = new Date(); //获取当前时间 b.getTime() //获取时间戳 b.getFullYear() //获取年份 b.getMonth( ...
- filter 在CSS用的效果
滤镜说明: Alpha:设置透明层次 blur:创建高速度移动效果,即模糊效果 Chroma:制作专用颜色透明 DropShadow:创建对象的固定影子 FlipH:创建水平镜像图片 FlipV:创建 ...
- Chrome不支持css字体小于12px的解决办法
我们先来看个效果图(chrome下): 从上面的图可以很明显地看出Chrome下css设置字体大小为12px及以下时,显示的都是一样大小,都是默认12px: 那么网上有一个方法就是给当前样式添加Chr ...
- 我的黑苹果之路 9400f + msi b360 mortar + 1050ti
硬件配置: CPU:i5 9400f 主板:微型msi迫击炮B360 内存:威刚 ddr4 8g 2133 *2 显卡:技嘉1050ti 4g 显示器:koiso 4K (使用的dp接口连接,hdmi ...
- KiCAD原理图更换库
KiCAD原理图库更换 将AD的工程文件转换位KiCAD后,打开原理图,系统会自动压缩生成当前工程库,但是这样将原理图复制粘贴到其他地方时,就找不到库了,原理图就会无法显示器件符号,如何将库替换为我们 ...
- QMap的key也可以是一个结构体类吗?
QMap<usbsnvidpid, QVector<QString>> USBVIDPIDTIME; USBVIDPIDTIME.insert(m_vidpidsn, time ...
- grpc协议--客户端构造
由于服务端不在构造,已经构造完成不做构造 gRPC 接口名字为service,proto文件内有定义 1.本目录生成grpc文件 python -m grpc_tools.protoc -I. --p ...
- Linux新建环境变量快速切换到文件夹(export)
如果有一个文件夹目录很深/home/user/aaa/bbb/ccc/ddd/eee/fff/ggg,但是经常要跳转到这个文件夹.一个简单的办法就是给这个文件夹建立一个类似$PATH那样的环境变量,如 ...