面试题:null == undefined ?以及object.is()区别

前言:

一、相等(==)和不相等(!=),这两个操作符都会先转换操作数(通常称为强制转型),然后再比较它们的相等性。

在转换不同数据类型时,相等和不相等操作符遵循以下基本规则:(笔试题常考)
1.如果有一个操作数是布尔值,则在比较相等性之前现将其转换为数值-false转换为0,true转换为1;
2.如果有一个操作数是字符串,另一个操作数是数值,在比较相等性之前先将字符串转换为数值;
3.如果一个操作数是对象,另一个操作数不是,则调用对象valueOf( )方法,用得到的基本类型值按照前面的规则进行比较;

这两个操作符( 相等(==)和不相等(!=) )在进行比较时则要遵循下列规则。
1.null和undefined是相等的;(面试考到)
2.要比较相等性之前,不能将 null 和 undefined 转换成其他任何值百度面试,说null转换为布尔值为false,undefined转换为布尔值是false,所以值为true,不对)
虽然==会进行自动类型转换,但比较 null 和 undefined 时,不会将它转换为其他任何值。
3.如果有一个操作数是NaN,则相等操作符(==)返回false,而不相等操作符返回true。
重要提示:如果两个操作数都是NaN,相等操作符(==)也返回false;因为按照规则,NaN不等于NaN
4.如果两个操作数都是对象,则比较它们是不是同一个对象。如果两个操作数都指向同一个对象,则相等操作符返回true,否则,返回false。(面试考到)

二、全等(===)和不全等(==)
两者的区别:不全等转换操作数,进行类型转换(面试考)

记住:null==undefined会返回true,因为它们是类似的值;但null===undefined会返回false,因为它们是不同类型的值。

最近在看《JavaScript高级程序设计》一书,书中讲到相等操作符(==)时说,要比较相等性之前,不能将 null 和 undefined 转换成其他任何值但要记住 null == undefined 会返回 true 。的确,在ECMAScript规范中也是这样定义的,但我认为这样来理解这件事情,似乎有些浮于表面,网上也有很多关于这个问题的文章,下面我希望从一个全新的角度来分析 null 和 undefined 的区别,从而理解两者为何会相等:

Undefined 和 Null 是 Javascript 中两种特殊的原始数据类型(Primary Type),它们都只有一个值,分别对应 undefined 和 null ,这两种不同类型的值,既有着不同的语义和场景,又表现出较为相似的行为:

1、undefined

undefined 的字面意思就是未定义的值,这个值的语义是,希望表示一个变量最原始的状态,而非人为操作的结果 。 这种原始状态会在以下 4 种场景中出现:

【1】声明了一个变量,但没有赋值

var foo;
console.log(foo); //undefined

访问 foo,返回了 undefined,表示这个变量自从声明了以后,就从来没有使用过,也没有定义过任何有效的值,即处于一种原始而不可用的状态。

【2】访问对象上不存在的属性

console.log(Object.foo); // undefined

访问 Object 对象上的 foo 属性,同样也返回 undefined , 表示Object 上不存在或者没有定义名为 “foo” 的属性。

【3】函数定义了形参,但没有传递实参

//函数定义了形参 a
function fn(a) {
    console.log(a); //undefined
}
fn(); //未传递实参

函数 fn 定义了形参 a, 但 fn 被调用时没有传递参数,因此,fn 运行时的参数 a 就是一个原始的、未被赋值的变量。
【4】使用 void 对表达式求值

void 0 ; // undefined
void false; //undefined
void []; //undefined
void null; //undefined
void function fn(){} ; //undefined
```**重点内容**

ECMAScript 明确规定 **void 操作符 对任何表达式求值**都返回 **undefined** ,这和**函数执行操作后没有返回值的作用**是一样的,JavaScript 中的函数都有**返回值**,当没有 return 操作时,就默认返回一个**原始的状态值,这个值就是 undefined**,表明函数的返回值未被定义。

因此,undefined 一般都来自于某个表达式最原始的状态值,不是人为操作的结果。当然,你也可以手动给一个变量赋值 undefined,但这样做没有意义,因为一个变量不赋值就是 undefined 。

**2null** 

null 的字面意思是**空值** ,这个值的语义是,希望表示 一个对象被人为的重置为**空对象**,而非一个变量最原始的状态 。 在内存里的表示就是,**栈中的变量没有指向堆中的内存对象**,即
![这里写图片描述](http://img.blog.csdn.net/20170824210259815?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc2h1aWRpbmFvemhvbmd5YW4=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)

当一个对象被赋值了null 以后,原来的对象在内存中就处于**游离状态**,GC 会择机**回收该对象并释放内存。**因此,如果需要释放某个对象,就将变量设置为 null,即表示该对象已经被清空,目前无效状态。试想一下,如果此处把 null 换成 undefined 会不会感到别扭? 显然语义不通,其操作不能正确的表达其想要的行为。

与 null 相关的另外一个问题需要解释一下:(**面试会考察typeOf的返回值**)




<div class="se-preview-section-delimiter"></div>

typeof null == ‘object’


null 有属于自己的类型 Null,而不属于Object类型,typeof 之所以会判定为 Object 类型,是因为JavaScript **数据类型**在底层都是以**二进制的形式**表示的,二进制的**前三位为 0** 会被 typeof 判断为**对象类型**,而 null 的**二进制位恰好都是 0** ,因此,null 被误判断为 Object 类型。

 - 000 - 对象,数据是对象的应用
 - 1 - 整型,数据是31位带符号整数
 - 010 - 双精度类型,数据是双精度数字
 - 100 - 字符串,数据是字符串
 - 110 - 布尔类型,数据是布尔值
**重点内容**
其实,我们可以通过另一种方法获取 null 的真实类型:




<div class="se-preview-section-delimiter"></div>

Object.prototype.toString.call(null) ; // [object Null]

通过 **Object 原型上的toString() 方法**可以获取到JavaScript 中对象的**真实数据类型**,当然 undefined 类型也可以通过这种方式来获取:





<div class="se-preview-section-delimiter"></div>

Object.prototype.toString.call(undefined) ; // [object Undefined]

**3、相似性**

虽然 undefinednull 的语义和场景不同,但总而言之,它们都表示的是一个**无效的值**。 因此,在JS中对这类值访问属性时,都会得到异常的结果:





<div class="se-preview-section-delimiter"></div>

null.toString(); // Cannot read property ‘toString’ of null
undefined.toString(); // Cannot read property ‘toString’ of undefined

ECMAScript 规范认为,既然 nullundefined 的行为很相似,并且都表示 一个**无效的值**,那么它们所表示的内容也具有相似性,即有




<div class="se-preview-section-delimiter"></div>

undefined == null; //true

不要试图通过**转换数据类型**来解释这个结论,因为:





<div class="se-preview-section-delimiter"></div>

Number(null); // 0
Number(undefined); // NaN

//在比较相等性之前,null 没有被转换为其他类型
null == 0 ; //false

但 === 会返回 false ,因为全等操作 === 在比较相等性的时候,不会主动转换分项的数据类型,而两者又不属于**同一种类型**:




<div class="se-preview-section-delimiter"></div>

undefined === null; //false,类型不相同
undefined !== null; //true, 类型不相同






<div class="se-preview-section-delimiter"></div>

补充object.is()
--
object.is()是ES6新增的,用来比较两个值是否严格相等。它与严格运算符(===)的行为基本一致。
不同之处只有两个:一是+0不等于-0,而是NaN等于自身。





<div class="se-preview-section-delimiter"></div>

+0 === -0 //true
NaN === NaN //false






<div class="se-preview-section-delimiter"></div>

object.is(+0,-0)//false
object.is(NaN,NaN )//true
“`

4、总结

用一句话总结两者的区别就是:undefined 表示一个变量自然的、最原始的状态值,而 null 则表示一个变量被人为的设置为空对象,而不是原始状态。所以,在实际使用过程中,为了保证变量所代表的语义,不要对一个变量显式的赋值 undefined,当需要释放一个对象时,直接赋值为 null 即可。

转自:

作者:一像素
www.cnblogs.com/onepixel/p/7337248.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值