js数值类型

anyux / 2024-09-19 / 原文

目录
  • 背景
  • 数字
    • 整型直接量
    • 浮点型直接量
    • JavaScript中的算术运算
    • 二进制浮点数和四舍五入错误
    • 日期和时间

背景

JavaScript的数据类型分为两类,原始类型(primitive type)和对象类(object type)

js中的原始类型包括数字,字符串,布尔值

js中有两个特殊的原始值: null(空)和undefined(未定义).它们代表了各自特殊类型的唯一成员

对象类是属性(property)的集合,每个属性都由"key/value".其中有一个比较特殊的对象----全局对象(global object)

js同样定义了一种特殊对象--数组(array),表示带有编号的有序集合

js还定义了特殊的对象----函数,函数是真值,并且js将它们当作普通对象对待

如果函数用来初始化(使用new运算符)一个新建的对象,则称为构建函数(constructor)

每个构造函数定义了一类(class)对象----由构建函数初始化的对象组成的集合

类可以看作是对象类型的子类型

除了数组和函数外,js定义了其他三种有用的类

代表日期的对象

Date

表示正则表达式

RegExp

错误

Error

js解释器有自己的内存管理机制,可以自动对构建的内存进行垃圾回收(garbage collection).这意味着程序可以按需创建对象,当不再有任何引用指向一个对象,解释器会回收它所占用的资源

假设我们有一个数组 a,其元素可以通过数组本身的方法来操作,而不是通过全局函数来处理

let a = [3, 1, 4, 1, 5, 9];
a.sort();  // 调用数组对象的 sort() 方法
console.log(a);  // 输出: [1, 1, 3, 4, 5, 9]

只有js对象才能拥有方法,数字,字符串,布尔值也可以拥有自己的方法.

js中只有nullundefined无法拥有方法的值

js可以分为拥有方法的类型和不拥有方法的类型
同样可分为可变类型不可变类型

可变类型: 对象,数组 js程序可以更改对象属性值和数组元素值

不可变类型: 数字,布尔值,null,undefined,字符串属于不可变类型

字符串可以看作是由字符组成的数组,但是在js中字符串不可变

js可以自由地进行数据类型转换

js的变量是无类型的,变量可以是任何值,同一个变量可以重复赋予任何值

使用var声明变量,js使用词法作用域

不在任何函数内声明的变量叫做全局变量,在任何js程序中可见

函数内部声明的变量具有函数作用域,并且只在函数内可见

数字

js不区分整数和浮点数,均用浮点数表示

当一个数字出现在js中,称为数字直接量
js支持多种格式的数字直接量,负号是一元求反运算符

整型直接量

在js中,用一个数字序列表示10进制整数

0
3
10000

十六进制是以0x0X为前缀,其后为十六进制数字的直接量

0xff // 15*16 + 15 = 255 (十进制)
0xCAFE911

八进制直接量以数字0开始,其后跟随一个由0~7(包括0和7)之间的数字组成
ECMAScript 6的严格模式下,八进制直接量是禁止的

0377 // 3*64 + 7*8 + 7 = 255 (十进制)

浮点型直接量

浮点型直接量可以含有小数点,它们采用的是传统的实数写法。一个实数由整数部分、小数点和小数部分组成

还可以使用指数记数法表示浮点型直接量,即在实数后跟字母e或E,后面再跟正负号,其后再加一个整型的指数。这种记数方法表示的数值,是由前面的实数乘以10的指数次幂

[digits][.digits][(E|e)[(+|-)]digits]
3.14
2345.789
.333333333333333333
6.02e23          // 6.02×1023
1.4738223E-32 // 1.4738223×10-32

JavaScript中的算术运算

运算符包括加法运算符(+)减法运算符(-)乘法运算符(*)除法运算符(/)和求余(求整除后的余数)运算符(%)

js支持更加复杂的算术运算符,这些复杂运算通过Math对象的属性定义的函数和常量来实现

const x = 5;
const y = 6;
const z = 7;

console.log(Math.pow(2, 53));           // => 9007199254740992: 2 的 53次幂
console.log(Math.round(.6));           // => 1.0: 四舍五入
console.log(Math.ceil(.6));            // => 1.0: 向上求整
console.log(Math.floor(.6));           // => 0.0: 向下求整
console.log(Math.abs(-5));             // => 5: 求绝对值
console.log(Math.max(x, y, z));        // 返回最大值
console.log(Math.min(x, y, z));        // 返回最小值
console.log(Math.random());            // 生成一个大于等于0小于1.0的伪随机数
console.log(Math.PI);                  // π: 圆周率
console.log(Math.E);                   // e: 自然对数的底数
console.log(Math.sqrt(3));             // 3的平方根
console.log(Math.pow(3, 1 / 3));       // 3的立方根
console.log(Math.sin(0));              // 三角函数: 还有Math.cos, Math.atan等
console.log(Math.log(10));             // 10的自然对数
console.log(Math.log(100) / Math.LN10); // 以10为底100的对数
console.log(Math.log(512) / Math.LN2); // 以2为底512的对数
console.log(Math.exp(3));              // e的三次幂

js中的算术运算符在溢出(overflow),下溢(underflow)被零整除时不会报错.

当数字结果超过了js所能表示的数字上限(溢出),结果为一个特殊的无穷大(infinity)值,在js中Infinity表示

当数字结果起过js所能表示的负数上限(溢出),结果为负为无穷大,在js中-Infinity表示

无穷大值的行为特性为: 基于它们的加,减,乘,除运算结果还是无穷大

下溢(underflow)是当运算结果无限接近零并比js所能表示的最小值还小的时候发生的一种情形.此时js返回0

当一个负数发生下溢时,js返回一个特殊的值"负零"

被零整除在js中并不报错:它只是简单的返回无穷大(Infinity)或负无穷大(-Infinity).

但有一个例外,零除以零是没有意义的,这咱整除运算结果也是一个非数字(not-a-number)值,用NaN表示.

无穷大除以无穷大,给任意负数作开方运算或者算术运算符与不是数字或无法转换为数字的操作数一起使用时都将返回NaN

js 预定义了全局变量InfinityNaN,用来表示正无穷大和非数字值.在ECMAScript 3中,这两个值是可读,可写的,并可修改

ECMAScript 5修正了这个错误,将它们定义为只读

ECMAScript 3中Number对象定义的属性值也只是只读的

console.log(Infinity); // 将一个可读/写的变量初始化为infinity
console.log(Number.POSITIVE_INFINITY); // 同样的值,只读
console.log(1/0); // 这也是同样的值
console.log(Number.MAX_VALUE + 1); // 计算结果还是Infinity
console.log(Number.NEGATIVE_INFINITY); // 该表达式表示了负无穷大
console.log(-Infinity);
console.log(-1/0);
console.log(-Number.MAX_VALUE - 1);
console.log(NaN); // 将一个可读/写的变量初始化为NaN
console.log(Number.NaN); // 同样的值,但是只读
console.log(0/0); // 计算结果是NaN
console.log(Number.MIN_VALUE/2); // 发生下溢:计算结果为0
console.log(-Number.MIN_VALUE/2); // 负零
console.log(-1/Infinity); // 同样是负零
console.log(-0); // 打印其输出结果

js中的 NaN与任何值都不相等,包括自己
也就是无法判断NaN是否为NaN
就当使用x != x来判断,当且仅当xNaN时,表达式的结果为true
函数isNaN()的作用与此类似,如果参数是NaN或非数字值(比如字符串和对象),则返回true

js中有一个类似的函数isFinite(),在参数不是NaN,Infinity,-Infinity的时候返回true

负零值同样有些特殊,它和正零值是相等的(使用js严格相等测试来判断).这意味着这两个值几乎一模一样,除了作为除数之外

var zero = 0;            // 正常的零值
var negz = -0;           // 负零值
console.log(zero === negz);            // => true: 正零值和负零值相等
console.log(1/zero === 1/negz);        // => false: 正无穷大和负无穷大不等

二进制浮点数和四舍五入错误

js浮点数的形式只能是表示其中有限的个数
数字不能精确表述会带来一些问题

var x = .3 - .2;                 // 30美分减去20美分
var y = .2 - .1;                 // 20美分减去10美分
console.log(x == y);             // => false: 两值不相等!
console.log(x == .1);            // => false: .3-.2 不等于 .1
console.log(y == .1);            // => true: .2-.1 等于 .1

由于误差,0.3和0.2之间的近似值实际并不是0.1
需要理解的是: 在任何用二进制浮点数的编程语言中都会有这个问题

日期和时间

js语言核心包括Date()函数,用来创建日期和时间的对象
这些日期对象的方法为日期计算简单的api

var then = new Date(2011, 0, 1); // 2011年1月1日
var later = new Date(2011, 0, 1, 17, 10, 30); // 同一天, 当地时间5:10:30pm
var now = new Date(); // 当前日期和时间
var elapsed = now - then; // 日期减法:计算时间间隔的毫秒数

console.log(later.getFullYear()); // => 2011
console.log(later.getMonth()); // => 0: 从0开始计数的月份
console.log(later.getDate()); // => 1: 从1开始计数的天数
console.log(later.getDay()); // => 5: 得到星期几,0代表星期日,5代表星期一
console.log(later.getHours()); // => 当地时间17: 5pm
console.log(later.getUTCHours()); // 使用UTC表示小时的时间,基于时区