原始类型的方法
以下是JavaScript创建者面临的悖论:
- 人们可能想对诸如字符串或数字之类的原始类型执行很多操作,最好将它们作为方法来访问。
- 原始类型必须尽可能的简单轻量。 解决方案,如下:
- 原始类型仍然是原始的。与预期相同,提供单个值
- JavaScript允许访问字符串,数字,布尔值和symbol的方法和属性。
- 为了使它们起作用,创建了提供额外功能的特殊“对象包装器”,使用后即被销毁。
"对象包装器"对于每种原始类型哦都是不同的,它们被称为String, Number,Boolean和Symbol。因此,它们提供了不同的方法。
举个例子:
let str = "Hello";
alert( str.toUpperCase() ); // HELLO
以下是实际str.toUpperCase()中实际发生的情况:
- 字符串
strs是一个原始值。因此,在访问其属性时,会创建一个包含字符串字面量的特殊对象,并且具有有用的方法,例如toUpperCase()。 - 该方法运行并返回一个新的字符串(由
alert显示)。 - 特殊对象被销毁,只留下原始值
str.
所以原始类型可以提供方法,但它们依然时轻量级的。
❗ 构造器Stirng/Number/Boolean仅提供内部使用
像Java这样的一些语言允许我们使用new Number(1) 或 new Boolean(true)等语法,明确地为原始类型创建“对象包装器”。
在JavaScript中,由于历史原因,这也是可以,但极其不推荐。因为这样会出问题let zero = new Number(0); if(zero) { alert("zero is truthy?!") };因为在if中始终为真,因此此处的alert将显示
另一方面,调用不带
new关键字的String/Number/Boolean函数是完全理智和有用的。它们将一个值转换为相应的类型:转成字符串,数字或布尔值(原始类型)。
例如,下面完全是有效的:let num = Number("123");
null和undefined
特殊的原始类型null和undefined是例外。它们没有对应的“对象包装器”,也没有提供任何方法。从某种意义上说,它们是最原始的。
原文链接:zh.javascript.info/primitives-…
数字类型
在现代JavaScript中,数字有两种类型:
- JavaScript中常规数字以64位的格式IEEE-754存储,也被称为“双精度浮点数”。这是我们大多数时候所使用的数字。
- Bigint数字,用于表示任意长度的整数。有时会需要它们,因为常规数字不能超过
2<sup>53</sup>或小于-2<sup>53</sup>。(另讲) - Infinity(-Infinity)
- NaN
我们将主要讨论常规数字。
科学计数法
在JavaScript中,我们通过在数字后附加字母e,并指定零的数量来缩短数字。
let billion = 1e9;
alert(billion); // 1000000000
alert(7.3e9); // 7300000000
e后面可以接负数,表示除以1后面跟着给定数量的0的数字
alert(1e-3); // 0.001
alert(1.23e-6); // 0.00000123
十六进制,二进制和八进制数字
十六进制,二进制和八进制可以使用0x,0b和0o前缀表示。
// 十六进制
alert( 0xff ); // 255
alert( 0x5f ); // 95
// 二进制
alert( 0b111101 ); // 61
alert( 0b1111 ); // 15
// 八进制
alert( 0o377 ); // 255
alert( 0o4523 ); // 2387
只有这三种进制支持这种写法。对于其他进制,我们应该使用函数
parseInt。
toString(base)
num.toString(base) 返回在给定base进制数字系统中num的字符串表示形式。
base的范围是 2 ~ 36 的整数。默认是 10 。
let num = 255;
alert(num.toString(2)); // 11111111
alert(num.toString(16)); // ff
⭐ 使用两个点调用toString()方法
如果我们想直接在一个数字上调用一个方法,我们需要在它后面放置两个点..。alert(123456..toString(36)); //2n9c // 相当于 alert( (123456).toString(36) );如果放置一个点,会出错。因为JavaScript语法隐含了第一个点之后的部分位小数部分。如果再放一个点,那么JavaScript就知道小数部分为空,现在使用该方法。
parseInt 和 parseFloat
parseInt和parseFloat的作用:
- 可以从字符串中“读取”数字,直到无法读取位置。如果发生error,则返回收集到的数字。函数
parseInt返回一个整数,函数parseFloat返回一个浮点数 parseInt函数具有可选的第二个参数,制定了数字系统的基数,可以解析十六进制数字等字符串。
// 第一个作用
alert( parseInt("100px") ); // 100
alert( parseFloat("12.5rem") ); //12.5
alert( parseInt("12.8") ); // 12 , 只有整数部分返回
alert( parseFloat("12.3.4") ); // 12.3 , 在第二个点处停止了读取
alert( parseInt("a123") ); //NaN 第一个符号停止了读取
// 第二个作用
alert( parseInt("0xff", 16) ); // 255
alert( parseInt("ff", 16) ); // 255 , 没有0x前缀仍然有效
alert( parseInt("2n9c", 36) ); // 123456
小数的舍入
Math.floor()向下舍入Math.ceil()向上舍入Math.round()四舍五入Math.trunc()保留整数(※IE浏览器不支持这个方法)
| Math.floor() | Math.ceil() | Math.round() | Math.trunc() | |
|---|---|---|---|---|
| 3.1 | 3 | 4 | 3 | 3 |
| 3.6 | 3 | 4 | 4 | 3 |
| -1.1 | -2 | -1 | -1 | -1 |
| -1.6 | -2 | -1 | -2 | -1 |
- 保留小数点后
n位:
- 乘除法
let num = 1.23456'
alert( Math.floor(num * 100) / 100 ); // 1.23
toFixed(n)方法,以 字符串 形式返回结果
let num = 12.34;
alert( num.toFixed(1) ); // "12.3"
num = 12.36;
alert( num.toFixed(1) ); // "12.4"
// 如果小数部分比所需要的短,则在结尾添加0
alert( num.toFixed(5) ); // "12.36000"
isFinite 和 isNaN
isFinity(value)将其参数转换为数字,如果是常规数字,则返回true
alert( isFinity("15") ); //true
alert( isFinity("str") ); //false, 因为是一个特殊的值 NaN
alert( isFinity(Infinity) ); //false 因为是一个特殊的值 Infinity
isNaN(value)将其参数转换为数字,然后测试它是否为NaN
alert( isNaN(NaN) ); // true
alert( isNaN("str") ); // true
// NaN === NaN
// 值NaN是独一无二的,它不等于任何东西,包括它自身
alert( NaN === NaN ); // false
在所有数字函数(包括isFinity)中,空字符串或仅有空格的字符串均被视为 0
Object.is方法 它类似于
===一样对值进行比较,但它对于两种边缘情况更可靠:
- 适用于NaN: Object.is(NaN,NaN) === true
- 值 0 和 -0 是不同的:Object.is(0,-0) === false
不精确的计算
在内部,数字是以 64 位格式 IEEE-754 表示的,所以正好有 64 位可以存储一个数字:其中 52 位被用于存储这些数字,其中 11 位用于存储小数点的位置(对于整数,它们为 0 ),而 1 位用于符号。
溢出
如果一个数字太大,则会溢出64位存储,并可能导致无穷大:
alert( 1e500 ); // Infinity
精度的损失
alert( 0.1 + 0.2 == 0.3 ); // false
alert( 0.1 + 0.2 ) // 0.30000000000000004
为什么会出现这样的情况呢?
一个数字以其二进制的形式存储在内存中。在十进制数字系统中开起来很简单的0.1,0.2这样的小数,实际上在二进制行驶中是无限循环小数。
在十进制数字系统中,可以保证以10的整数次幂作为除数能够正常工作,但是以3作为除数则不能。也是同样的原因,在二进制数字系统中,可以保证以2的整数次幂作为除数时能够正常工作,但1/10就变成了一个无限循环的二进制小数。
IEEE-754数字格式通过将数字舍入到最接近的可能数字来解决此问题,这些舍入规则通常不允许我们看到“极小的精度损失”,但是它确实存在。
最可靠的方法时借助方法 toFixed(n)对结果进行舍入,再将其强制转换位数字:
let sum = 0.1 + 0.2;
alert( +sum.toFixed(2) ); // 0.3
尝试运行下面的这段代码:
alert( 9999999999999999 ) // 显示 10000000000000000出现了同样的问题:精度损失。有64位来表示数字,其中52位可用于存储整数,但这还不够,所以最不重要的数字就消失了 JavaScript不会在此类事件中触发error。它会尽最大努力使数字符合所需的格式。
其他数学函数
- Math.random(): 返回一个从 0 到 1 的随机数(不包括 1 )
- Math.max(a, b...)/Math.min(a, b...): 从任意数量的参数中返回最大/最小值
- Math.pow(n, power): 返回 n 的给定 power 次幂 其他数学函数,点击这里查看
原文链接:zh.javascript.info/number
字符串
字符串的表示
可以包含在单引号,双引号或反引号中,反引号允许我们通过${...}将任何表达式嵌入到字符串中,允许跨行。
let single = 'single-quoted';
let double = "double-quoted";
function sum(a, b){
return a + b;
}
let guestList = `Guest:
* John
* Pete
* Mary
`;
alert(single); // single-quoted
alert(double); // double-quoted
/*
Guest:
* John
* Pete
* Mary
*/
alert(guestList);
alert(`1 + 2 = ${sum(1, 2)}.`); // 1 + 2 = 3.
特殊字符
常用特殊字符
| 字符 | 描述 |
|---|---|
\n | 换行 |
\r | 回车:不单独使用。Windows文本文件使用两个字符\r\n的组合来表示换行。 |
\'``\" | 引号 |
\\ | 反斜线 |
\t | 制表符 |
\xXX | 具有给定十六进制 Unicode XX 的 Unicode 字符 |
\uXXXX | 以 UTF-16 编码的十六进制代码 XXXX 的 unicode 字符 |
\U{XXXX..}(1到6个十六进制字符) | 具有给定 UTF-32 编码的 unicode 符号。一些罕见的字符用两个 unicode 符号编码 |
字符串的长度
Length属性表示字符串的长度
alert(`My\n`.length); // 3
\n是一个单独的“特殊”字符,所以长度是 3.
访问字符
- 使用方括号
[] - 调用
str.charAt(pos)方法 ❗
- 第一个字符下标为 0
- 如果没有找到字符,
[]返回undefined,charAt返回一个空字符串 - 可以使用
for..of遍历字符
for(let char of "Hello"){
alert(char); // H e l l o
}
常用方法
改变大小写
str.toUpperCase() 转换大写
str.toLowerCase() 转换小写
查找字符串
str.indexOf(substr [, pos])
- 从给定位置
pos开始,在str中查找substr,如果没有找到,则返回-1,否则返回匹配成功的位置。
str.lastIndexOf(substr [, pos])
- 从给定位置
pos开始向前搜索,默认为字符串末尾
str.inclueds(substr [, pos])
- 返回布尔值,判断是否存在
substr - 第二个可选参数是开始搜索的起始位置
str.startsWith(substr)
- 判断是否以
substr开头
str.endsWith(substr)
- 判断是否以
substr结尾
获取子字符串
str.slice(start [, end])
- 返回字符串从
start到(但不包括)end的部分 - 如果没有第二个参数,
slice会一直运行到字符串末尾 start/end也有可能是负值
let str = "stringify";
// 从右边的第四个位置开始,在右边的第一个位置结束
alert( str.slice(-4, -1) ); // "gif"
str.substring(start [, end])
- 返回字符串从
start到(但不包括)end的部分 - 允许
start大于end - 不允许负参数,负参数视为 0
str.substr(start [, length])
- 返回字符串从
start开始获取length的字符串 - 允许
start负值
比较字符串
str.codePointAt(pos)
- 返回
pos位置的字符UTF-16编码
String.fromCodePoint(code)
- 通过数字
code创建字符
alert( String.fromCodePoint(90) ); // Z
str.localeCompare(str2)
- 根据语言规则返回一个整数,这个整数能指示字符串
str在排序顺序中排在字符串str2前面,后面,还是相同:- 如果
str排在str2前面,则返回负数。 - 如果
str排在str2后面,则返回正数。 - 如果它们在相同位置,则返回
0
- 如果
其他
str.trim()
- 删除字符串前后的空格
str.repeat(n)
- 重复字符串 n 次