0

0

深入了解JS中的原始类型(primitive type)

青灯夜游

青灯夜游

发布时间:2021-02-02 18:01:44

|

3386人浏览过

|

来源于OSCHINA

转载

深入了解JS中的原始类型(primitive type)

JavaScript中的原始类型(primitive type)包括Undefined、Null、Number、Boolean和String,其他变量均为引用类型,也就是Object Type。原始类型保存位置是“栈内存”,而引用类型保存在“堆内存”中,但通常JavaScript中对变量的使用,并不十分关心变量在内存中的位置。

“typeof”操作符用以获取变量的值的数据类型。typeof可以接受变量名或字面量值作为操作数,返回一个描述变量类型信息的字符串。需要注意的是,typeof的返回值与JavaScript中的类型并不是一一对应的:

  • “undefined” ——变量值未定义

  • “number” ——变量值是数值

  • “boolean” ——变量值是布尔值

  • “string” ——变量值是字符串

  • “object” ——变量值是对象或者null

  • “function” ——变量值是函数

另外,typeof是一个像(+,-)一样的操作符,而不是函数,虽然形如“typeof(12)”的用法不会产生错误,但对于操作符来说“typeof 12”才是合适的使用方法。

1、undefined和null

Undefined Type在ECMA-262文档中的定义是:

The Undefined type has exactly one value, called undefined. Any variable that has not been assigned a value has the value undefined.

Undefined类型只有一个唯一的值“undefined”,变量的值为undefined意味着变量没有被初始化。对于尚未使用var声明的变量,使用它会产生错误,但使用typeof操作符会返回“undefined”:

var foo;
alert(foo);        // undefined
alert(bar);        // 错误
alert(typeof foo); // undefined
alert(typeof bar); // undefined

undefined被实现为一个全局变量(而不是像null一样的字面值),它的值是“未定义”。在ECMAScript 3中,undefined可以被赋予其它值,在ECMAScript 5中已被修正为只读的。

Null Type 也只有一个值null,用来表示“空值”。多数编程语言中的都有类似null、nil等用来表示空值的字面量。但与其他编程语言不同的是,JavaScript并不使用null表示未初始化的变量的值(由undefined表示)。

null的逻辑意义是表示一个空对象指针。JavaScript中通常意义的对象并不包括简单数据类型,所以逻辑上null表示变量指向了一个空值的Object类型(不是字面量“{}”)。

出于这个原因,便可理解为什么使用typeof操作符获取null值的类型会得到“object”了。JavaScript里null值对Object类型的意义,类似于0对Number类型,“”对于String类型。

undefined和null都用来描述“空值”,但在逻辑意义上,undefined比null要更为“底层”一些。一般情况下,不需要显示的把变量值指定为undefined。

而对于一个意在保存Object但还没有真正指向一个对象的变量,则应该把变量值设置为null,体现null作为空对象指针的作用并且与undefined区分开来。

2、数值

ECMAScript使用了简化的数字模型。它只有一个数字类型Number,而没有分离出单独的整数类型。在实现上,Number类型采用了IEEE 754标准定义的64位双精度浮点数格式。

64位的浮点数格式中,52位用来表示尾数,11位表示指数,1位符号。因此在表示整数时,JavaScript能够表示的整数范围在-Math.pow(2,53)和Math.pow(2,53)之间,超过这个范围,低位数字的精度便无法保证了。

var n = Math.pow(2,53); // 9007199254740992
alert(n === n + 1);     // true, 9007199254740992 + 1得到的值还是9007199254740992

在实际的Web开发中,若需要在后台(如Java)传递一个Long Int类型给Javascript处理,很可能JavaScript把JSON数据解析为Number类型后,得到的结果并不是你想要的:它的后面几位数字发生了变化。

JavaScript使用浮点数值进行运算,因此小数部分会出现精度问题,这跟所有其他采用IEEE 754标准格式表示浮点数的编程语言一样。避免在代码中出现对小数部分的相等判断。(整数部分是精确的)

var a = 0.1;
var b = 0.2;
alert(a + b === 0.3); // false

如果数值超过了JavaScript所能表示数字上限(overflow),将被自动转换为一个代表无穷大的Infinity(或-Infinity,负无穷)值;如果数值无限接近0并且超过JavaScript表示范围(underflow),将被设置为0(或-0,同0)。JavaScript不会出现溢出错误(包括被零整除的时候)。

MyMap AI
MyMap AI

使用AI将想法转化为图表

下载
var a = Number.MAX_VALUE * 2;          //Infinity
var b = Number.MIN_VALUE / 2;          //0
var c = 1 / 0;                         //Infinity or NaN, 依JS执行环境不同
var d = 0 / 0;                         // NaN

Number类型定义了一个特殊的值NaN,即not-a-number。NaN的意义代表一个本该得到数值的地方没有得到任何数值。任何使用NaN做操作数的算术运算,都会得到NaN。

另外NaN也是唯一一个使用对自身进行相等判断会得到false的数值。NaN的这个怪异之处破坏了JavaScript运算符的对称性。如果在代码中需要通过比较数值大小进行分支判断,就需要注意可能出现NaN的情况,因为使用NaN与其他数值进行大小比较总会得到false,而这可能不是你想要的结果。

var a = 10;   
a = a - "not number"         // NaN
alert(a === a);             // false
var b = 12 + a;              // NaN
var c = 10;
alert(b >= c || b < c);      // false

另一个Number类型中不常引人注目的地方是位运算。JavaScript中提供了按位操作运算符。在很多其他编程语言中,按位操作可以进行硬件级处理,所以非常快。

但是JavaScript没有整数类型,它的位操作是先把数值转换为32位整数,然后进行计算,然后再转换回去,JavaScript绝大部分运行环境是在浏览器中,与硬件相隔较远,因此位操作执行很慢。

3、字符串

与很多其他编程语言中一样,JavaScript中的字符串值也是不可变的,改变一个字符串变量的值,相当于重新生成了一个字符串并把它赋值给变量。JavaScript中的简单类型无法进行方法调用(作为this调用函数),但我们还是可以进行诸如

"abcdefg".toUpperCase();

这样的操作。这是因为JavaScript为简单数据类型提供了一种方式,把它们包装为对象类型,然后进行方法调用。”"abcdefg"“先被隐式地包装为对象,然后使用包装出的对象调用toUpperCase方法,待方法调用结束后,JavaScript再隐式地把包装对象回收。

其它简单数据类型也使用同样的方式。也可以使用JavaScript提供的构造函数显示地创建包装对象,JavaScript提供了String()、Number()和Boolean()三个构造函数,分别用于构建String、Number和Boolean类型的包装对象。

4、类型转换

ECMA-262中对数据类型的转换有详细的定义,很多JavaScript的参考资料也会列出类型转换的详细规则,这里就不再赘述了,下面只讨论一些值得注意的问题。

JavaScript有两组相等比较运算符:”===“和”!==“、”==“和”!=“。Crockford在著作《JavaScript:The Good Parts》里面列举的Bad Parts中的第一个就是”==“运算符。

原因在于”==“运算符会执行隐式的类型转换,而JavaScript中类型转换的规则又非常复杂,很容易导致代码中出现不易发现的bug。与”===“和其他编程语言中的”==“不同,JavaScript中的”==“运算符并不具备传递性: ∀x∀y∀z(x == y ∧ y == z → x == z)并不成立:

"" == "0";             // false
"" == 0;               // true
"0" == 0;              // true

Crockford和Zakas都建议不要使用“==”运算符,而使用“===”代替。若不遵循这个建议,使用“==”运算符时,请务必确保你明确知道两个比较变量的类型信息,以免发生预料之外的类型转换。

另外一个经常用到类型转换的地方是分支判断。if(和其它)语句并不要求进行分支判断的表达式结果必须为Boolean类型,而会根据特定的规则把判断表达式的结果转换为true或false后再进行判断。

if (obj !== undefined && obj !== null) {
    // code
}

// 上面的判断条件可以替换为

if (obj) {
    // code
}

上面代码中的obj代表一个对象变量,若其值为undefined或null,则被转换为false,反之转换为true。这种方式并不完全安全,若使用的变量是简单数据类型,就需要注意一些特殊值的转换规则,否则代码可能不会按照预想的方式执行。

if (typeof num === "number" && num) { 
    // if num is 0, get false
    //code
}

上面代码的本意是获取一个有效的数值类型,屏蔽了其他类型和num的值为NaN的情况(NaN会转换false)。但代码中有一个纰漏,它忽略了num值为0的情况。

0值会被转换为false,从而导致下面的代码不会被执行,这可能与编码者的本意相违背。同样使用String类型作为分支条件,也要考虑""会被自动转换为false的情况。

与分支判断中的类型转换相似的情况,是采用短路方式为变量赋值。由于JavaScript中”&&“和”||“操作符的特性,我们经常采用短路方式为变量赋值。

”&&“操作符会返回表达式中第一个可以转换为false的操作数或最后一个操作数(全为true时);”||“操作符返回表达式中第一个可以转换为true的操作数或最后一个操作数(全为false时)。

var obj = obj1 || obj2 || {}; 
var attr = obj && pro && attr;

与分支判断一样,需要警惕表达式中可能出现的特殊值:0,"",null等。

JavaScript的类型模型,提供了极大的灵活性的同时也带来了很多陷阱,编码过程中需要小心地规避这些陷阱,因为代码审查很容易忽略它们,出现问题时,它们也往往很难被发现。

更多计算机编程相关知识,请访问:编程入门!!

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
go语言 注释编码
go语言 注释编码

本专题整合了go语言注释、注释规范等等内容,阅读专题下面的文章了解更多详细内容。

2

2026.01.31

go语言 math包
go语言 math包

本专题整合了go语言math包相关内容,阅读专题下面的文章了解更多详细内容。

1

2026.01.31

go语言输入函数
go语言输入函数

本专题整合了go语言输入相关教程内容,阅读专题下面的文章了解更多详细内容。

1

2026.01.31

golang 循环遍历
golang 循环遍历

本专题整合了golang循环遍历相关教程,阅读专题下面的文章了解更多详细内容。

0

2026.01.31

Golang人工智能合集
Golang人工智能合集

本专题整合了Golang人工智能相关内容,阅读专题下面的文章了解更多详细内容。

1

2026.01.31

2026赚钱平台入口大全
2026赚钱平台入口大全

2026年最新赚钱平台入口汇总,涵盖任务众包、内容创作、电商运营、技能变现等多类正规渠道,助你轻松开启副业增收之路。阅读专题下面的文章了解更多详细内容。

76

2026.01.31

高干文在线阅读网站大全
高干文在线阅读网站大全

汇集热门1v1高干文免费阅读资源,涵盖都市言情、京味大院、军旅高干等经典题材,情节紧凑、人物鲜明。阅读专题下面的文章了解更多详细内容。

73

2026.01.31

无需付费的漫画app大全
无需付费的漫画app大全

想找真正免费又无套路的漫画App?本合集精选多款永久免费、资源丰富、无广告干扰的优质漫画应用,涵盖国漫、日漫、韩漫及经典老番,满足各类阅读需求。阅读专题下面的文章了解更多详细内容。

67

2026.01.31

漫画免费在线观看地址大全
漫画免费在线观看地址大全

想找免费又资源丰富的漫画网站?本合集精选2025-2026年热门平台,涵盖国漫、日漫、韩漫等多类型作品,支持高清流畅阅读与离线缓存。阅读专题下面的文章了解更多详细内容。

19

2026.01.31

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
React 教程
React 教程

共58课时 | 4.4万人学习

TypeScript 教程
TypeScript 教程

共19课时 | 2.6万人学习

Bootstrap 5教程
Bootstrap 5教程

共46课时 | 3.1万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号