《JavaScript高级程序设计》读书笔记
1.JavaScript实现
JavaScript 与 ECMAScript 之间的关系:
* 核心(ECMAScript)
语法
类型
语句
关键字
保留字
操作符
对象* 文档对象模型(DOM)
是针对 XML 但经过扩展用于 HTML 的应用程序编
程接口(API,Application Programming Interface)。DOM 把整个页面映射为一个多层节点结构。
DOM1 (目标:DOM1 级的目标主要是映射文档的结构): DOM HTML +DOM Core
DOM2(在
原来 DOM 的基础上又扩充了(DHTML 一直都支持的)鼠标和用户界面事件、范围、遍历(迭代 DOM
文档的方法)等细分模块,而且通过对象接口增加了对 CSS(Cascading Style Sheets,层叠样式表)的
支持。
DOM 视图:定义了跟踪不同文档(例如,应用 CSS 之前和之后的文档)视图的
接口
DOM 事件:定义了事件和事件处理的接口
DOM 样式:定义了基于 CSS 为元素应用样式的接口
DOM 遍历和范围:定义了遍历和操作文档树的接口
)
* 浏览器对象模型(BOM) 弹出新浏览器窗口的功能;
移动、缩放和关闭浏览器窗口的功能;
提供浏览器详细信息的 navigator 对象;
提供浏览器所加载页面的详细信息的 location 对象;
提供用户显示器分辨率详细信息的 screen 对象;
对 cookies 的支持;
像 XMLHttpRequest 和 IE的 ActiveXObject 这样的自定义对象。
JavaScript 是一种专为与网页交互而设计的脚本语言,由下列三个不同的部分组成:
ECMAScript,由 ECMA-262 定义,提供核心语言功能;
文档对象模型(DOM),提供访问和操作网页内容的方法和接口;
浏览器对象模型(BOM),提供与浏览器交互的方法和接口。
JavaScript 的这三个组成部分,在当前五个主要浏览器(IE、Firefox、Chrome、Safari 和 Opera)中都得到了不同程度的支持。其中,所有浏览器对 ECMAScript 第 3 版的支持大体上都还不错,而对
ECMAScript 5 的支持程度越来越高,但对 DOM 的支持则彼此相差比较多。对已经正式纳入 HTML5 标
准的 BOM来说,尽管各浏览器都实现了某些众所周知的共同特性,但其他特性还是会因浏览器而异。
2.在 HTML 中使用 JavaScript
<script> 元素定义了下列 6 个属性:
async :可选。表示应该立即下载脚本,但不应妨碍页面中的其他操作,比如下载其他资源或
等待加载其他脚本。只对外部脚本文件有效。( async 属性的目的是不让页面等待两个脚本下载和执行,从而异步加载页面其他内容。
为此,建议异步脚本不要在加载期间修改 DOM)
charset :可选。表示通过 src 属性指定的代码的字符集。由于大多数浏览器会忽略它的值,
因此这个属性很少有人用。
defer :可选。表示脚本可以延迟到文档完全被解析和显示之后再执行。只对外部脚本文件有
效。IE7 及更早版本对嵌入脚本也支持这个属性(立即下载延迟到浏览器遇到 </html> 标签后再执行
HTML5 规范要求脚本按照它们出现的先后顺序执行,因此第一
个延迟脚本会先于第二个延迟脚本执行,而这两个脚本会先于 DOMContentLoaded 事件(详见第 13 章)
执行。在现实当中,延迟脚本并不一定会按照顺序执行,也不一定会在 DOMContentLoaded 事件触发
前执行
)。
language :已废弃。原来用于表示编写代码使用的脚本语言(如 JavaScript 、 JavaScript1.2或 VBScript )。大多数浏览器会忽略这个属性,因此也没有必要再用了。
src :可选。表示包含要执行代码的外部文件。
type :可选。可以看成是 language 的替代属性;表示编写代码使用的脚本语言的内容类型(也
称为 MIME 类型)。虽然 text/javascript 和 text/ecmascript 都已经不被推荐使用,但人
们一直以来使用的都还是 text/javascript 。实际上,服务器在传送 JavaScript 文件时使用的
MIME 类型通常是 application/x–javascript ,但在 type 中设置这个值却可能导致脚本被
忽略。另外,在非IE浏览器中还可以使用以下值: application/javascript 和 application/ecmascript 。考虑到约定俗成和最大限度的浏览器兼容性,目前 type 属性的值依旧还是
text/javascript 。不过,这个属性并不是必需的,如果没有指定这个属性,则其默认值仍为
text/javascript 。使用 <script> 元素的方式有两种:直接在页面中嵌入 JavaScript 代码和包含外部 JavaScript
文件。
在使用 <script> 元素嵌入 JavaScript 代码时,只须为 <script> 指定 type 属性。然后,像下面这
样把 JavaScript 代码直接放在元素内部即可:
<script type="text/javascript">
function sayHi(){
alert("Hi!");
}
</script>
包含在 <script> 元素内部的 JavaScript 代码将被从上至下依次解释(下载,解析,执行完成)。就拿前面这个例子来说,解释
器会解释一个函数的定义,然后将该定义保存在自己的环境当中。在解释器对 <script> 元素内部的所
有代码求值完毕以前,页面中的其余内容都不会被浏览器加载或显示。与解析嵌入式 JavaScript 代码一样,
在解析外部 JavaScript 文件(包括下载该文件)时,页面的处理也会暂时停止。
通过 <script> 元素的 src 属性还可以包含来自外部域的 JavaScript 文件。这一点既让
<script> 元素倍显强大,又让它备受争议。在这一点上, <script> 与 <img> 元素非常相似,即它的 src
属性可以是指向当前 HTML 页面所在域之外的某个域中的完整 URL,例如:
<script type="text/javascript" src="http://www.somewhere.com/afile.js"></script>
这样,位于外部域中的代码也会被加载和解析,就像这些代码位于加载它们的页面中一样。利用这
一点就可以在必要时通过不同的域来提供 JavaScript 文件。
把 JavaScript 插入到 HTML 页面中要使用 <script> 元素。使用这个元素可以把 JavaScript 嵌入到
HTML页面中,让脚本与标记混合在一起;也可以包含外部的 JavaScript文件。而我们需要注意的地方有:
在包含外部 JavaScript 文件时,必须将 src 属性设置为指向相应文件的 URL。而这个文件既可
以是与包含它的页面位于同一个服务器上的文件,也可以是其他任何域中的文件。
所有 <script> 元素都会按照它们在页面中出现的先后顺序依次被解析。在不使用 defer 和
async 属性的情况下,只有在解析完前面 <script> 元素中的代码之后,才会开始解析后面
<script> 元素中的代码。
由于浏览器会先解析完不使用 defer 属性的 <script> 元素中的代码,然后再解析后面的内容,
所以一般应该把 <script> 元素放在页面最后,即主要内容后面, </body> 标签前面。
使用 defer 属性可以让脚本在文档完全呈现之后再执行。延迟脚本总是按照指定它们的顺序执行。
使用 async 属性可以表示当前脚本不必等待其他脚本,也不必阻塞文档呈现。不能保证异步脚
本按照它们在页面中出现的顺序执行。
另外,使用 <noscript> 元素可以指定在不支持脚本的浏览器中显示的替代内容。但在启用了脚本
的情况下,浏览器不会显示 <noscript> 元素中的任何内容。
3.JavaScript基本概念
下会导致抛出 ReferenceError 错误(未使用var let const操作符)
ECMAScript 中有 5 种简单数据类型(也称为基本数据类型): Undefined 、 Null 、 Boolean 、 Number
和 String 。还有 1种复杂数据类型—— Object
八进制字面量在严格模式下是无效的,会导致支持的 JavaScript 引擎抛出错误。
( "use strict"(es5的写法,规范es3)
070 会报错 Uncaught SyntaxError: Octal literals are not allowed in strict mode.
)
在进行算术计算时,所有以八进制和十六进制表示的数值最终都将被转换成十进制数值。
保存浮点数值需要的内存空间是保存整数值的两倍
6000000.0000000000000006700000000000000000000000000000000000000000000002587000000000000005875780000000000000000000000000000000000000000000000000000000000000005400000054
==6000000
永远不
要测试某个特定的浮点数值
如果某次计算返回了正或负的 Infinity 值,那么该值将无法继续参与下一次的计算,
因为 Infinity 不是能够参与计算的数值。要想确定一个数值是不是有穷的(换句话说,是不是位于最
小和最大的数值之间),可以使用 isFinite() 函数
isNaN会转换操作数据的类型
isNaN("true")
true
isNaN(true)
false
要把某个值转换为字符串,可以使用加号操作符把它与一个字符串( "" )加在一起。
数值、布尔值、对象和字符串值(没错,每个字符串也都有一个 toString() 方法,该方法返回字
符串的一个副本)都有 toString() 方法。但 null 和 undefined 值没有这个方法。调用数值的 toString() 方法时,可
以传递一个参数:输出数值的基数。默认情况下, toString() 方法以十进制格式返回数值的字符串表
示。而通过传递基数, toString() 可以输出以二进制、八进制、十六进制,乃至其他任意有效进制格
式表示的字符串值。下面给出几个例子:
var num = 10;
alert(num.toString()); // "10"
alert(num.toString(2)); // "1010"
alert(num.toString(8)); // "12"
alert(num.toString(10)); // "10"
alert(num.toString(16)); // "a"
在不知道要转换的值是不是 null 或 undefined 的情况下,还可以使用转型函数 String() ,这个
函数能够将任何类型的值转换为字符串。 String() 函数遵循下列转换规则:
如果值有 toString() 方法,则调用该方法(没有参数)并返回相应的结果;
如果值是 null ,则返回 "null" ;
如果值是 undefined ,则返回 "undefined" 。
下面再看几个例子:
var value1 = 10;
var value2 = true;
var value3 = null;
var value4;
alert(String(value1)); // "10"
alert(String(value2)); // "true"
alert(String(value3)); // "null"
alert(String(value4)); // "undefined"
Object 类型
ECMAScript 中的对象其实就是一组数据和功能的集合。对象可以通过执行 new 操作符后跟要创建
的对象类型的名称来创建。而创建 Object 类型的实例并为其添加属性和(或)方法,就可以创建自定
义对象,如下所示:
var o = new Object();
parseInt与toString()的区别
parseInt是按照参数解析成十进制
toString()是按传进的参数进制转换
逻辑非
逻辑非操作符由一个叹号(!)表示,可以应用于 ECMAScript 中的任何值。无论这个值是什么数据类型,这个操作符都会返回一个布尔值。逻辑非操作符首先会将它的操作数转换为一个布尔值,然后再
对其求反。也就是说,逻辑非操作符遵循下列规则:
如果操作数是一个对象,返回 false ;
如果操作数是一个空字符串,返回 true ;
如果操作数是一个非空字符串,返回 false ;
如果操作数是数值 0,返回 true ;
如果操作数是任意非 0 数值(包括 Infinity ),返回 false ;
如果操作数是 null ,返回 true ;
如果操作数是 NaN ,返回 true ;
如果操作数是 undefined ,返回 true 。
下面几个例子展示了应用上述规则的结果:
alert(!false); // true
alert(!"blue"); // false
alert(!0); // true
alert(!NaN); // true
alert(!""); // true
alert(!12345); // false
LogicalNotExample01.htm
逻辑非操作符也可以用于将一个值转换为与其对应的布尔值。而同时使用两个逻辑非操作符,实际
上就会模拟 Boolean() 转型函数的行为。其中,第一个逻辑非操作会基于无论什么操作数返回一个布
尔值,而第二个逻辑非操作则对该布尔值求反,于是就得到了这个值真正对应的布尔值。当然,最终结
果与对这个值使用 Boolean() 函数相同,如下面的例子所示:
alert(!!"blue"); //true
alert(!!0); //falsealert(!!NaN); //false
alert(!!""); //false
alert(!!12345); //true
这是因为 arguments 对象的长度是由传入的参数个数决定的
JavaScript 的核心语言特性在 ECMA-262 中是以名为 ECMAScript 的伪语言的形式来定义的。ECMAScript 中包含了所有基本的语法、操作符、数据类型以及完成基本的计算任务所必需的对象,但
没有对取得输入和产生输出的机制作出规定。理解 ECMAScript 及其纷繁复杂的各种细节,是理解其在
Web 浏览器中的实现——JavaScript 的关键。目前大多数实现所遵循的都是 ECMA-262 第 3 版,但很多
也已经着手开始实现第 5 版了。以下简要总结了 ECMAScript 中基本的要素。
ECMAScript 中的基本数据类型包括 Undefined 、 Null 、 Boolean 、 Number 和 String 。
与其他语言不同,ECMScript 没有为整数和浮点数值分别定义不同的数据类型, Number 类型可
用于表示所有数值。
ECMAScript 中也有一种复杂的数据类型,即 Object 类型,该类型是这门语言中所有对象的基
础类型。
严格模式为这门语言中容易出错的地方施加了限制。
ECMAScript 提供了很多与 C 及其他类 C 语言中相同的基本操作符,包括算术操作符、布尔操作
符、关系操作符、相等操作符及赋值操作符等。
ECMAScript 从其他语言中借鉴了很多流控制语句,例如 if 语句、 for 语句和 switch 语句等。
ECMAScript 中的函数与其他语言中的函数有诸多不同之处。
无须指定函数的返回值,因为任何 ECMAScript 函数都可以在任何时候返回任何值。
实际上,未指定返回值的函数返回的是一个特殊的 undefined 值。
ECMAScript 中也没有函数签名的概念,因为其函数参数是以一个包含零或多个值的数组的形式
传递的。
可以向 ECMAScript 函数传递任意数量的参数,并且可以通过 arguments 对象来访问这些参数。
由于不存在函数签名的特性,ECMAScript 函数不能重载。
ECMAScript 中所有函数的参数都是按值传递的。也就是说,把函数外部的值复制给函数内部的参
数,就和把值从一个变量复制到另一个变量一样。基本类型值的传递如同基本类型变量的复制一样,而
引用类型值的传递,则如同引用类型变量的复制一样。
函数
函数的参数是按值传递,基本类型参数就是复制一个值给函数的形参(局部变量),变量类型的参数虽然也是值传递,但是引用类型是按引用访问(变量对象存指针,堆内存存实际对象,复制的是指针副本)
一旦数据不再有用,最好通过将其值设置为 null 来释放其引用——这个做法叫做解除引用(dereferencing)
由于 alert() 要接收字符串参数,所以它会在后台调用 toString() 方法,由此会得到与直接调用 toString() 方法相同的结果。
window是BOM对象,而非JavaScript对象,不过恰好为EMCAScript中所定义的Global对象
document.getElementByxxxxx获取的是HTMLCollection(18) document.querySelectorAll获取的是NodeList
在严格模式下,未指定环境对象而调用函数,则 this 值不会转型为 window。
除非明确把函数添加到某个对象或者调用 apply()或 call(),否则 this 值将是
另一种取得 Global 对象的方法是使用以下代码:
var global = function(){
return this;
}();
以上代码创建了一个立即调用的函数表达式,返回 this 的值。如前所述,在没有给函数明确指定
this 值的情况下(无论是通过将函数添加为对象的方法,还是通过调用 call()或 apply()),this
值等于 Global 对象。而像这样通过简单地返回 this 来取得 Global 对象,在任何执行环境下都是可
行的
2.<script> 在</body>外不执行