1-JS-数据类型-原始类型方法、数字类型

原始类型的方法

我们来看看原始类型和对象之间的关键区别。

一个原始值:

  • 是原始类型中的一种值。
  • 在 JavaScript 中有 7 种原始类型:stringnumberbigintbooleansymbolnullundefined

一个对象:

  • 能够存储多个值作为属性。

  • 可以使用大括号 {} 创建对象,例如:{name: "John", age: 30}。JavaScript 中还有其他种类的对象,例如函数就是对象。

关于对象的最好的事儿之一是,我们可以把一个函数作为对象的属性存储到对象中。

let john = {
  name: "John",
  sayHi: function() {
    alert("Hi buddy!");
  }
};

john.sayHi(); // Hi buddy!
当作对象的原始类型
let str = "Hello";

alert( str.toUpperCase() ); // HELLO

//
let n = 1.23456;

alert( n.toFixed(2) ); // 1.23

**注意:**构造器 String/Number/Boolean 仅供内部使用

像 Java 这样的一些语言允许我们使用 new Number(1)new Boolean(false) 等语法,明确地为原始类型创建“对象包装器”。

在 JavaScript 中,由于历史原因,这也是可以的,但极其 不推荐。因为这样会出问题。

例如:

alert( typeof 0 ); // "number"

alert( typeof new Number(0) ); // "object"!

//对象在 if 语句中始终为真,因此此处的 alert 将显示
let zero = new Number(0);

if (zero) { // zero 为 true,因为它是一个对象
  alert( "zero is truthy?!?" );
}

null/undefined 没有任何方法

特殊的原始类型 nullundefined 是例外。它们没有对应的“对象包装器”,也没有提供任何方法。从某种意义上说,它们是“最原始的”。

尝试访问这种值的属性会导致错误:

alert(null.test); //error
数字类型

在现代 JavaScript 中,数字(number)有两种类型:

  1. JavaScript 中的常规数字以 64 位的格式 IEEE-754 存储,也被称为“双精度浮点数”。这是我们大多数时候所使用的数字,我们将在本章中学习它们。
  2. BigInt 数字,用于表示任意长度的整数。有时会需要它们,因为常规数字不能超过 253 或小于 -253。由于仅在少数特殊领域才会用到 BigInt,因此我们在特殊的章节 BigInt 中对其进行了介绍。
编写数字的更多方法

在 JS 中,我们可以通过在数字后面附加字母 “e”,并指定零的数量来缩短数字:

let billion = 1e9;  // 10 亿,字面意思:数字 1 后面跟 9 个 0

alert( 7.3e9 );  // 73 亿(7,300,000,000)

//1e3 = 1 * 1000
//1.23e6 = 1.23 * 1000000

let ms = 1e-6; // 1 的左边有 6 个 0

// -3 除以 1 后面跟着 3 个 0 的数字
1e-3 = 1 / 1000 (=0.001)

// -6 除以 1 后面跟着 6 个 0 的数字
1.23e-6 = 1.23 / 1000000 (=0.00000123)
十六进制,二进制和八进制数字
alert( 0xff ); // 255
alert( 0xFF ); // 255(一样,大小写没影响)


//二进制和八进制数字系统很少使用,但也支持使用 0b 和 0o 前缀:
let a = 0b11111111; // 二进制形式的 255
let b = 0o377; // 八进制形式的 255

alert( a == b ); // true,两边是相同的数字,都是 255
toString(base)

方法 num.toString(base) 返回在给定 base 进制数字系统中 num 的字符串表示形式。

let num = 255;

alert( num.toString(16) );  // ff
alert( num.toString(2) );   // 11111111

base 的范围可以从 2 到 36。默认情况下是 10。

举例:

  • base=16 用于十六进制颜色,字符编码等,数字可以是 0..9A..F
  • base=2 主要用于调试按位操作,数字可以是 01
  • base=36 是最大进制,数字可以是 0..9A..Z。所有拉丁字母都被用于了表示数字。对于 36 进制来说,一个有趣且有用的例子是,当我们需要将一个较长的数字标识符转换成较短的时候,例如做一个短的 URL。可以简单地使用基数为 36 的数字系统表示:
alert( 123456..toString(36) ); // 2n9c

注意:使用两个点来调用一个方法

请注意 123456..toString(36) 中的两个点不是打错了。如果我们想直接在一个数字上调用一个方法,比如上面例子中的 toString,那么我们需要在它后面放置两个点 ..

如果我们放置一个点:123456.toString(36),那么就会出现一个 error,因为 JavaScript 语法隐含了第一个点之后的部分为小数部分。如果我们再放一个点,那么 JavaScript 就知道小数部分为空,现在使用该方法。

也可以写成 (123456).toString(36)

舍入
  • Math.floor

    向下舍入:3.1 变成 3-1.1 变成 -2

  • Math.ceil

    向上舍入:3.1 变成 4-1.1 变成 -1

  • Math.round

    向最近的整数舍入:3.1 变成 33.6 变成 4-1.1 变成 -1

  • Math.trunc(IE 浏览器不支持这个方法)

    移除小数点后的所有内容而没有舍入:3.1 变成 3-1.1 变成 -1

这个是总结它们之间差异的表格:

Math.floorMath.ceilMath.roundMath.trunc
3.13433
3.63443
-1.1-2-1-1-1
-1.6-2-1-2-1
  1. 乘除法

要将数字舍入到小数点后两位,可以将数字乘以 100,调用舍入函数,然后再将其除回。

let num = 1.23456;

alert( Math.floor(num * 100) / 100 ); // 1.23456 -> 123.456 -> 123 -> 1.23
  1. 函数 toFixed(n) 将数字舍入到小数点后 n 位,并以字符串形式返回结果。
let num = 12.34;
alert( num.toFixed(1) ); // "12.3"

这会向上或向下舍入到最接近的值,类似于 Math.round

let num = 12.36;
alert( num.toFixed(1) ); // "12.4"

注意到 toFixed 的结果是一个字符串。如果小数部分比所需要的短,则在结尾添加零:

let num = 12.34;
alert( num.toFixed(5) ); // "12.34000",在结尾添加了 0,以达到小数点后五位
不精确的计算

如果一个数字太大,则会溢出64位存储,并可能导致无穷大

alert( 1e500 ); // Infinity

这可能不太明显,但经常会发生的是,精度的损失。

测试一下:

alert( 0.1 + 0.2 == 0.3 ); // false

//其实呢
alert( 0.1 + 0.2 ); // 0.30000000000000004

使用二进制数字系统无法 精确 存储 0.10.2,就像没有办法将三分之一存储为十进制小数一样。

舍入规则不允许看到“极小的精度损失”

就可以看到

alert( 0.1.toFixed(20) ); // 0.10000000000000000555

如何解决这个问题呢,最可靠的方法就是借助方法 toFixed(n) 对结果进行舍入

let sum = 0.1 + 0.2;
alert( sum.toFixed(2) ); // 0.30

//注意,toFixed 返回一个字符串,所以用一元符号强制转换为一个数字
let sum = 0.1 + 0.2;
alert( +sum.toFixed(2) ); // 0.3

当我们使用整数进行数学运算时,误差会有所减少,但仍然可以在除法中得到:

alert( (0.1 * 10 + 0.2 * 10) / 10 ); // 0.3
alert( (0.28 * 100 + 0.14 * 100) / 100); // 0.4200000000000001

乘/除法可以减少误差,但不能完全消除误差。

有时候我们可以尝试完全避免小数。

看个例子

// Hello!我是一个会自我增加的数字!
alert( 9999999999999999 ); // 显示 10000000000000000

出现了同样的问题:精度损失。有 64 位来表示该数字,其中 52 位可用于存储数字,但这还不够。所以最不重要的数字就消失了。

JavaScript 不会在此类事件中触发 error。它会尽最大努力使数字符合所需的格式,但不幸的是,这种格式不够大到满足需求。

两个零

数字内部表示的另一个有趣结果是存在两个零:0-0

这是因为在存储时,使用一位来存储符号,因此对于包括零在内的任何数字,可以设置这一位或者不设置。

在大多数情况下,这种区别并不明显,因为运算符将它们视为相同的值。

测试:isFinite 和 isNaN
  • Infinity(和 -Infinity)是一个特殊的数值,比任何数值都大(小)。
  • NaN 代表一个 error。

isNaN(value) 将其参数转换为数字,然后测试它是否为 NaN

alert( isNaN(NaN) ); // true
alert( isNaN("str") ); // true

//值 NaN 是独一无二的,不等于任何东西,包括它本身
alert( NaN === NaN ); // false

isFinite(value) 将其参数转换为数字,如果是常规数字,则返回 true,而不是 NaN/Infinity/-Infinity

alert( isFinite("15") ); // true
alert( isFinite("str") ); // false,因为是一个特殊的值:NaN
alert( isFinite(Infinity) ); // false,因为是一个特殊的值:Infinity

有时 isFinite 被用于验证字符串值是否是常规数字

let num = +prompt("Enter a number", '');

// 结果会是 true,除非你输入的是 Infinity、-Infinity 或不是数字
alert( isFinite(num) );

**注意:**与 Object.is 进行比较

有一个特殊的内建方法 Object.is,它类似于 === 一样对值进行比较,但它对于两种边缘情况更可靠:

  1. 它适用于 NaNObject.is(NaN,NaN)=== true,这是件好事。
  2. 0-0 是不同的:Object.is(0,-0)=== false,从技术上讲这是对的,因为在内部,数字的符号位可能会不同,即使其他所有位均为零。

在所有其他情况下,Object.is(a,b)a === b 相同。

这种比较方式经常被用在 JavaScript 规范中。当内部算法需要比较两个值是否完全相同时,它使用 Object.is(内部称为 SameValue)。

parseInt 和 parseFloat

使用加号 +Number() 的数字转换是严格的。如果一个值不完全是一个数字,就会失败:

alert( +"100px" ); // NaN

parseInt 返回一个整数,parseFloat 返回一个浮点数。

alert( parseInt('100px') ); // 100
alert( parseFloat('12.5em') ); // 12.5

alert( parseInt('12.3') ); // 12,只有整数部分被返回了
alert( parseFloat('12.3.4') ); // 12.3,在第二个点出停止了读取

而某些情况下会返回 NaN。当没有数字可读时会发生

alert( parseInt('a123') ); // NaN,第一个符号停止了读取

parseInt(str, radix)` 的第二个参数

parseInt() 函数具有可选的第二个参数。它指定了数字系统的基数,因此 parseInt 还可以解析十六进制数字、二进制数字等的字符串:

alert( parseInt('0xff', 16) ); // 255
alert( parseInt('ff', 16) ); // 255,没有 0x 仍然有效

alert( parseInt('2n9c', 36) ); // 123456
其它数学函数

Math.random()

返回一个从0到1的随机数(不包括1)

alert( Math.random() ); // 0.1234567894322
alert( Math.random() ); // 0.5435252343232
alert( Math.random() ); // ... (任何随机数)

Math.max(a,b,c…) / Math.min(a,b,c…)

从任意数量的参数中返回最大/最小值。

alert( Math.max(3, 5, -10, 0, 1) ); // 5
alert( Math.min(1, 2) ); // 1

Math.pow(n, power)

返回 n 的给定 (power) 次幂

alert( Math.pow(2, 10) ); // 2 的 10 次幂 = 1024
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值