天天看点

走进javascript——类型

ecmascript语言类型对应于使用ecmascript语言的ecmascript程序员直接操作的值。ecmascript语言类型有以下几种undefined,null,boolean,string,symbol,number和object。ecmascript语言值是以ecmascript语言类型为特征的值。

如果你奇怪为什么这里没有写function类型,并且把null也当做一种类型,建议你看一下hax在知乎上的一个回答javascript 里 function 也算一种基本类型?

简单说:按照规范,typeof只是一个运算符,其返回值并不能作为js类型系统的依据。

摘录在网上看到的一段话:

我听到很多次人们声称`typeof null =='object''是某种意图,表示'null'应该是一个“空对象引用”值,他们进一步使用当前的“任何对象价值”的措辞来支持这种说法。我相信这是非常不准确的,至少就js今天而言,正如brendan eich自己所说的那样,'typeof null =='object'只是一个错误,而不是一个有意的功能或者如何使用它的信号。

mdn上这样说:

在 javascript 最初的实现中,javascript 中的值是由一个表示类型的标签和实际数据值表示的。对象的类型标签是0。由于 null 代表的是空指针(大多数平台下值为0x00),因此,null的类型标签也成为了0,typeof null就错误的返回了"object"

关于null == ‘object’的更多信息,你可以去看看the history of “typeof null”这篇文章。译文 typeof null的前世今生

恩,它是es6新增的啦,主要用来解决命名冲突,如果你感兴趣可以看一下下面这篇文章。

js的第七种基本类型symbols

用instanceof来判断对象类型多少有些不合适,因为instanceof是用来判断某个对象的原型链是否存在于某个构造函数的prototype上的,因原型链这一层关系导致部分情况下用instanceof来判断对象类型就变得不是那么准确了,比如判断数组的类型。

走进javascript——类型

导致这个原因是因为所有对象都继承至object.prototype,当然,通过object.create(null)方式创建对象,原型是不会指向object.prototype的。

这里推荐一篇关于instanceof的文章javascript instanceof 运算符深入剖析

mdn上是这样说的:

返回一个指向创建了该对象原型的函数引用。需要注意的是,该属性的值是那个函数本身,而不是一个包含函数名称的字符串。对于原始值(如1,true 或 "test"),该属性为只读。

将这句话翻译成代码就是这样:

而这个fn.prototype.constructor就是指向fn本身,因而有些人就想着通过constructor来判断某个对象的类型,如下图

走进javascript——类型

看起来通过constructor来判断对象类型是个不错的方法,更重要的是还能判断自定义对象类型。

虽然说通过constructor来判断对象类型是一个方案,但这种方法并不是总正确的,主要还是因为这个constructor指向的是构造函数prototype.constructor属性,而这个值我们是可以手动更改的,如下面这样:

我们手动将fn.prototype指向一个新对象,它的执行结果如下:

如果你实在是想用constructor来判断对象类型,那么在像上面那种情况时,你可以这样去做:

走进javascript——类型

我们来看一下规范是怎么定义这个tostring方法的

​ tostring转换

输入类型

结果

undefined

"undefined"

null

"null"

boolean

如果参数是 true,那么结果为 "true"。如果参数是 false,那么结果为 "false"。

number

结果等于输入的参数(不转换)。

string

参见下文的文法和注释。

object

应用下列步骤:调用 toprimitive( 输入参数 , 暗示 字符串类型)。调用 tostring(result(1))。返回 result(2)。

话说规范写的有些苦涩哈,我们还是看一下mdn上怎么说的吧

每个对象都有一个 tostring() 方法,当对象被表示为文本值时或者当以期望字符串的方式引用对象时,该方法被自动调用。默认情况下,tostring() 方法被每个继承自object的对象继承。如果此方法在自定义对象中未被覆盖,tostring() 返回 "[object type]",其中type是对象类型。

也就是说当我们调用object中的tostring方法时,它会返回"[object type]"这么个东西,但问题是像number、boolean、string类型的值它们都是有自己的tostring方法的,因此我们必须借用object中的tostring方法,也就是用call、apply或bind方法。

mdn对null的解释是:

null是一个 javascript 字面量,表示空值(null or an "empty" value),即没有对象被呈现(no object value is present)。它是 javascript 原始值 之一。

再来看看undefined

undefined是全局对象的一个属性。也就是说,它是全局作用域的一个变量。undefined的最初值就是原始数据类型undefined。 一个没有被赋值的变量是undefined类型。一个方法或者是语句如果在执行期间没有变量被赋值也会返回undefined,一个函数如果没有返回值,就会返回一个undefined值。

undefined和null的不同点

null是一个字面量(而不是全局对象的一个属性,undefined 是)。在 apis 中,null 常被放在期望一个对象,但是不引用任何对象的参数位置。当检测 null 或 undefined 时,注意相等()与全等(=)两个操作符的区别 (前者会执行类型转换)。

在使用上还有一个区别就是,我们可以将一个对象赋值为null,从而告诉垃圾回收器这个对象可以回收了,那么为什么不将对象赋值为undefined呢?我觉得undefined本身就是一个值,而null才是真的没有,如果你对此不太理解,可以看一下下面这个链接 w3c上说的“可以通过将变量的值设置为 null 来清空变量”中的清理变量有什么特别意思吗?

在aimingoo的一篇文章中他是这样说的:无废话javascript(上)

hax: 大哥你好像漏了null。。。 aimingoo: null是object,所以不必单独提出来讲。我记得我曾经问到过你关于null和undefined的问题,你说在邮件列表中对这个问题讨论得很多,但无有答案。其实我后来想明白了,js中有两套类型体系,各有一个“无”的概值。基本的6种类型中,undefined表示无;对象系统中,null表示无。 例如,dom是基于对象系统的,所以适宜于用null来填写attribute中的无值;而var声明的无值变量,由于是基于基本类型系统,所以适宜于用undefined。 当然,也可以直接说js内部以及语言级别或引擎级别用undefined,而js外部或扩展用null。这个与上面大概相同,但思考角度有异。

主要还是因为隐式转换导致的。

null是一个表示"无"的对象,转为数值时为0;undefined是一个表示"无"的原始值,转为数值时为nan。

undefined与null的区别

探索javascript中null和undefined的深渊

我们知道如果使用一个未定义的变量是会报错的,但是用typeof判断一个未定义的变量是不会报错的,我觉得这也合理,因为typeof只是用来判断,而不是去操作。

---------- 2017-05-07更新 -----------------

object number function boolean underfind symbol

当程序知道它所要处理的数据的类型之后,能够降低存储空间总量,并且能提高访问速度.例如:可以使用4个字节的计算机存储器量来存放数值243787452.如果将相同的数值存储为字符,则会占涌9个存储器量。

不同的数据需要的方法也会不同,如果只有一种数据类型那么问题就大了。

当将数据分成不同的类型以后,有时又会有需求,将一种数据类型转换成另外一种数据类型,甚至有时是不需要区分数据类型。

强制类型转换

转数字:parseint number parsefloat

转字符串:tofixed toprecision toexponential tostring json.stringify join

转布尔:boolean

转对象:jsos.parse

转数组:split

数字转数组 string.prototype.split.call(1123,null);

隐式类型转换

转数字:- * / % ~ +var -var math.ceil math.floor math.abs math系列

转字符串:+

将js中的值赋值给所有和dom相关的内容,都会自动转换成字符串。

转布尔:! isnan 所有和判断相关

js中为什么要有隐式转换

js在ecmascript3出现之前是没有异常处理的。这就可以解释为什么这门语言为什么如此频繁的自动强制 转换而且出错的时候总是那么沉默,是因为它从一开始就没有抛出异常。

继续阅读