JavaScript高级程序设计(4)
第3章 语言基础(2)数据类型
### 3.4 数据类型 30 ##### 3.4.1 typeof操作符 对一个值使用typeof操作符会返回下列字符串之一: ❑ "undefined"表示值未定义; ❑ "boolean"表示值为布尔值; ❑ "string"表示值为字符串; ❑ "number"表示值为数值; ❑ "object"表示值为对象(而不是函数)或null; ❑ "function"表示值为函数; ❑ "symbol"表示值为符号。 ```javascript let message = "some string"; console.log(typeof message); // "string" console.log(typeof(message)); // "string" console.log(typeof 95); // "number" ``` ##### 3.4.2 Undefined类型 > Undefined类型只有一个值,就是特殊值undefined。当使用var或let声明了变量但没有初始化时,就相当于给变量赋予了undefined值。 ```javascript let message; console.log(message == undefined); // true ``` ##### 3.4.3 Null类型 Null类型同样只有一个值,即特殊值null。逻辑上讲,null值表示一个空对象指针,这也是给typeof传一个null会返回"object"的原因 ```javascript let car = null; console.log(typeof car); // "object" ``` undefined值是由null值派生而来的,因此ECMA-262将它们定义为表面上相等,如下面的例子所示: ```javascript console.log(null == undefined); // true ``` 即使null和undefined有关系,它们的用途也是完全不一样的。如前所述,永远不必显式地将变量值设置为undefined。但null不是这样的。任何时候,只要变量要保存对象,而当时又没有那个对象可保存,就要用null来填充该变量。这样就可以保持null是空对象指针的语义,并进一步将其与undefined区分开来。 null是一个假值。因此,如果需要,可以用更简洁的方式检测它。不过要记住,也有很多其他可能的值同样是假值。所以一定要明确自己想检测的就是null这个字面值,而不仅仅是假值。 ```javascript let message = null; let age; if (message) { // 这个块不会执行 } if (! message) { // 这个块会执行 } if (age) { // 这个块不会执行 } if (! age) { // 这个块会执行 } ``` ##### 3.4.4 Boolean类型 Boolean(布尔值)类型是ECMAScript中使用最频繁的类型之一,有两个字面值:true和false。这两个布尔值不同于数值,因此true不等于1,false不等于0。 注意,布尔值字面量true和false是区分大小写的,因此True和False(及其他大小混写形式)是有效的标识符,但不是布尔值。 ```javascript let found = true; let lost = false; //要将一个其他类型的值转换为布尔值,可以调用特定的Boolean()转型函数 let message = "Hello world! "; let messageAsBoolean = Boolean(message); ```  ##### 3.4.5 Number类型 1.浮点值 ```javascript let floatNum1 = 1.1; let floatNum2 = 0.1; let floatNum3 = .1; // 有效,但不推荐 let floatNum1 = 1.; // 小数点后面没有数字,当成整数1 处理 let floatNum2 = 10.0; // 小数点后面是零,当成整数10 处理 let floatNum = 3.125e7; // 浮点值可以用科学记数法来表示,等于31250000 // 别这么干! if (a + b == 0.3) { console.log("You got 0.3."); } 这里检测两个数值之和是否等于0.3。如果两个数值分别是0.05和0.25,或者0.15和0.15,那没问题。但如果是0.1和0.2,如前所述,测试将失败。因此永远不要测试某个特定的浮点值。 ``` 2.值的范围 ECMAScript可以表示的最小数值保存在Number.MIN_VALUE中,这个值在多数浏览器中是5e-324;可以表示的最大数值保存在Number.MAX_VALUE中,这个值在多数浏览器中是1.797693134862315 7e+308。如果某个计算得到的数值结果超出了JavaScript可以表示的范围,那么这个数值会被自动转换为一个特殊的Infinity(无穷)值。任何无法表示的负数以-Infinity(负无穷大)表示,任何无法表示的正数以Infinity(正无穷大)表示。 ```javascript let result = Number.MAX_VALUE + Number.MAX_VALUE; console.log(isFinite(result)); // false ``` 3.NaN 有一个特殊的数值叫NaN,意思是“不是数值”(Not a Number),用于表示本来要返回数值的操作失败了(而不是抛出错误) ```javascript console.log(0/0); // NaN console.log(-0/+0); // NaN console.log(5/0); // Infinity console.log(5/-0); // -Infinity ``` NaN有几个独特的属性。首先,任何涉及NaN的操作始终返回NaN(如NaN/10),在连续多步计算时这可能是个问题。其次,NaN不等于包括NaN在内的任何值。 ```javascript console.log(NaN == NaN); // false 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 ``` > 注意 虽然不常见,但isNaN()可以用于测试对象。此时,首先会调用对象的valueOf()方法,然后再确定返回的值是否可以转换为数值。如果不能,再调用toString()方法,并测试其返回值。这通常是ECMAScript内置函数和操作符的工作方式。 4.数值转换 有3个函数可以将非数值转换为数值:Number()、parseInt()和parseFloat()。Number()是转型函数,可用于任何数据类型。后两个函数主要用于将字符串转换为数值。 Number()函数基于如下规则执行转换: - 布尔值,true转换为1,false转换为0。 - 数值,直接返回。 - null,返回0。 - undefined,返回NaN。 - 对象,调用valueOf()方法,并按照上述规则转换返回的值。如果转换结果是NaN,则调用toString()方法,再按照转换字符串的规则转换。 - 字符串,应用以下规则。 - 如果字符串包含数值字符,包括数值字符前面带加、减号的情况,则转换为一个十进制数值。因此,Number("1")返回1, Number("123")返回123, Number("011")返回11(忽略前面的零)。 - 如果字符串包含有效的浮点值格式如"1.1",则会转换为相应的浮点值(同样,忽略前面的零)。 - 如果字符串包含有效的十六进制格式如"0xf",则会转换为与该十六进制值对应的十进制整数值。 - 如果是空字符串(不包含字符),则返回0。 - 如果字符串包含除上述情况之外的其他字符,则返回NaN。 ```javascript let num1 = Number("Hello world! "); // NaN let num2 = Number(""); // 0 let num3 = Number("000011"); // 11 let num4 = Number(true); // 1 ``` ```javascript 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 = parseInt("10", 2); // 2,按二进制解析 let num2 = parseInt("10", 8); // 8,按八进制解析 let num3 = parseInt("10", 10); // 10,按十进制解析 let num4 = parseInt("10", 16); // 16,按十六进制解析 ``` ```javascript 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 ``` ##### 3.4.6 String类型 String(字符串)数据类型表示零或多个16位Unicode字符序列。字符串可以使用双引号(")、单引号(')或反引号(`)标示,因此下面的代码都是合法的: ```javascript let firstName = "John"; let lastName = 'Jacob'; let lastName = `Jingleheimerschmidt` ``` 1.字符字面量 字符串数据类型包含一些字符字面量,用于表示非打印字符或有其他用途的字符,如\n、\t、\b、\r、\f等,这些字符字面量可以出现在字符串中的任意位置,且可以作为单个字符被解释。 2.字符串的特点 ECMAScript中的字符串是不可变的(immutable),意思是一旦创建,它们的值就不能变了。要修改某个变量中的字符串值,必须先销毁原始的字符串,然后将包含新值的另一个字符串保存到该变量,如下所示: ```javascript let lang = "Java"; lang = lang + "Script"; ``` 3.转换为字符串 ```javascript let age = 11; let ageAsString = age.toString(); // 字符串"11" let found = true; let foundAsString = found.toString(); // 字符串"true" ``` 如果你不确定一个值是不是null或undefined,可以使用String()转型函数,它始终会返回表示相应类型值的字符串。String()函数遵循如下规则。 ❑ 如果值有toString()方法,则调用该方法(不传参数)并返回结果。 ❑ 如果值是null,返回"null"。 ❑ 如果值是undefined,返回"undefined" ```javascript 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" ``` 4.模板字面量 ECMAScript 6新增了使用模板字面量定义字符串的能力。与使用单引号或双引号不同,模板字面量保留换行字符,可以跨行定义字符串 ```javascript let pageHTML = ` <div> <a href="#"> <span>Jake</span> </a> </div>`; ``` 5.字符串插值 模板字面量最常用的一个特性是支持字符串插值,也就是可以在一个连续定义中插入一个或多个值。所有插入的值都会使用toString()强制转型为字符串,而且任何JavaScript表达式都可以用于插值。嵌套的模板字符串无须转义。 ```javascript let foo = { toString: () => 'World' }; console.log(`Hello, ${ foo }! `); // Hello, World! ``` 6.模板字面量标签函数 模板字面量也支持定义标签函数(tag function),而通过标签函数可以自定义插值行为。标签函数会接收被插值记号分隔后的模板和对每个表达式求值的结果。 ```javascript let a = 6; let b = 9; functionsimpleTag(strings, ...expressions){ console.log(strings); for(const expression of expressions) { console.log(expression); } return 'foobar'; } let taggedResult = simpleTag`${ a } + ${ b } = ${ a + b }`; // ["", " + ", " = ", ""] // 6 // 9 // 15 console.log(taggedResult); // "foobar" ``` 7.原始字符串 使用模板字面量也可以直接获取原始的模板字面量内容(如换行符或Unicode字符),而不是被转换后的字符表示。为此,可以使用默认的String.raw标签函数: ```javascript // 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" // 对实际的换行符来说是不行的 // 它们不会被转换成转义序列的形式 console.log(`first line second line`); // first line // second line console.log(String.raw`first line second line`); // first line // second line ``` ##### 3.4.7 Symbol类型 Symbol(符号)是ECMAScript 6新增的数据类型。符号是原始值,且符号实例是唯一、不可变的。符号的用途是确保对象属性使用唯一标识符,不会发生属性冲突的危险。 1.符号的基本用法 ```javascript let sym = Symbol(); console.log(typeof sym); // symbol 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()实例并将其用作对象的新属性,就可以保证它不会覆盖已有的对象属性,无论是符号属性还是字符串属性。 最重要的是,Symbol()函数不能与new关键字一起作为构造函数使用。这样做是为了避免创建符号包装对象,像使用Boolean、String或Number那样,它们都支持构造函数且可用于初始化包含原始值的包装对象 2.使用全局符号注册表 ```javascript let fooGlobalSymbol = Symbol.for('foo'); console.log(typeof fooGlobalSymbol); // symbol ``` 3.使用符号作为属性 4.常用内置符号 5.Symbol.asyncIterator 6.Symbol.hasInstance 7.Symbol.isConcatSpreadable 8.Symbol.iterator 9.Symbol.match 10.Symbol.replace 11.Symbol.search 12.Symbol.species 13.Symbol.split 14.Symbol.toPrimitive 15.Symbol.toStringTag 16.Symbol.unscopables ##### 3.4.8 Object类型 ECMAScript中的对象其实就是一组数据和功能的集合。对象通过new操作符后跟对象类型的名称来创建。开发者可以通过创建Object类型的实例来创建自己的对象,然后再给对象添加属性和方法: ```javascript let o = new Object(); let o = new Object; // 合法,但不推荐 ``` 每个Object实例都有如下属性和方法: - constructor:用于创建当前对象的函数。在前面的例子中,这个属性的值就是Object()函数。 - hasOwnProperty(propertyName):用于判断当前对象实例(不是原型)上是否存在给定的属性。要检查的属性名必须是字符串(如o.hasOwnProperty("name"))或符号。 - isPrototypeOf(object):用于判断当前对象是否为另一个对象的原型。(第8章将详细介绍原型。) - propertyIsEnumerable(propertyName):用于判断给定的属性是否可以使用(本章稍后讨论的)for-in语句枚举。与hasOwnProperty()一样,属性名必须是字符串。 - toLocaleString():返回对象的字符串表示,该字符串反映对象所在的本地化执行环境。 - toString():返回对象的字符串表示。 - valueOf():返回对象对应的字符串、数值或布尔值表示。通常与toString()的返回值相同。
顶部
收展
底部
[TOC]
目录
第1章 JavaScript简介
第2章 在 HTML中使用JavaScript
第3章 语言基础(1)语法变量
第3章 语言基础(2)数据类型
第3章 语言基础(3)操作符
第3章 语言基础(4)语句
第4章 变量、作用域与内存
第5章 基本引用类型
第6章 集合引用类型
第7章 迭代器与生成器
第8 章对象、类与面向对象编程
第9章 代理与反射
第10章 函数
第11章 期约与异步函数
第12章 BOM
第13章 客户端检测
第14章 DOM
第15章 DOM 扩展
第16章 DOM2 和 DOM3
第17章 事件
第18章 动画与 Canvas 图形
第19章 表单脚本
第20章 JavaScript API
第21章 错误处理与调试
第22章 处理 XML
第23章 JSON
第24章 网络请求与远程资源
第25章 客户端存储
第26章 模块
第27章 工作者线程
第28章 最佳实践
相关推荐
WebSocket