JavaScript 系列二:数据类型 (下)
在下篇中,我们将继续讨论以下数据类型
String 类型
BigInt 类型
Symbol 类型
Object 类型
数值类型转换
String 类型
String (字符串)数据类型表示零或多个 16 位 Unicode 字符序列。字符串可以使用双引号( "" )、单引号('')或反引号( ` ` )标示。
let xhsFirstName = 'John'
let xhsLastName = 'Jacob'
let xhsLastName = `Jingleheimerschmidt`
let xhsError = 'Nicholas"; // 语法错误:开头和结尾的引号必须是同一种
字符字面量
语法
字面量是由语法表达式定义的常量,或通过由一定字词组成的语词表达式定义的常量。
字符串数据类型包含一些字符字面量,用于表示非打印字符或有其他用途的字符。
| 字 面 量 | 含 义 |
| \n | 换行 |
| \t | 制表 |
| \b | 退格 |
| \r | 回车 |
| \f | 换页 |
| \ | 反斜杠(\) |
| \ | 单引号('),在字符串以单引号标示时使用,例如'He said, \'hey.\'' |
| \" | 双引号("),在字符串以双引号标示时使用,例如"He said, \"hey.\"" |
| \` | 反引号(\`),在字符串以反引号标示时使用,例如\` He said, \` hey.\`` |
| \xnn | 以十六进制编码 nn 表示的字符(其中 n 是十六进制数字 0~F),例如\x41 等于"A" |
| \unnnn | 以十六进制编码 nnnn 表示的 Unicode 字符(其中 n 是十六进制数字 0~F),例如\u03a3 等于希腊字符"Σ" |
这些字符字面量可以出现在字符串中的任意位置,且可以作为单个字符被解释:
let text = 'This is the letter sigma: \u03a3.'
在这个例子中,即使包含 6 个字符长的转义序列,变量 text 仍然是 28 个字符长。因为转义序列表示一个字符,所以只算一个字符。
console.log(text.length) // 28 字符串的长度获取
这个属性返回字符串中 16 位字符的个数。
注意: 如果字符串中包含双字节字符,那么 length 属性返回的值可能不是准确的字符数。
字符串的特点
字符串是不可变的,意思是一旦创建,它们的值就不能变了。要修改某个变量中的字符串值,必须先销毁原始的字符串,然后将包含新值的另一个字符串保存到该变量。
let lang = 'Java'
lang = lang + 'Script'
这里,变量 lang 一开始包含字符串"Java"。紧接着,lang 被重新定义为包含"Java"和"Script"的组合,也是"JavaScript"。整个过程首先会分配一个足够容纳 10 个字符的空间,然后填充上"Java"和"Script"。最后销毁原始的字符串"Java"和字符串"Script",因为这两个字符串都没有用了。
字符串插值
模板字面量最常用的一个特性是支持字符串插值,也就是可以在一个连续定义中插入一个或多个值。技术上讲,模板字面量不是字符串,而是一种特殊的 JavaScript 句法表达式,只不过求值后得到的是字符串。模板字面量在定义时立即求值并转换为字符串实例,任何插入的变量也会从它们最接近的作用域中取值。
字符串插值通过在 ${} 中使用一个 JavaScript 表达式实现:
let value = 5
let exponent = 'second'
// 以前,字符串插值是这样实现的:
let interpolatedString = value + ' to the ' + exponent + ' power is ' + value * value
// 现在,可以用模板字面量这样实现:
let interpolatedTemplateLiteral = `${value} to the ${exponent} power is ${value * value}`
console.log(interpolatedString) // 5 to the second power is 25
console.log(interpolatedTemplateLiteral) // 5 to the second power is 25
所有插入的值都会使用 toString() 强制转型为字符串,而且任何 JavaScript 表达式都可以用于插值。
- 嵌套的模板字符串无须转义:
console.log(`Hello, ${`World`}!`) // Hello, World!
- 将表达式转换为字符串时会调用
toString():let foo = { toString: () => 'World' } console.log(`Hello, ${foo}!`) // Hello, World! - 在插值表达式中可以调用函数和方法:
function capitalize(word) { return `${word[0].toUpperCase()}${word.slice(1)}` } console.log(`${capitalize('hello')}, ${capitalize('world')}!`) // Hello, World!
其他类型转换为字符串
有两种方式把一个值转换为字符串。首先是使用几乎所有值都有的 toString()方法。这个方法唯一的用途就是返回当前值的字符串等价物。
let xhsAge = 11
let xhsAgeAsString = xhsAge.toString() // 字符串"11"
let xhsFound = true
let xhsFoundAsString = xhsFound.toString() // 字符串"true"
toString()方法可见于数值、布尔值、对象和字符串值。(没错,字符串值也有 toString()方法,该方法只是简单地返回自身的一个副本。)null 和 undefined 值没有 toString() 方法。
多数情况下,toString() 不接收任何参数,默认情况下返回十进制,也可以通过参数来设置进制数。
let xhsNum = 10
console.log(xhsNum.toString()) // "10"
console.log(xhsNum.toString(2)) // "1010"
console.log(xhsNum.toString(8)) // "12"
console.log(xhsNum.toString(10)) // "10"
console.log(xhsNum.toString(16)) // "a"
注意,默认情况下(不传参数)的输出与传入参数 10 得到的结果相同。
如果你不确定一个值是不是 null 或 undefined ,可以使用 String() 转型函数,它始终会返回表示相应类型值的字符串。 String() 函数 遵循如下规则。
- 如果值有
toString()方法,则调用该方法(不传参数)并返回结果。 - 如果值是
null,返回"null"。 - 如果值是
undefined,返回"undefined"。let xhsValue1 = 10 let xhsValue2 = true let xhsValue3 = null let xhsValue4 console.log(String(xhsValue1)) // "10" console.log(String(xhsValue2)) // "true" console.log(String(xhsValue3)) // "null" console.log(String(xhsValue4)) // "undefined"
这里展示了将 4 个值转换为字符串的情况: 数值 、布尔值 、null 和 undefined 。
数值 和 布尔值 的转换结果与调用 toString() 相同。因为 null 和 undefined 没有 toString() 方法,所以 String() 方法就直接返回了这两个值的字面量文本。
注意: 用加号操作符给一个值加上一个空字符串""也可以将其转换为字符串
BigInt 类型
BigInt 是一种内置对象,它提供了一种方法来表示大于 2^53 - 1 的整数。这原本是 Javascript 中可以用 Number 表示的最大数字。 BigInt 可以表示任意大的整数。
描述 可以用在一个整数字面量后面加 n 的方式定义一个 BigInt ,如:10n,或者调用函数 BigInt() 。
const theBiggestInt = 9007199254740991n
const alsoHuge = BigInt(9007199254740991)
// ↪ 9007199254740991n
const hugeString = BigInt('9007199254740991')
// ↪ 9007199254740991n
const hugeHex = BigInt('0x1fffffffffffff')
// ↪ 9007199254740991n
const hugeBin = BigInt('0b11111111111111111111111111111111111111111111111111111')
// ↪ 9007199254740991n
它在某些方面类似于 Number ,但是也有几个关键的不同点:不能用于 Math 对象中的方法;不能和任何 Number 实例混合运算,两者必须转换成同一种类型。在两种类型来回转换时要小心,因为 BigInt 变量在转换成 Number 变量时可能会丢失精度。
Symbol 类型
symbol 是一种基本数据类型( primitive data type )。 Symbol() 函数会返回 symbol 类型的值,该类型具有静态属性和静态方法。它的静态属性会暴露几个内建的成员对象;它的静态方法会暴露全局的 symbol 注册,且类似于内建对象类,但作为构造函数来说它并不完整,因为它不支持语法:"new Symbol()"。
每个从 Symbol() 返回的 symbol 值都是唯一的。一个 symbol 值能作为对象属性的标识符;这是该数据类型仅有的目的。
语法
参数 description 可选
Symbol([description])
可选的,字符串类型。对 symbol 的描述,可用于调试但不是访问 symbol 本身。
描述
直接使用 Symbol() 创建新的 symbol 类型,并用一个可选的字符串作为其描述。
var sym1 = Symbol()
var sym2 = Symbol('foo')
var sym3 = Symbol('foo')
上面的代码创建了三个新的 symbol 类型。 注意, Symbol("foo") 不会强制将字符串 “foo” 转换成 symbol 类型。它每次都会创建一个新的 symbol 类型:
Symbol('foo') === Symbol('foo') // false
下面带有 new 运算符的语法将抛出 TypeError 错误:
var sym = new Symbol() // TypeError
Object 类型
ECMAScript 中的对象其实就是一组数据和功能的集合。对象通过 new 操作符后跟对象类型的名称来创建。开发者可以通过创建 Object 类型的实例来创建自己的对象,然后再给对象添加属性和方法.
let xhsO = new Object()
ECMAScript 中的 Object 是派生其他对象的基类。 Object 类型的所有属性和方法在派生的对象上同样存在。每个 Object 实例都有如下属性和方法。
constructor:用于创建当前对象的函数。在前面的例子中,这个属性的值就是Object()函数。hasOwnProperty(*propertyName*):用于判断当前对象实例(不是原型)上是否存在给定的属性。要检查的属性名必须是字符串(如o.hasOwnProperty("name"))或符号。isPrototypeOf(*object*):用于判断当前对象是否为另一个对象的原型。propertyIsEnumerable(*propertyName*):用于判断给定的属性是否可以使用for-in语句枚举。与hasOwnProperty()一样,属性名必须是字符串。toLocaleString():返回对象的字符串表示,该字符串反映对象所在的本地化执行环境。toString():返回对象的字符串表示。valueOf():返回对象对应的字符串、数值或布尔值表示。通常与toString()的返回值相同。
因为在 ECMAScript 中 Object 是所有对象的基类,所以任何对象都有这些属性和方法。
数值类型转换
有 3 个函数可以将非数值转换为数值: Number() 、 parseInt() 和 parseFloat() 。 Number() 是转型函数,可用于任何数据类型。后两个函数主要用于将字符串转换为数值。对于同样的参数,这 3 个函数执行的操作也不同。
Number() 函数
基于如下规则执行转换。
- 布尔值,
true转换为1,false转换为0。 - 数值,直接返回。
null,返回0。undefined,返回NaN。-
字符串,应用以下规则。
- 如果字符串包含数值字符,包括数值字符前面带加、减号的情况,则转换为一个十进制数值。因此,
Number("1")返回1,Number("123")返回123,Number("011")返回11(忽略前面的零)。 - 如果字符串包含有效的浮点值格式如
"1.1",则会转换为相应的浮点值(同样,忽略前面的零)。 - 如果字符串包含有效的十六进制格式如
"0xf",则会转换为与该十六进制值对应的十进制整数值。 - 如果是空字符串(不包含字符),则返回
0。 - 如果字符串包含除上述情况之外的其他字符,则返回
NaN。
- 如果字符串包含数值字符,包括数值字符前面带加、减号的情况,则转换为一个十进制数值。因此,
- 对象,调用
valueOf()方法,并按照上述规则转换返回的值。如果转换结果是NaN,则调用toString()方法,再按照转换字符串的规则转换。let xhsNum1 = Number('Hello world!') // NaN let xhsNum2 = Number('') // 0 let xhsNum3 = Number('000011') // 11 let xhsNum4 = Number(true) // 1
parseInt() 函数
- 字符串最前面的空格会被忽略,从第一个非空格字符开始转换
- 如果第一个字符不是数值字符、加号或减号,
parseInt()立即返回NaN - 如果第一个字符是数值字符、加号或减号,则继续依次检测每个字符,直到字符串末尾,或碰到非数值字符。比如,
"1234blue"会被转换为1234,因为"blue"会被完全忽略。类似地,"22.5"会被转换为22,因为小数点不是有效的整数字符。
假设字符串中的第一个字符是数值字符, parseInt() 函数也能识别不同的整数格式(十进制、八进制、十六进制)。换句话说,如果字符串以 "0x" 开头,就会被解释为十六进制整数。如果字符串以 "0" 开头,且紧跟着数值字符,在非严格模式下会被某些实现解释为八进制整数。
let xhsNum1 = parseInt('1234blue') // 1234
let xhsNum2 = parseInt('') // NaN
let xhsNum3 = parseInt('0xA') // 10,解释为十六进制整数
let xhsNum4 = parseInt(22.5) // 22
let xhsNum5 = parseInt('70') // 70,解释为十进制值
let xhsNum6 = parseInt('0xf') // 15,解释为十六进制整数
parseInt() 也接收第二个参数,用于指定进制数。可以省略前面的 0x 或者 0
let xhsNum = parseInt('0xAF', 16) // 175
let xhsNum1 = parseInt('AF', 16) // 175
let xhsNum2 = parseInt('AF') // NaN
通过第二个参数,可以极大扩展转换后获得的结果类型。
let xhsNum1 = parseInt('10', 2) // 2,按二进制解析
let xhsNum2 = parseInt('10', 8) // 8,按八进制解析
let xhsNum3 = parseInt('10', 10) // 10,按十进制解析
let xhsNum4 = parseInt('10', 16) // 16,按十六进制解析
注意: 多数情况下解析的应该都是十进制数,此时第二个参数就要传入 10 。
parseFloat() 函数
该函数的工作方式跟 parseInt() 函数类似,都是从位置 0 开始检测每个字符。同样,它也是解析到字符串末尾或者解析到一个无效的浮点数值字符为止。这意味着第一次出现的小数点是有效的,但第二次出现的小数点就无效了,此时字符串的剩余字符都会被忽略。因此, "22.34.5" 将转换成 22.34 。
注意
- 它始终忽略字符串开头的零
- 十六进制数值始终会返回
0 - 如果字符串表示整数(没有小数点或者小数点后面只有一个零),则
parseFloat()返回整数let xhsNum1 = parseFloat('1234blue') // 1234,按整数解析 let xhsNum2 = parseFloat('0xA') // 0 let xhsNum3 = parseFloat('22.5') // 22.5 let xhsNum4 = parseFloat('22.34.5') // 22.34 let xhsNum5 = parseFloat('0908.5') // 908.5 let xhsNum6 = parseFloat('3.125e7') // 31250000
题目自测
一:null 和 undefined 的区别是什么?
二:以下代码,哪个结果返回的是 NaN()
A. let a = Number('')
B. let b = Number('xhs')
C. let c = Number(true)
D. let d = Number(120);
三: 以下代码输出什么?
let a = 12
let b = false
let c = null
let d = undefined
console.log(typeof a.toString())
console.log(typeof b.toString())
console.log(String(c))
console.log(String(d))
题目解析
一、null 和 undefined 都是基本的数据类型,它们都本身都只有一个值,就是 null 和 undefined 。 undefined 表示未定义,null 表示为空对象。
null == undefined // true
null === undefined // false
Number(null) // 0
Number(undefined) // NaN
二、
Answr:B
此处用到了数值类型转换中的 Number() 函数
A 为空字串,转换之后返回的是 0 , B 字符串中的其他类型,转化为 NaN ,C true 会先转化为 1 ,然后转化为数值,D 普通数值,返回原来的值,所以是 120
三、toString() 方法将值都转化为字符串的方式输出。然而 null 和 undefined 没有 toString() 方法,可以使用 String() 直接转化为字符串。
// 'string'
// 'string'
// 'null'
// 'undefined'




















