《JavaScript高级程序设计》Nicholas C.Zakas著
第1章 JavaScript简介
第2章 在HTML中使用JavaScript
标签:
<script>
属性:
type=”text/javascript”
src=”……”
async 只对外部脚步文件有效,立即下载脚步,异步加载。
defer 只对外部脚步文件有效,立即下载脚本,延迟执行。
外部文件的优势:
- 可维护性
- 可缓存
- 适应未来
注意:
- 不要在代码中的任何地方出现“</script>”字符串
- 带有src属性的<script>元素不应该在其<script>和</script>标签之间包含额外的JS代码,嵌入的代码会被忽视。
- 现代web应用程序一般都把全部JS引用放在<body>元素中页面内容的后面。
第3章 基本概念
3.1 语法
严格模式:
在严格模式下,ES3中的一些不确定行为将得到处理,而对于某些不安全的操作也会抛出错误。
启用严格模式,只需在顶端或函数内部的上方包含代码:
"use strict";
注意:
/*
* 这是一个多行的注释
* 之所以第二行第三行开头都以一个不必要的*开头,是为了提高注释的可读性
*/
3.3 变量
松散类型:
JS的变量都是松散类型,可用于保存任何类型的数据。
var操作符定义的变量将成为定义该变量的作用域中的局部变量。
省略var操作符,会创建一个全局变量,但不推荐这么做。
3.4 数据类型
基本数据类型:
Undefined、Null、Boolean、Number、String
复杂数据类型:
Object
typeof:
结果 | 情况 | 结果 | 情况 |
---|---|---|---|
undefined | 未声明或未初始化 | number | 数值 |
boolean | 布尔值 | object | 对象或null |
string | 字符串 | function | 函数 |
Undefined类型:
使用var声明变量但为对其加以初始化时,变量的值就是undefined。
即使未初始化的变量会自动被赋予undefined值,但显示地初始化变量仍然是明智的选择。这样做的话,当typeof操作符返回“undefined”时,我们就知道被检测的变量是未声明,还是未初始化。
Null类型:
唯一一个值null。
从逻辑的角度来看,null值表示一个空对象指针,从而有typeof检测null结果为object。
如果定义的变量准备在将来用于保存对象,那么最好将该对象初始化为null,而不是其他值。
实际上undefined值派生自null值,也就是说undefined==null的值为true。
Boolean:
Boolean()将一个值转换为其对应的Boolean值
注意,在运算过程中,这个转换是自动的。
var messageAsBoolean = Boolean(message);
数据类型 | 转换为true | 转换为false |
---|---|---|
Boolean | true | false |
String | 任何非空字符 | “”(空字符串) |
Number | 任何非零数字值 | 0和NaN |
Object | 任何对象 | null |
Undefined | 不适用 | undefined |
Number类型:
使用IEEE754格式来表示整数和浮点数
由于保存浮点数值需要的内存空间是保存整数值的两倍,因此ECMAScript会不失时机地将浮点数值转换为整数值。
数值的表示范围Number.MIN_VALUE~Number.MAX_VALUE
超过范围,数值将会被自动转换为Infinity
isFinite()用于检测参数是否有穷。
NaN即非数值用于表示一个本来要返回数值的操作数未返回数值的情况。
任何涉及NaN的操作都返回NaN。
NaN与任何值都不相等,包括它本身。
isNaN()检测参数是否为一个数值。(在接收到一个值的时候,会尝试将这个值转换为数值)
数值转换
方法 | true | 12 | NaN | null | undefined |
---|---|---|---|---|---|
Number() | 1 | 12 | NaN | 0 | NaN |
parseInt() | NaN | 12 | NaN | NaN | NaN |
parseFloat() | NaN | 12 | NaN | NaN | NaN |
Boolean() | true | true | false | false | false |
.toString() | “true” | “12” | “NaN” | 不适用 | 不适用 |
String() | “true” | “12” | “NaN” | “null” | “undefined” |
方法 | “7” | “021” | “0xf” | “” | “1a” | “1.2.3” | “a” |
---|---|---|---|---|---|---|---|
Number() | 7 | 21 | 15 | 0 | NaN | NaN | NaN |
parseInt() | 7 | 21 | 15 | NaN | 1 | 1 | NaN |
parseFloat() | 7 | 21 | 0 | NaN | 1 | 1.2 | NaN |
Boolean() | true | true | true | false | true | true | true |
.toString() | “7” | “021” | “0xf” | “” | “1a” | “1.2.3” | “a” |
String() | “7” | “021” | “0xf” | “” | “1a” | “1.2.3” | “a” |
注意:
- ++、–、+、-四则运算,JS都会自动将操作数按Number()转换。
-对于Number() ,如果操作数是对象,则先调用对象的valueOf()方法,将得到的值进行转化,若转化值是NaN,再调用对象的toString()方法,重复之前的步骤。 - 对于parseInt(),它会忽略字符串前面的空格,直到找到第一个非空字符。
- 对于parseInt(),在ES5中,已不具有直接解析八进制值的能力,因此在无可选参数的情况下,前导0会被认为无效。
- 对于parseInt(),可选参数表明被转换参数是用几进制表示的,所以转换结果都是十进制表示。
- 对于parseFloat(),始终忽视前导0,始终将十六进制值解析为0。
- 对于.toString(),可选参数表明转换结果用几进制表示。
String类型:
String类型是由零或多个16位Unicode字符组成的字符序列。
注意:
- 如果字符串中包含双字节字符,那么length属性可能不会精确地返回字符串中的字符数目。
- ES中的字符串是不可变的,要改变某个变量保存的字符串,首先要销毁原来的字符串,再用一个包含新值的字符串填充该变量。
Object对象:
Object类型是ES中所有实例的基础,其每一个实例都具有以下属性和方法:
属性或方法 | 作用 |
---|---|
constructor | 保存用于创建当前对象的函数,var o = new Object();中便是构造函数Object(); |
hasOwnProperty(pName) | 检查给定的属性是否存在于当前对象的实例中,而不是在实例的原型中 |
isPrototypeOf(Object) | 检查当前的对象是否是传入对象的原型 |
propertyIsEnumerable(pName) | 用于检查指定属性是否能够使用for-in进行枚举 |
.toLocaleString() | 返回对象的字符串表示,该字符串与执行环境的地区对应 |
.toString() | 返回对象的字符串表示 |
.valueOf() | 返回对象的字符串、数值或布尔值表示 |
3.5 操作符
一元操作符和位操作符
两者都会对非数值操作数自动进行Number()转换。
ES中所有的数值都以IEEE754 64位格式存储,但位操作符并不直接操作64位的值,而是先将64位的值转换成32位的整数,然后执行操作,最后再将结果转换回64位。
转换过程导致了一个副效应,即在对特殊的NaN和Infinity值应用位操作时,这两个值都会被当成0来处理。
布尔操作符
逻辑非得返回值是布尔值,操作时首先会将操作数转换为一个布尔值,然后对其求反。
逻辑与和逻辑或的返回值未必是布尔值,两者都是短路操作。
对于逻辑与:第一个操作数是false、NaN、null、undefined则返回这些,反之就返回第二个操作数。
对于逻辑或:两个操作数都是false、NaN、null、undefined则返回这些,如果第一个操作数为true返回第一个,反之,则返回第二个。
可以利用逻辑或来避免为变量赋null或undefined。
乘性操作符
- 3个乘性操作符:*/%,如果操作数为非数值,会自动进行类型转换(Number())
- Infinity * 0 = NaN
- 0/0=NaN
- 非零数/0=Infinity
- 有限数%0=NaN
加性操作符
对于加法:
操作数有字符串,则都转为字符串拼接(toString(),只有undefined和null才用String())。
操作数没字符串,没数值,全转为数值(Number()),常规计算。
对于减法:
操作数是字符串、布尔值、null或undefined,则先后在后台调用Number()进行转换。
操作数是对象,则调用对象的valueOf()方法获得该对象的数值,没有该方法则调用toString()方法
关系操作符
操作数A | 操作数B | 结果 |
---|---|---|
布尔值 | 将A转换为数值 | |
数值 | 数值 | 数值比较 |
字符串 | 字符串 | 字符编码值比较 |
数值 | B转换为数值 | |
对象 | 调用valueOf(),如果无,调用toString() | |
NaN | false |
相等操作符
相等和不相等(==)先转换,再比较。
全等和不全等(===)仅比较。
操作数A | 操作数B | 结果 |
---|---|---|
布尔值 | 将A转换为数值 | |
字符串 | 数值 | 将A转换为数值 |
对象 | 非对象 | 调用A的valueOf() |
对象 | 对象 | 比较它们是不是同一个对象 |
null | undefined | true |
NaN | false | |
undefined | 0 | false |
null | 0 | false |
语句
for-in循环输出的属性名的顺序是不可预测的。
switch语句中使用任何数据类型,每个case的值不一定是常量,还可以是变量,甚至是表达式。
switch语句在比较值的时候用的是全等操作符。
函数
- ES函数不介意传递多少个参数,也不在乎传进来的参数是什么数据类型。
- 因为ES函数中的参数在内部是用一个数组来表示的,并可以通过arguments对象来访问这个参数数组。
- 也就是说,命名参数只是提供便利,但不是必须的。
- arguments对象可以与命名参数一起使用。
- arguments访问的参数值与对应的命名参数的值保持同步,若一者做出修改,另一者也会发生改变。
- 但是这个参数数组命名参数的内存空间是独立的。
- 如果只传入了一个参数,那么arguments[1]设置的值不会反映到命名参数中(即使有第二个命名参数)。
- 没有传递值的命名参数将自动被赋予undefined值。
- ES中的所有参数传递的都是值,不可能通过引用传递参数。
- 这是因为arguments对象的长度是由传入的参数个数决定的,不是由定义函数的命名参数的个数决定的。
- 由于ES的函数不存在签名(接受参数的类型和数量),所以在ES中重载是不存在。
- 在ES中,如果定义了两个名字相同的函数,那么该名字属于后定义的函数。
- 如果要模仿方法的重载,那么通过检测传入函数中的参数的数量和类型做出不同的反应。