《JavaScript高级程序设计》读书笔记(一)

1.JavaScript的组成(简单介绍)

一个完整的JavaScript实现应该由下列三个不同的部分组成:

核心(ECMAScript)、文档对象模型(DOM )、浏览器对象模型(BOM)

1.ECMAScript

常见的 Web浏览器只是ECMAScript实现可能的宿主环境之一 。既然ECMA-262标准没有参照Web浏览器,那它都规定了些什么内容呢?大致说来,它规定了这门语言的下列组成部分:

语法
类型
语句
关键字
保留字
操作符
对象

ECMAScript 就是对实现该标准规定的各个方面内容的语言的描述。JavaScript实现了ECMAScript ,Adobe ActionScript同样也实现了ECMAScript。 


2.DOM

文档对象模型(DOM,Document Object Model)是针对XML但经过扩展用于HTML的应用程序编程接口(API,Application Programming Interface)。 DOM把整个页面映射为一个多层节点结构。 

DOM1 级的目标主要是映射文档的结构 ,DOM2级在原来DOM的基础上又扩充了(DHTML一直都支持的)鼠标和用户界面事件、范围、遍历(迭代DOM文档的方法)等细分模块,而且通过对象接口增加了对CSS(Cascading Style Sheets,层叠样式表)的支持。 DOM3级则进一步扩展了DOM,引入了以统一方式加载和保存文档的方法——在DOM加载和保存(DOM Load and Save)模块中定义;新增了验证文档的方法——在DOM验证(DOM Validation)模块中定义。DOM3级也对DOM核心进行了扩展,开始支持XML 1.0规范,涉及XML InfosetXPathXML Base。 


3.浏览器对象模型(BOM,Browser Object Model

可以访问和操作浏览器窗口,

从根本上讲,BOM只处理浏览器窗口和框架;但人们习惯上也把所有针对浏览器的JavaScript扩展算作BOM的一部分。下面就是一些这样的扩展:

弹出新浏览器窗口的功能;
移动、缩放和关闭浏览器窗口的功能;
提供浏览器详细信息的navigator对象;
提供浏览器所加载页面的详细信息的location对象;
提供用户显示器分辨率详细信息的screen对象;
cookies的支持;
XMLHttpRequestIEActiveXObject这样的自定义对象。 

由于没有 BOM标准可以遵循,因此每个浏览器都有自己的实现。虽然也存在一些事实标准,例如要有window对象和navigator对象等,但每个浏览器都会为这两个对象乃至其他对象定义自己的属性和方法。现在有了HTML5,BOM实现的细节有望朝着兼容性越来越高的方向发展。 

2.在HTML中使用JavaScript

<script>定义了下列6个属性。

  •   async:可选。表示应该立即下载脚本,但不应妨碍页面中的其他操作,比如下载其他资源或等待加载其他脚本。只对外部脚本文件有效。

  • <script type="text/javascript" async src="example1.js"></script>

  • <script type="text/javascript" async src="example2.js"></script> 

  • 在以上代码中,第二个脚本文件可能会在第一个脚本文件之前执行。 

  •   charset:可选。表示通过src属性指定的代码的字符集。由于大多数浏览器会忽略它的值,因此这个属性很少有人用。

  •   defer:可选。表示脚本可以延迟到文档完全被解析和显示之后再执行。(<script>元素中设置defer属性,相当于告诉浏览器立即下载,但延迟执行。

           最好只包含一个延迟脚本 

  •   language:已废弃。原来用于表示编写代码使用的脚本语言(如JavaScriptJavaScript1.2VBScript)。大多数浏览器会忽略这个属性,因此也没有必要再用了。

  •   src:可选。表示包含要执行代码的外部文件。

  •   type:可选。可以看成是language的替代属性;表示编写代码使用的脚本语言的内容类型(也

    称为 MIME类型)。虽然text/javascripttext/ecmascript都已经不被推荐使用,但人们一直以来使用的都还是text/javascript。(也是默认值) 

JavaScript插入到HTML页面中要使用<script>元素。使用这个元素可以把JavaScript嵌入到HTML页面中,让脚本与标记混合在一起;也可以包含外部的JavaScript文件。而我们需要注意的地方有:

  •   在包含外部JavaScript文件时,必须将src属性设置为指向相应文件的URL。而这个文件既可以是与包含它的页面位于同一个服务器上的文件,也可以是其他任何域中的文件。

  •   所有<script>元素都会按照它们在页面中出现的先后顺序依次被解析。在不使用deferasync属性的情况下,只有在解析完前面<script>元素中的代码之后,才会开始解析后面<script>元素中的代码。

  •   由于浏览器会先解析完不使用defer属性的<script>元素中的代码,然后再解析后面的内容,所以一般应该把<script>元素放在页面最后,即主要内容后面,</body>标签前面。

  •   使用defer属性可以让脚本在文档完全呈现之后再执行。延迟脚本总是按照指定它们的顺序执行。

  •   使用async属性可以表示当前脚本不必等待其他脚本,也不必阻塞文档呈现。不能保证异步脚

    本按照它们在页面中出现的顺序执行。另外,使用<noscript>元素可以指定在不支持脚本的浏览器中显示的替代内容。但在启用了脚本

    的情况下,浏览器不会显示<noscript>元素中的任何内容。

3.基础知识

1.数据类型

ECMAScript 中有 5种简单数据类型(也称为基本数据类型):UndefinedNullBooleanNumberString。还有1种复杂数据类型——Object,Object本质上是由一组无序的名值对组成的。ECMAScript不支持任何创建自定义类型的机制,而所有值最终都将是上述6种数据类型之一。 

可以通过typeof来获取变量的类型。


case1:

var message; // 这个变量声明之后默认取得了 undefined

// 下面这个变量并没有声明

// var age

alert(message);
alert(age);

// "undefined"// 产生错误 


case2:

var message; // 这个变量声明之后默认取得了 undefined

// 下面这个变量并没有声明

// var age

alert(typeof message);
alert(typeof age);
// "undefined"
// "undefined

case3:

var car = null;
alert(typeof car);// "object" 

null 值表示一个空对象指针,而这也正是使用typeof操作符检测null值时会返回"object"的原因 

实际上,undefined值是派生自null值的,因此ECMA-262规定对它们的相等性测试要返回true:

     alert(null == undefined);    //true

尽管 null 和 undefined 有这样的关系,但它们的用途完全不同。如前所述,无论在什么情况下都没有必要把一个变量的值显式地设置为 undefined,可是同样的规则对 null 却不适用。换句话说,只要意在保存对象的变量还没有真正保存对象,就应该明确地让该变量保存 null 值。这样做不仅可以体现 null 作为空对象指针的惯例,而且也有助于进一步区分 null 和 undefined。 

case4:


2.函数

  • ECMAScript 中的函数与其他语言中的函数有诸多不同之处。

    •   无须指定函数的返回值,因为任何ECMAScript函数都可以在任何时候返回任何值。

    •   实际上,未指定返回值的函数返回的是一个特殊的undefined值。

    •   ECMAScript中也没有函数签名的概念,因为其函数参数是以一个包含零或多个值的数组的形式 

      传递的。 8

    •   由于不存在函数签名的特性,ECMAScript函数不能重载。 

    •   可以向ECMAScript函数传递任意数量的参数,并且可以通过arguments对象来访问这些参数。

4.变量、作用域和内存问题 

1.typeof和instanceof

虽然在检测基本数据类型时 typeof 是非常得力的助手,但在检测引用类型的值时,这个操作符的用处不大。通常,我们并不是想知道某个值是对象,而是想知道它是什么类型的对象。为此,ECMAScript提供了 instanceof 操作符,其语法如下所示:

result = variable instanceof constructor 

2.作用域

1.作用域链



当执行try-catch语句的catch块或使用with语句时,作用域链会被加长。

这两个语句都会在作用域链的前端添加一个变量对象。对 with 语句来说,会将指定的对象添加到作用域链中。对 catch 语句来说,会创建一个新的变量对象,其中包含的是被抛出的错误对象的声明。 

2.没有块级作用域

    if (true) {
        var color = "blue";
    }
    alert(color);    //"blue"

这里是在一个 if 语句中定义了变量 color。如果是在 C、C++或 Java 中,color 会在 if 语句执行完毕后被销毁。但在 JavaScript 中,if 语句中的变量声明会将变量添加到当前的执行环境(在这里是全局环境)中。在使用 for 语句时尤其要牢记这一差异,例如:

    for (var i=0; i < 10; i++){
        doSomething(i);

}

    alert(i);      //10

3.垃圾收集

确保占用最少的内存可以让页面获得更好的性能。而优化内存占用的最佳方式,就是为执行3中的代码只保存必要的数据。一旦数据不再有用,最好通过将其值设置为null 来释放其引用——这个做法叫做解除引用(dereferencing)。这一做法适用于大多数全局变量和全局对象的属性。局部变量会在它们离开执行环境时自动被解除引用 。

不过,解除一个值的引用并不意味着自动回收该值所占用的内存。解除引用的真正作用是让值脱离执行环境,以便垃圾收集器下次运行时将其回收。 


4.第四章总结

JavaScript 变量可以用来保存两种类型的值:基本类型值和引用类型值。基本类型的值源自以下5种基本数据类型:UndefinedNullBooleanNumberString。基本类型值和引用类型值具有以下特点:11

  •   基本类型值在内存中占据固定大小的空间,因此被保存在栈内存中;

  •   从一个变量向另一个变量复制基本类型的值,会创建这个值的一个副本;

  •   引用类型的值是对象,保存在堆内存中;

  •   包含引用类型值的变量实际上包含的并不是对象本身,而是一个指向该对象的指针;

  •   从一个变量向另一个变量复制引用类型的值,复制的其实是指针,因此两个变量最终都指向同

    一个对象;

121   确定一个值是哪种基本类型可以使用 typeof 操作符,而确定一个值是哪种引用类型可以使用instanceof操作符。


所有变量(包括基本类型和引用类型)都存在于一个执行环境(也称为作用域)当中,这个执行环境决定了变量的生命周期,以及哪一部分代码可以访问其中的变量。以下是关于执行环境的几点总结:

  •   执行环境有全局执行环境(也称为全局环境)和函数执行环境之分;

  •   每次进入一个新执行环境,都会创建一个用于搜索变量和函数的作用域链;

  •   函数的局部环境不仅有权访问函数作用域中的变量,而且有权访问其包含(父)环境,乃至全

    局环境;

  •   全局环境只能访问在全局环境中定义的变量和函数,而不能直接访问局部环境中的任何数据;

  •   变量的执行环境有助于确定应该何时释放内存。


  • JavaScript 是一门具有自动垃圾收集机制的编程语言,开发人员不必关心内存分配和回收问题。可以对JavaScript 的垃圾收集例程作如下总结。

  •   离开作用域的值将被自动标记为可以回收,因此将在垃圾收集期间被删除。

  •   “标记清除”是目前主流的垃圾收集算法,这种算法的思想是给当前不使用的值加上标记,然

    后再回收其内存。

  •   另一种垃圾收集算法是“引用计数”,这种算法的思想是跟踪记录所有值被引用的次数。JavaScript

    引擎目前都不再使用这种算法;在IE 中访问非原生 JavaScript对象(如 DOM 元素)时,这种

       算法仍然可能会导致问题。
    
  •   当代码中存在循环引用现象时,“引用计数”算法就会导致问题。

  •   解除变量的引用不仅有助于消除循环引用现象,而且对垃圾收集也有好处。为了确保有效地回

       收内存,应该及时解除不再使用的全局对象、全局对象属性以及循环引用变量的引用。
    
 
阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页