ECMAScript
中有 6 种简单数类型(也称基本数据类型):Undefined
、Null
、Boolean
、Number
、String
、symbol
(ES6
新增)
以及 1 种复杂数据类型:Object
typeof 操作符
由于 ECMAScript
是松散类型的,所以我们需要检测变量的数据类型,而 typeof
就是负责检测数据类型的操作符,它的返回值是字符串:
'undefined'
—— 未定义‘boolean’
—— 布尔’string’
—— 字符串’number’
—— 数值‘object’
—— 对象或者null
‘function’
—— 函数‘symbol’
—— 符号(ES6
新增)
如下列例子:
var message = 'some string'
console.log(typeof message) // string
console.log(typeof (message)) // string
console.log(typeof 1) // number
console.log(typeof true) // boolean
var message1;
console.log(typeof message1) // undefined
console.log(typeof null) // object
function test () {}
console.log(typeof test) // function
上面? 例子中的 typeof null
的值为 object
字符串,是因为 null
被认为是一个空的对象引用。
而 typeof test
值为 function
字符串,这里我们得知道,函数在 ECMAScript
中是对象,不是一种数据类型,但是可以通过 typeof
操作符来区分函数和其他对象。
undefined
undefined
类型只有一个值,它在使用 var/let
声明变量没有初始化时,这时候这个变量的值就是 undefined
。
还有一个特别的地方就是,对于未声明的变量,typeof
也是返回 undefined
。
var a;
typeof a // undefined
typeof b // undefined
let c;
typeof c // undefined
结果表明,对未初始化和未声明的变量执行 typeof
操作符都返回了 undefined
这个值,对于这个结果有符合逻辑上的合理性,因为虽然这两种变量从技术角度看有本质区别,但是实际上无论对哪种变量也不可能执行真正的操作。
null
null
和 undefined
一样,也是只有一个值的数据类型,它表示一个空对象指针,这也就是 typeof
检测 null
返回 object
的原因。
实际上 undefined
值派生自 null
,因此 ECMA-262
规定对它们相等性测试要返回 true
:
console.log(undefined == null) // true
虽然我们的 undefined
与 null
有这样的关系,但是当我们初始化变量时没有必要将变量的值赋值为 undefined
,同样的规则在 null
这里就不一样了,我们可以将一个保存变量的对象赋值为 null
,这样在使用的时候就可以知道相应的变量是否已经保存了一个对象的引用:
var car = null;
if (car != null) {
// 对 car 对象执行某些操作
}
并且这样做的好处也有助于区分 undefined
和 unll
。
Boolean
boolean
有两个字面值:true
和 false
,这两个值与数字值不是一回事,所以,true
不一定等于 1,false
不一定等于 0。
我们需要注意一点,boolean
类型的字面值是区分大小写的,也就是说,True
和 False
或者其它形式的混合大小写都不是 boolean
值,只是标识符。
我们可以使用 Boolean()
将一个值转换为对应的 Boolean
值:
var message = "abc"
var messageBoolean = Boolean(message)
console.log(messageBoolean) // true
上面的例子是字符串转 boolean
值,那么其它类型转 Boolean
值如下表:
数据类型 | 转换为 true 的值 | 转换为 false 的值 | Boolean | true | false | String | 任何非空字符串 | “”(空字符串) | Number | 任何非零数字值(包括无穷大) | 0 和 NaN | Object | 任何对象 | null | undefined | 不适用 | undefined |
---|
Number
Number
分为整数和浮点数值(浮点数值在某些语言中也成为双精度数值)。为支持各种数据类型,ECMA-262
定义了不同的数值字面量格式:
- 十进制整数
- 八进制(以
8
为基数),八进制字面值的第一位必须是0
,数字序列为0 ~7
,如果字面值中的数值超出了范围,那么前面的0
就会被忽略,后面的数值就会被当做十进制数值解析。 - 十六进制(以
16
为基数),十六进制字面值的前两位必须是0x
,数字序列为0 ~ 9
和A ~ F/ a~f
var intNum = 1; // 十进制整数
var octalNum1 = 070; // 八进制的 56
var octalNum2 = 079; // 无效的八进制数值 —— 解析为 79
var octalNum3 = 08; // 无效的八进制数值 —— 解析为 8
var hexNum1 = 0xA; // 十六进制的10
var hexNum2 = 0x1f; // 十六进制的 31
当然,在进行算术计算时,所有八进制和十六进制表示的数值最终都会被转换成十进制数值。
1. 浮点数值
浮点数值就是这个数值中必须包含一个小数点,并且小数点后面必须至少有一位是数字:
var floatNum = 1.1
var floatNum1 = 0.1
var floatNum2 = .1
在上面的例子中,var floatNum2 = .1
省略了前面的数字,这种写法是有效的,但是不推荐这种写法。
当然,如果我们的小数点后面没有跟任何数字或者是跟的 0,那么这个值会被转换为整数,因为保存浮点数值需要的内存空间是保存整数值的两倍。
var floatNum = 1. // 小数点后面没有数字,会转换为整数 1
floatNum = 1.0 // 小数点后面跟的是0,会转换为整数 1
我们平时会遇到一些极大或极小的数值,这时就可以用科学计数法 —— e
表示浮点数值。使用 e
表示的数值等于 e
前面的数值乘以 10
的指数次幂,比如:前面是一个数值,可以是整数也可以是浮点数,中间是一个大写或者小写的字母 e
,后面是 10
的指数次幂,这个幂值会用来与前面的数相乘,如下面这个例子,就是 3.12345
乘以 107:
var floatNum = 3.12345e7 // 等于 31234500
当然,我们的 e
表示法也可以表示极小的数值,如 0.00000000000001
就可以使用 1e-14
来表示。
值得注意的是,浮点数的最高精度是 17
位小数,但是在进行算术计算时其精度远远不如整数。一个典型的例子:0.1 + 0.2
的结果不是 0.3
,而是 0.30000000000000004
。
2. 数值范围
- 最小数值:
Number.MIN_VALUE
,在大多数浏览器中为5e-324
- 最大数值:
Number.MAX_VALUE
,在大多数浏览器中为1.7976931348623157e+308
如果某次计算的结果得到了一个超出了上面?的这两个范围,那么这个值将自动转换成特殊的 Infinity
,若这个数是负数,则会被转换成 -Infinity
,若是正数则会被转换成 Infinity
。
而我们访问 Number.NEGATIVE_INFINITY
,则会得到 -Infinity
;访问 Number.POSITIVE_INFINITY
,则会得到 Infinity
。由此可知,这两个属性中分别保存着正无穷和负无穷。
3.NaN
NaN
是一个特殊的数值,它表示一个非数值(Not a Number
),这个数值用于表示一个本来要返回数值的操作数未返回数值的情况。
NaN
有两个特点:
- 任何与
NaN
相关的操作都会返回NaN
NaN
与任何值都不相等,包括NaN
本身
NaN + 1 // NaN
NaN * 1 // NaN
NaN == NaN // false
针对 NaN
的这两个特点,ECMAScript
定义了 isNaN()
函数。
isNaN()
接收一个参数,这个参数可以是任何类型,它会在接收到这个值之后,去尝试将这个值转换为数值,如果转换完成后,结果不是一个数值则会返回 true
,否则返回 false
。
isNaN(NaN) // true
isNaN(1) // false,1 本身就是一个数值
isNaN("1") // false,字符串 1 可以被转换成一个数值 1
isNaN('blue') // true,blue 不能被转换成数值
isNaN(true) // false,true 可以被转换成数值 1
isNaN('true') // false,同上
4. 数值转换
在 ECMAScript
中,有 3
个函数可以把非数值转换为数值:
Number()
可用于任何数据类型parseInt()
用于字符串转换成数值parseFloat()
用于字符串转换成数值
Number()
Number()
转换规则如下:
Boolean
——true
为1
,false
为0
- 数值,传入什么返回什么,但是会去掉无用的
0
,如:Number(0.10)
则会返回0.1
null
——0
undefined
——NaN
- 字符串有以下规则:
- 只包含数字
- 整数:若前导有多余的
0
,则省略。如:Number('011')
->11
- 浮点数:转换为对应的浮点数,若前导和结尾有多余的
0
,则忽略。如:Number('00.110')
->0.11
- 整数:若前导有多余的
- 十六进制则会转换为相同大小的十进制数:
Number(0xf)
->15
- 空字符串 ——
0
- 字符串包含除上述外的其它字符,则为
NaN
- 只包含数字
- 对象,使用
valueOf()
依照上述规则转换返回的值,若结果为NaN
,则调用对象的toString()
方法,然后再依次按照前面的规则转换返回的字符串值。
根据上面的条例,我们来看几个例子:
Number('Hello world!') // NaN,遵循字符串包含除数字值的任意字符
Number('') // 0,遵循空字符串转换为 0
Number("00011000") // 11000,遵循字符串为整数时,删除前导的零
Number("00.1010100") // 0.10101,遵循字符串为浮点数时,删除前导和结尾多余的 0
Number(true) // 1,遵循 Boolean true 为 1
Number(null) // 0,遵循 null 为 0
Number(undefined) // NaN,遵循 undefined 为 NaN
由于 Number()
函数转换字符串时比较复杂且不够合理,因此就有了我们处理字符串时常用的两个函数:parseInt()
和 parseFloat()
。parseInt()
用于处理整数字符串,而 parseFloat()
则用于处理我们的浮点数字符串。
parseInt()
那我们就先来看看 parseInt()
:
parseInt()
在 ECMAScript 3 JavaScript
引擎中,会自动识别八进制,就是会将以 0
开头的字符串解析为八进制。但是在 ECMAScript 5 JavaScript
引擎中,parseInt()
就已经不具有解析八进制的能力,因此,parseInt()
提供了第二个参数,这个参数就是指定转换为哪个进制。
当然 parseInt()
也有一些其它规则:
- 若第一个字符不是数字字符或者负号,则返回
NaN
。 - 若第一个字符是数字字符,则会继续解析第二个字符,直到遇到一个非数字字符。
- 若以
0x
开头的字符,则会当做十六进制数来解析。 - 虽然指定基数不填时,
parseInt()
会自动解析为十进制数,但为了避免错误的解析,应明确指定基数。
parseInt('123abc') // 123,遵循第二条例
parseInt('010') // 10,自动转换为十进制数
parseInt('AB') // NaN,省略了第二个参数,转换为十进制时,不识别 AB
parseInt('AB', 16) // 171,第二个参数指定为十六进制
parseInt('10', 2) // 2,按二进制解析
parseInt('10', 8) // 8,按八进制解析
parseInt('10', 10) // 10,按十进制解析
parseInt('10', 16) // 16,按十六进制解析
parseInt('0x1A') // 26,按十六进制解析
以上就是 parseInt()
的用法及示例,在多数情况下我们解析的都是十进制数值,所以可以始终将 10 作为第二个参数是非常必要的。
parseFloat()
parseFloat()
与 parseInt()
函数类似,但还是有以下区别:
- 解析浮点数时,第一个小数点有效,第二个小数点无效
- 只解析十进制格式的字符串
- 十六进制的格式始终会被转换为 0
- 字符串包含一个可解析为整数的数(没有小数点或者小数点后面是零),则返回一个整数
parseFloat('1234blue') // 1234,与 parseInt 规则一一样
parseFloat('0xA') // 0,十六进制的格式始终会被转换为 0
parseFloat('123.45') // 123.45,正常格式鸳鸯输出
parseFloat('123.45.6') // 123.45,值识别第一个小数点
parseFloat('1.2345e7') // 12345000
parseFloat('1.00') // 1,小数点后都是零,返回整数
String
String
类型就是我们日常所说的字符串,它是由零或多个 16
位 Unicode
字符组成的字符串。
字符串有两种写法:双引号("")和单引号('')。这两种表示方法的字符串时完全相同的,需要注意的是以双引号开头的字符串需要以双引号结束。
var firstName = 'a" // 这种写法的字符串是错误的。
1.字符串字面量
String
数据类型包含一些特殊的字符字面量,也叫转义序列,用于表示非打印字符,如下表:
字面量 | 含义 | \n | 换行符 | \t | 制表符 | \b | 退格符 | \r | 回车符 | \f | 换页符 | \\ | 斜杠符 | \' | 单引号,在单引号表示的字符串中使用。如:'Hi, I'm Shinkai' | \" | 双引号,在双引号表示的字符串中使用。如:"He said, "hey"" | \xnn | 以十六进制代码 nn 表示一个字符(其中 n 为 0~F),如:\x41,表示 "A" | \unnn | 以十六进制代码nnnn表示的一个Unicode字符(其中n为0~F)。例如,\u03a3表示希腊字符Σ |
---|
上表的字面量可以出现在字符串中的任意位置,如:``,
var test = 'Hi, I\'m Shinkai, \x456' // Hi, I'm Shinkai, E6
test.length // 19
这例子中的变量 test
有 19
个字符, 其中 \x456
表示两位字符。
2.字符串的特点
ECMAScript
中的字符串时不可变的,意思是一旦创建,它们的值就不能变了,要修改某个变量中的字符串值,必须先销毁原始的字符串,然后将包含新值的另一个字符串保存到该变量中。
let a = 'ECMA'
a = a + 'Script'
上面的 a
变量一开始只包含字符串 ECMA
,后面又被重新定义包含 ECMA
和 Script
的组合。在这个过程中,首先会先分配一个容纳 10
个字符的空间,然后填充 ECMA
和 Script
,最后会销毁原始的字符串 ECMA
和 Script
,因为这两个字符串都没有用了。这些处理都是在后台发生的,这也是早期浏览器在拼接字符串时非常慢的原因。但现在的浏览器都针对性的解决了这个问题。
3.转换为字符串
toString()
—— 可用于数值、布尔值、对象和字符串值等,是字符串本身的方法。- 接受的参数是进制,比如八进制、二进制、十六进制等,或者任何其他有效基数的字符串表示。
String()
—— 可用于数值、布尔值、对象、字符串值、null
、undefined
,是转型函数。- 如果值是
null
,则返回"null"
- 如果值是
undefined
,则返回"undefined"
- 不可转进制
- 如果值是
toString()
示例:
let example = 11;
example.toString() // "11"
example.toString(2) // "1011", 二进制的字符串数值
example.toString(8) // "3",八进制的字符串数值
example.toString(16) // "b",十六进制的字符串数值
example = true
example.toString() // "true"
example = undefined
example.toString() // 报错,undefined 没有 toString() 方法
example = null
example.toString() // 报错,null 没有 toString() 方法
String()
示例:
String() // 空字符串
let example = 10
String(example) // 字符串“10”
example = true
String(example) // 字符串 “true”
example = undefined
String(example) // “undefined”
example = null
String(example) // "null"
4.模板字面量
ECMAScript 6
新增字符串方法
它与使用单引号或双引号不同,模板字面量保留换行字符,它是可以跨行定义的字符串 —— ``
let example = `a \n b`
console.log(example)
// a
// b
example = `a
b`
console.log(example)
// a
// b
// 可以定义 HTML 模板:
example = `
<div>
<a href="#">
<span>Shinkai</span>
</a>
</div>
`
模板字符会保留所有空格及换行符,因此,我们在使用模板字符的时候,尽量不要使用多余的空格。
5.字符串插值
ECMAScript 6
新增字符串方法
JavaScript
有一种句法表达式 —— 模板字面量,这个东西就是字符串插值中最常用的特性,它可以在一个连续定义中插入一个或多个值,最后得到一个完整的字符串。
字符串插值通过在 ${}
中使用一个 JavaScript
表达式实现:
let value = 'apple'
let example = 'an'
// 以前的字符串拼接
let str = 'I have' + example + value;
console.log(str) // "I have an apple"
// 使用字符串插值
str = `I have ${example} ${value}`
console.log(str) // "I have an apple"
当然,我们的模板字面量不仅仅可以是变量,也可以是函数和方法:
function capitalize(word) {
return `${ word[0].toUpperCase() }${ word.slice(1) }`;
}
console.log(`${ capitalize('hello') }, ${ capitalize('world') }!`); // Hello, World!
模板字面量也支持定义标签函数(tag function),标签函数本身是一个常规函数,我们可以通过前缀模板字面量来应用自定义行为:
let a = 6;
let b = 9;
function example(strings, aExpression, bExpression, sumExpression) {
console.log(strings) // ["", "+", "=", ""]
console.log(aExpression) // 6
console.log(bExpression) // 9
console.log(sumExpression) // 15
return 'foobar'
}
let untaggedResult = `${a} + ${b} = ${a + b}`
let taggedResult = example`${a} + ${b} = ${a + b}`
// ["", "+", "=", ""]
// 6
// 9
// 15
console.log(untaggedResult) // "6 + 9 = 15"
console.log(taggedResult) // 'foobar'
6.原始字符串
String.raw
—— 这个标签函数可以获取原始字符串
// Unicode 示例
// \u00A9 是版权符号
console.log(`\u00A9`); // ©
console.log(String.raw`\u00A9`); // \u00A9
// 换行符示例
console.log(`first line\nsecond line`);
// first line
// second line
console.log(String.raw`first line\nsecond line`); // "first line\nsecond line"
Symbol
ECMAScript 6
新增基本数据类型
Symbol
是一种基本数据类型,所以typeof
操作符返回symbol
- 使用
Symbol()
函数会返回symbol
类型的值,这个值具有静态属性和静态方法。 - 不能与
new
关键字一起作为构造函数使用。 - 符号实例是唯一、不可改变的,这也是这个数据类型仅有的目的。
使用 Symbol()
创建新的 symbol
类型,可传入字符串作为描述。
let symbol1 = Symbol() // Symbol()
let symbol2 = Symbol(2) // Symbol(2)
let symbol3 = Symbol(true) // Symbol(true)
let symbol4 = Symbol('foo') // Symbol(foo)
// 使用 typeof
typeof symbol1 // "symbol"
// symbol 数据类型的唯一性
symbol1 == Symbol() // false
symbol2 == 2 // false
Symbol('foo') === Symbol('foo') // false
// 使用 new 运算符会报错
var sym = new Symbol() // Uncaught TypeError: Symbol is not a constructor
若真想使用 Symbol
包装对象,可以借用 Object()
函数:
let sym = Symbol("foo")
typeof sym; // "symbol"
let symObj = Object(sym)
typeof symObj; // "object"
其余属性及特性可去 MDN 或者 JavaScript 高级程序设计(第4版)查看哦。
Object
Object
就是一组数据和功能的集合,它是派生其他对象的基类,所以 Object
类型的所有属性和方法在派生的对象向同样存在。
Object
实例有以下属性和方法:
constructor
:用于创建当前对象的函数。hasOwnProperty(propertyName)
:返回一个布尔值,判断对象自身属性中是否具有指定的属性。isPrototypeOf(object)
:用于测试一个对象是否存在于另一个对象的原型链上。propertyIsEnumerable(propertyName)
:返回一个布尔值,检测对象是否可枚举。toLocaleString()
:返回对象的字符串表示,该字符串反映对象所在的本地话执行环节。toString()
:返回对象的字符串表示。valueOf()
:返回对象对应的字符串、数值或布尔值表示。通常与toString()
的返回值相同。
对象可以通过执行 new
操作符后跟要创建的对象类型的名称来创建,而创建 Object
类型的实例并为其添加属性和(或)方法,就可以创建自定
义对象,如下所示:
var o = new Object();
结语
ES6
新增:
- 字符串的模板字面量 —— ``
- 字符串的字符串插值 ——
${}
- 字符串的原始字符串 ——
String.raw
Symbol
参考文献
MDN web docs
JavaScript 高级程序设计(第4版)
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!