壹-数据类型
ECMAScript有6种简单的数据类型:undefined、null、boolean、number、string和symbol。其中symbol是ECMAScript新增的数据类型。
ECMAScript还有一种复杂数据类型:Object(对象)
1、typeof操作符
typeof操作符用来确定变量的数据类型。对一个值使用typeof,会返回下面的字符串之一:
值 | 含义 |
---|---|
undefined | 表示值未定义 |
boolean | 表示值为布尔值 |
string | 表示值为字符串 |
number | 表示值为数值 |
object | 表示值为对象 |
function | 表示值为函数 |
symbol | 表示值为符号 |
例如下面的例子:
let userName = 'zhangsan';
console.log(typeof userName); //输出 string
console.log(typeof(userName)); //输出 string
console.log(typeof 99); //输出 number
console.log(typeof null); //输出 Object
上述代码中的最后一行,可能令人比较费解,明明是个空值,为什么会输出object呢?这是因为特殊值null被认为是一个对空对象的引用。
2、undefined类型
undefined 类型只有一个值,就是特殊值 undefined。当使用 var 或 let 声明了变量但没有初始化时,就相当于给变量赋予了 undefined 值。
let age;
console.log(age == undefined); //输出为true
注意:声明了一个变量未赋值,和未定义一个变量是有区别的;
let userName;
//let age;
console.log(userName); //输出为 undefined
console.log(age); //报错,因为age未定义
3、null类型
null 类型同样只有一个值,即特殊值 null。逻辑上讲, null 值表示一个空对象指针,这也是给typeof 传一个 null 会返回"object"的原因。
let cat = null;
console.log(typeof cat); //输出 object
在定义将来要保存对象值的变量时,建议使用 null 来初始化,不要使用其他值。
undefined 值是由 null 值派生而来的,所以:
console.log(undefined == null); // true
但是他俩的用途是不一样的,可不能混淆。就像上述所说的,如果声明一个变量但是并未赋予其值,那么该变量就是undefined。但是null却不是这样,只要变量要保存对象,但是又没有那个对象存在,就先用null占着位置。
4、boolean类型
boolean(布尔值)类型是 ECMAScript 中使用最频繁的类型之一,有两个字面值: true 和 false。这两个布尔值与数值不同,true不等于1,false不等于0。
let see = false;
let say = true;
let message = 'Hello World!';
let messageBoolean = Boolean(message); //Boolean()转型函数
不同类型的值,可以通过Boolean() 转化为布尔值。见下表:
数据类型 | 转化为true | 转化为false |
---|---|---|
boolean | true | false |
string | 非空字符串 | "" (空字符串) |
number | 非零数值(包括无穷) | 0, NaN |
object | 任意对象 | null |
undefined | N/A(不存在) | undefined |
理解以上转换非常重要,因为像 if 等流控制语句会自动执行其他类型值到布尔值的转换。
let userName = 'lisi';
if(userName){
console.log('可以执行!')
}
5、number类型
number类型使用 IEEE 754 格式表示整数和浮点值(在某些语言中也叫双精度值,死去的计算机组成原理突然攻击我)。
可以使用的进制数又十进制,八进制,十六进制。
let initNum = 55; //十进制
let oNum = 070; //八进制,转化为十进制数是56;
let oNum1 = 079; //无效的八进制数,当做十进制数79处理
let oNum2 = 080; //无效的八进制数,当做十进制数80处理
let oxNum = 0xA; //十六进制10
let oxNum = 0x1f; //十六进制31
浮点数
要定义浮点数,数值中必须有小数点,而且小数点后面必须有一个数字。
let floatNum1 = 1.1;
let floatNum2 = 0.1;
let floatNum3 = .1; // 有效,但不推荐
在小数点后面没有数字的情况下,数值就会变成整数。因为浮点数存储站空间。
对于非常大或非常小的数值,浮点值可以用科学记数法来表示。
let floatNum = 3.125e7; //等于31250000
注意:ECMAScript表示值的时候是有限制的,并不是能够表示所有的值。ECMAScript 可以表示的最小数值保存在 Number.MIN_VALUE 中,这个值在多数浏览器中是 5e-324。可以表示的最大数值保存在Number.MAX_VALUE 中,这个值在多数浏览器中是 1.797 693 134 862 315 7e+308。
尽管超过表示范围的数值并不多见,但还是要注意下,要检测是否超过表示范围。
NaN,这个很常见嗷,兄弟们
有一个特殊的数值叫 NaN,意思是“不是数值”( Not a Number),用于表示本来要返回数值的操作 失败了(而不是抛出错误)。
console.log(0/0); // NaN
console.log(-0/+0); // NaN
//如果分子是非 0 值,分母是有符号 0 或无符号 0,则会返回 Infinity 或-Infinity
console.log(5/0); // Infinity
console.log(5/-0); // -Infinity
NaN有几个特点。任何涉及到NaN的操作都会返回NaN;NaN不等于任何值,包括NaN本身。
ECMAScript 提供了 isNaN()函数,用来判断一个值是否是NaN,如果是,它会尝试着把它变为数值。
console.log(isNaN(NaN)); // true
console.log(isNaN(10)); // false, 10 是数值
console.log(isNaN("10")); // false,可以转换为数值 10
console.log(isNaN("blue")); // true,不可以转换为数值
console.log(isNaN(true)); // false,可以转换为数值 1
6、数值转换
有三个函数可以将数值转化为非数值。
函数 | 功能特性 |
---|---|
Number() | 1、转型函数,可以用于任何类型的值; 2布尔值, true 转换为 1, false 转换为 0; 3、数值,直接返回; 4、null,返回 0; 5、undefined,返回 NaN |
parseInt() | 主要用于将字符串转化为数值, 通常在需要得到整数时可以优先使用 parseInt()函数 |
parseFloat() | 主要用于将字符串转化为数值 |
Number()函数转化字符串时:
①如果字符串包含数值字符,包括数值字符前面带加、减号的情况,则转换为一个十进制数值。因此, Number("1")返回 1, Number("123")返回 123, Number("011")返回 11(忽略前面的零)。 ②如果字符串包含有效的浮点值格式如"1.1",则会转换为相应的浮点值(同样,忽略前面的零)。 ③如果字符串包含有效的十六进制格式如"0xf",则会转换为与该十六进制值对应的十进制整 数值。 ④如果是空字符串(不包含字符),则返回 0。 ⑤如果字符串包含除上述情况之外的其他字符,则返回 NaN。
let num1 = Number("Hello world!"); // NaN
let num2 = Number(""); // 0
let num3 = Number("000011"); // 11
let num4 = Number(true); // 1
let num1 = parseInt("1234blue"); // 1234
let num2 = parseInt(""); // NaN
let num3 = parseInt("0xA"); // 10,解释为十六进制整数
let num4 = parseInt(22.5); // 22
let num5 = parseInt("70"); // 70,解释为十进制值
let num6 = parseInt("0xf"); // 15,解释为十六进制整数
let num1 = parseFloat("1234blue"); // 1234,按整数解析
let num2 = parseFloat("0xA"); // 0
let num3 = parseFloat("22.5"); // 22.5
let num4 = parseFloat("22.34.5"); // 22.34
let num5 = parseFloat("0908.5"); // 908.5
let num6 = parseFloat("3.125e7"); // 31250000
7、String类型
String(字符串)数据类型表示零或多个 16 位 Unicode 字符序列。
字符串可以使用双引号( ")、单引号( ')或反引号( `)标示。
let firstName = "John";
let lastName = 'Jacob';
let lastName = `Jingleheimerschmidt`
除了这些以外,还有字符字面量:
字面量 | 含义 |
---|---|
\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 等于希腊字 符"Σ" |
ECMAScript 中的字符串是不可变的( immutable),意思是一旦创建,它们的值就不能变了。要修改 某个变量中的字符串值,必须先销毁原始的字符串,然后将包含新值的另一个字符串保存到该变量。
let lang = "Java";
lang = lang + "Script";
//整个过程首先会分配一个足够容纳 10 个字符的空间,然后填充上"Java"和"Script"
转化为字符串
toString()方法。这个方法唯一的用途就是返回当前值的字符串等价物。
let age = 11;
let ageAsString = age.toString(); // 字符串"11"
let found = true;
let foundAsString = found.toString(); // 字符串"true"
toString()方法可见于数值、布尔值、对象和字符串值。null 和 undefined 值没有 toString()方法。
通过传入参数,可以得到数值的二进制、八进制、十六进制,或者其他任何有效基数的字符串表示。
let num = 10;
console.log(num.toString()); // "10"
console.log(num.toString(2)); // "1010"
console.log(num.toString(8)); // "12"
console.log(num.toString(10)); // "10"
console.log(num.toString(16)); // "a"
如果你不确定一个值是不是 null 或 undefined,可以使用 String()转型函数,它始终会返回表示相应类型值的字符串。String()函数遵循下面的规则:
1、如果值有 toString()方法,则调用该方法(不传参数)并返回结果。
2、如果值是 null或undefined,返回"null" 或 "undefined"。
let value1 = 10;
let value2 = true;
let value3 = null;
let value4;
console.log(String(value1)); // "10"
console.log(String(value2)); // "true"
console.log(String(value3)); // "null"
console.log(String(value4)); // "undefined"
ECMAScript 6 新增了使用模板字面量定义字符串的能力。与使用单引号或双引号不同,模板字面量保留换行字符,可以跨行定义字符串。模板字面量在定义模板时特别有用,比如定义HTML代码。格式正确的模板字符串看起来可能会缩进不当。
let myMultiLineString = 'first line\nsecond line';
let myMultiLineTemplateLiteral = `first line
second line`;
console.log(myMultiLineString);
// first line
// second line"
console.log(myMultiLineTemplateLiteral);
// first line
// second line
console.log(myMultiLineString === myMultiLinetemplateLiteral); // true
let pageHTML = `
<div>
<a href="#">
<span>Jake</span>
</a>
</div>`;
字符串插值
模板字面量最常用的一个特性是支持字符串插值,也就是可以在一个连续定义中插入一个或多个值。模板字面量在定义时立即求值并转换为字符串。
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()强制转型为字符串。
8、Symbol类型
Symbol(符号)是 ECMAScript 6 新增的数据类型。符号实例是唯一、不可变的。符号的用途是确保对象属性使用唯一标识符,不会发生属性冲突的危险。
符号需要使用 Symbol()函数初始化。使用typeof操作符,会返回symbol。
let sym = Symbol();
console.log(typeof sym); // symbol
调用 Symbol()函数时,也可以传入一个字符串参数作为对符号的描述( description),将来可以通过这个字符串来调试代码。但是,这个字符串参数与符号定义或标识完全无关。
//定义符号
let genericSymbol = Symbol();
let otherGenericSymbol = Symbol();
//定义符号,并且传入一个字符串参数作为对符号的描述
let fooSymbol = Symbol('foo');
let otherFooSymbol = Symbol('foo');
console.log(genericSymbol == otherGenericSymbol); // false
console.log(fooSymbol == otherFooSymbol); // false
你只要创建 Symbol()实例并将其用作对象的新属性,就可以保证它不会覆盖已有的对象属性,无论是符号属性还是字符串属性。
let genericSymbol = Symbol();
console.log(genericSymbol); // Symbol()
let fooSymbol = Symbol('foo');
console.log(fooSymbol); // Symbol(foo);
(PS:这一部分看不懂,回头再看看,再重新记笔记)
9、Object类型
ECMAScript 中的对象其实就是一组数据和功能的集合。通过 new 操作符后跟对象类型的名称来创建。开发者可以通过创建 Object 类型的实例来创建自己的对象,然后再给对象添加属性和方法。
let o = new Object();