热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

JS的类型和值

1.类型ECMAScript语言中所有的值都有一个对应的语言类型。ECMAScript语言类型包括Undefined、Null、Boolean、String、Number和Obje

1.类型



ECMAScript语言中所有的值都有一个对应的语言类型。ECMAScript语言类型包括Undefined、Null、Boolean、String、Number和Object。

对语言引擎和开发人员来说,类型是值的内部特征,它定义了值的行为,以使其区别于其他值。



内置类型


Javascript有七种内置类型:



  • 空值(null)

  • 未定义(undefined)

  • 布尔值(boolean)

  • 数字(number)

  • 字符串(string)

  • 对象(object)

  • 符号(symbol,ES6中新增)


除了对象之外,其他统称为“基本类型”。


我们可以用typeof运算符来查看值的类型,它返回的是类型的字符串值。


typeof undefined === "undefined";//true
typeof true === "boolean";//true
typeof 42 === "number";//true
typeof "42" === "string";//true
typeof {life:42} === "object";//true

typeof Symbol() === "symbol";//true

//下面是一个bug
typeof null === "object";//true

typeof function a(){ /*...*/ } === "function";//true

Javascript中的变量是没有类型的。只有值才有。变量可以随时持有任何类型的值。

在对变量执行typeof操作时,得到的结果并不是该变量的类型,而是该变量持有的值的类型,因为Javascript中的变量没有类型。


var a = 42;
typeof a;//"number"

a = true;
typeof a;//"boolean"

//因为typeof 42返回"number"
typeof typeof 42;//"string"

2.值


2.1 数组


在Javascript中,数组可以容纳任何类型的值,可以是字符串、数字、对象(object),甚至是其他数组。


var a = [1,"2",[3]];

a.length;//3
a[0] === 1;//true
a[2][0] === 3;//true

对数组声明后即可向其中加入值,不需要预先设定大小。


var a = [];

a.length;//0

a[0] = 1;
a[1] = "2";
a[2] = [3];

a.length;//3

使用delete运算符可以将单元从数组中删除,但是要注意,单元删除后,数组的length属性并不会发生变化。


var a = [];

a[0] = 1;
a[2] = [3];

a[1];//undefined

a.length;//3

数组通过数字进行索引,但有趣的是它们也是对象,所以也可以包含字符串键值和属性,但这些并不计算在数组长度内:


var a = [];

a[0] = 1;
a["foobar"] = 2;

a.length;//1
a["foobar"];//2
a.foobar;//2

如果字符串键值能够被强制类型转换为十进制数字的话,它就会被当作数字索引来处理。


var a = [];

a["13"] = 42;

a.length;//14

建议使用对象来存放键值/属性值,用数组来存放数字索引值。


2.2 字符串


Javascript中的字符串和字符数组并不是一回事。


var a = "foo";
var b = ["f","o","o"];

a.length;//3
b.length;//3

a.indexOf("o");//1
b.indexOf("o");//1

a;//"foo"
b;//["f","o","o"]

a[1] = "0";
b[1] = "0";

a;//"foo"
b;//["f","0","o"]

Javascript中字符串是不可变的,而数组是可变的。

a[1]在Javascript中并非总是合法语法,正确的方法应该是a.charAt(1)

字符串不可变是指字符串的成员函数不会改变其原始值,而是创建并返回一个新的字符串。


许多数组函数用来处理字符串很方便(字符串没有这些函数)。


var a = "foo";
var b = ["f","o","o"];

a.join;//undefined
a.map;//undefined

var c = Array.prototype.join.call(a,"-");
var d = Array.prototype.map.call(a,function(v){
return v.toUpperCase() + ".";
}).join("");

c;//"f-o-o"
d;//"F.O.O."

2.3 数字


number(数字),包括"整数"和带小数的十进制数。


数字的语法


var a = 0.42;
var b = .42;
var c = 42.0;
var d = 42.;

特别大的特别小的数字默认用指数格式显示。


var a = 5E10;
a;//50000000000
a.toExponential();//"5e+10"

var b = a*a;
b;//2.5e+21

var c = 1/a;
c;//2e-11

var a = 42.59;

a.toFixed(0);//43
a.toFixed(1);//42.6
a.toFixed(2);//42.59
a.toFixed(3);//42.590
a.toFixed(4);//42.5900

a.toPrecision(1);//4e+1
a.toPrecision(2);//43
a.toPrecision(3);//42.6
a.toPrecision(4);//42.59

技术分享图片


但是下面的语法是有效的(请注意其中的空格):

技术分享图片


2.4 特殊数值


undefined类型只有一个值,即undefined。null类型也只有一个值,即null

null指空值。

undefined指没有值。

null是一个特殊关键字,不是标识符,我们不能将其当作变量来使用和赋值。

undefined是一个标识符,可以被当作变量来使用和赋值。


我们通过void运算符即可得到undefined这个值。


var a = 42;

console.log(void a, a);//undefined 42

按惯例我们用void 0来获得undefined。void 0、void 1和undefined之间并没有实质上的区别。


特殊的数字


如果数学运算的操作数不是数字类型,就无法返回一个有效的数字,这种情况下返回值为NaN


var a = 2/"foo";//NaN

typeof a === "number";//true

NaN仍然是数字类型。

NaN用于指出数字类型中的错误情况,即“执行数学运算没有成功,这是失败后返回的结果”。


var a = 2/"foo";

a == NaN;//false
a === NaN;//false

NaN是一个特殊值,它和自身不相等,是唯一一个非自反的值。

可以使用内建的全局工具函数isNaN(..)来判断一个值是否是NaN。

NaN是Javascript中唯一一个不等于自身的值。


if(!Number.isNaN){
Number.isNaN = function(n){
return n != n;
};
}

无穷数

var a = 1/0;//Infinity
var b = -1/0;//-Infinity

Javascript的运算结果有可能溢出。

规范规定,如果数学运算的结果超出处理范围,则由IEEE754规范中的“就近取整”模式来决定最后结果。

计算结果一旦溢出为无穷数就无法再得到有穷数。换句话说,就是你可以从有穷走向无穷,但无法从无穷回到有穷。

无穷除以无穷(Infinity/ Infinity)是一个未定义操作,结果为NaN


零值

var a = 0/-3;//-0
var b = 0*-3;//-0

加法和减法运算不会得到负零。

根据规范,对负零进行字符串化会返回"0":


var a = 0/-3;
a.toString();//"0"
a + "";//"0"
String(a);//"0"
JSON.stringify(a);//"0"
+"-0";//-0
Number("-0");//-0
JSON.parse("-0");//-0

var a = 0;
var b = 0/-3;

a == b;//true
-0 == 0;//true
a === b;//true
-0 === 0;//true

//区分-0和0
function isNegZero(n){
n = Number(n);
return (n === 0)&&(1/n === -Infinity);
}

isNegZero(-0);//true
isNegZero(0/-3);//true
isNegZero(0);//false

特殊的等式


ES6中新加入了一个工具方法Object.is(..)来判断两个值是否绝对相等。


var a = 2/"foo";
var b = -3*0;

Object.is(a,NaN);//true
Object.is(b,-0);//true

Object.is(b,0);//false

能使用=====时就尽量不要使用Object.is(..),因为前者效率更高,更为通用。Object.is(..)主要用来处理那些特殊的相等比较。


2.5 值和引用


var a = 2;
var b = a;//b是a的值的一个副本
b++;
a;//2
b;//3

var c = [1,2,3];
var d = c;//d是[1,2,3]的一个引用
c;//[1,2,3,4]
d;//[1,2,3,4]

简单值总是通过值复制的方式来赋值/传递,包括null、undefined、字符串、数字、布尔和ES6中的symbol。

复合值——对象(包括数组和封装对象)和函数,则总是通过引用复制的方式来赋值/传递。


var a = [1,2,3];
var b = a;
a;//[1,2,3]
b;//[1,2,3]

b = [4,5,6]
a;//[1,2,3]
b;//[4,5,6]

//由于引用指向的是值本身而非变量,所以一个引用无法更改另一个引用的指向。

function foo(x){
x.push(4);
x;//[1,2,3,4]

x = [4,5,6];
x.push(7);
x;//[4,5,6,7]
}

var a = [1,2,3];

foo(a);
a;//[1,2,3,4]

//我们不能通过引用x来更改引用a的指向,只能更改a和x共同指向的值。

function foo(x){
x.push(4);
x;//[1,2,3,4]

x.length = 0;
x.push(4,5,6,7);
x;//[4,5,6,7]
}

var a = [1,2,3];

foo(a);
a;//[4,5,6,7]

/*
function foo(wrapper){
wrapper.a = 42;
}

var obj = {
a : 2
};

foo(obj);
obj.a;//42
*/

/*
function foo(x){
x = x + 1;
x;//3
}

var a = 2;
var b = new Number(a);//Object(a)也一样

foo(b);
console.log(b);//2
*/

我们无法自行决定使用值复制还是引用复制,一切由值的类型来决定。


参考资料:《你不知道的Javascript》(中卷) 第一部分 前两章

JS的类型和值



推荐阅读
  • 1:有如下一段程序:packagea.b.c;publicclassTest{privatestaticinti0;publicintgetNext(){return ... [详细]
  • 深入理解Cookie与Session会话管理
    本文详细介绍了如何通过HTTP响应和请求处理浏览器的Cookie信息,以及如何创建、设置和管理Cookie。同时探讨了会话跟踪技术中的Session机制,解释其原理及应用场景。 ... [详细]
  • 本文详细介绍了Akka中的BackoffSupervisor机制,探讨其在处理持久化失败和Actor重启时的应用。通过具体示例,展示了如何配置和使用BackoffSupervisor以实现更细粒度的异常处理。 ... [详细]
  • 本文介绍如何通过Windows批处理脚本定期检查并重启Java应用程序,确保其持续稳定运行。脚本每30分钟检查一次,并在需要时重启Java程序。同时,它会将任务结果发送到Redis。 ... [详细]
  • 本文探讨了如何通过最小生成树(MST)来计算严格次小生成树。在处理过程中,需特别注意所有边权重相等的情况,以避免错误。我们首先构建最小生成树,然后枚举每条非树边,检查其是否能形成更优的次小生成树。 ... [详细]
  • QUIC协议:快速UDP互联网连接
    QUIC(Quick UDP Internet Connections)是谷歌开发的一种旨在提高网络性能和安全性的传输层协议。它基于UDP,并结合了TLS级别的安全性,提供了更高效、更可靠的互联网通信方式。 ... [详细]
  • 深入理解OAuth认证机制
    本文介绍了OAuth认证协议的核心概念及其工作原理。OAuth是一种开放标准,旨在为第三方应用提供安全的用户资源访问授权,同时确保用户的账户信息(如用户名和密码)不会暴露给第三方。 ... [详细]
  • Windows服务与数据库交互问题解析
    本文探讨了在Windows 10(64位)环境下开发的Windows服务,旨在定期向本地MS SQL Server (v.11)插入记录。尽管服务已成功安装并运行,但记录并未正确插入。我们将详细分析可能的原因及解决方案。 ... [详细]
  • Explore a common issue encountered when implementing an OAuth 1.0a API, specifically the inability to encode null objects and how to resolve it. ... [详细]
  • Java 中的 BigDecimal pow()方法,示例 ... [详细]
  • 深入解析Spring Cloud Ribbon负载均衡机制
    本文详细介绍了Spring Cloud中的Ribbon组件如何实现服务调用的负载均衡。通过分析其工作原理、源码结构及配置方式,帮助读者理解Ribbon在分布式系统中的重要作用。 ... [详细]
  • 理解存储器的层次结构有助于程序员优化程序性能,通过合理安排数据在不同层级的存储位置,提升CPU的数据访问速度。本文详细探讨了静态随机访问存储器(SRAM)和动态随机访问存储器(DRAM)的工作原理及其应用场景,并介绍了存储器模块中的数据存取过程及局部性原理。 ... [详细]
  • 几何画板展示电场线与等势面的交互关系
    几何画板是一款功能强大的物理教学软件,具备丰富的绘图和度量工具。它不仅能够模拟物理实验过程,还能通过定量分析揭示物理现象背后的规律,尤其适用于难以在实际实验中展示的内容。本文将介绍如何使用几何画板演示电场线与等势面之间的关系。 ... [详细]
  • MySQL中枚举类型的所有可能值获取方法
    本文介绍了一种在MySQL数据库中查询枚举(ENUM)类型字段所有可能取值的方法,帮助开发者更好地理解和利用这一数据类型。 ... [详细]
  • 在使用 DataGridView 时,如果在当前单元格中输入内容但光标未移开,点击保存按钮后,输入的内容可能无法保存。只有当光标离开单元格后,才能成功保存数据。本文将探讨如何通过调用 DataGridView 的内置方法解决此问题。 ... [详细]
author-avatar
万源佳威5
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有