JavaScript高级程序设计——笔记(1~4章)

JavaScript简介

待补充

第二章 在HTML中使用JavaScript

2.1 script元素

.js扩展名可以不带,因为浏览器不会检查包含JavaScript的文件的扩展名,但是服务器通常还是需要看扩展名决定为响应应用哪种MIME类型,如果不适用.js扩展名,需要确保服务器能返回正确的MIME类型

<script>元素会在页面中按照出现的顺序依次解析。文档中<head>元素中最好不要放大量的js文件,在<head>中放大量的js文件,会导致浏览器在呈现页面时出现明显的延迟,而延迟期间的浏览器窗口是空白的(浏览器遇到body元素才开始呈现内容)。为了避免这个问题,现在的web应用程序一般把全部的JavaScript引用放到<body>元素中页面的内容后面。

延迟脚本
<script>元素中定义defer属性,效果是立即下载js文件,但是延迟执行。延迟脚本一定会按照顺序执行,因此最好只引入一个延迟脚本。defer属性只适用于外部脚本文件,对嵌入脚本的defer属性,html5会忽略。

异步脚本
指定外部脚本的async属性,和defer相似,但是标记为async的外部脚本并不按照前后顺序执行,因此要确保两个指定了async属性的外部脚本互不依赖。异步脚本不要再加载期间修改DOM元素

XHTML中的用法

主要是一些特殊字符需要使用字符实体表示

2.2 嵌入代码和外部文件

可维护性、可缓存、适应未来

2.3 文档模式

混杂模式和标准模式

2.4 noscript元素

包含在<noscript>元素中的内容只有在两种情况下可以显示出来:浏览器不支持脚本;浏览器支持脚本,但脚本被禁用。

第三章 基本概念

3.1 语法

3.2 关键字和保留字

3.3 变量

在函数中使用var定义局部变量

在函数中不使用var关键字直接定义的是全局变量(不推荐这样做)

严格模式下给未经声明的变量赋值将会抛出ReferenceError错误

可以使用一条语句声明多个变量:

var bianliang1 = "1",

bianliang2 = "2",

bianliang3 = 3;

只要使用逗号分隔开即可。

3.4 数据类型

5种简单基本类型:undefined、null、boolean、number和String

1种复杂类型:Object(Object本质上由一组无序的名值对组成)

不支持自定义数据类型

typeof操作符 检测给定变量的数据类型(还可以是数值字面量)

typeof (null); 返回”Object”

从技术角度讲,函数是对象而不是一种数据类型,可以使用typeof区分出函数和对象

Undefined
只有一个值undefined,它是使用了var关键字声明了某个变量但是并未对其进行初始化。

注意:使用typeof检测未初始化和未声明的变量时,都会返回undefined。这在技术角度上逻辑是合理的,因为这两种变量都不能执行真正的操作。

null
表示一个空对象指针

实际上,undefined的值是派生自null值的,因此使用”==”检测时会返回true

alert(null == undefined); //true

Boolean
Boolean类型的值只有两个:truefalse , 区分大小写

空字符串(”“)会再进行Boolean运算时转换为false:

var message = "";
if(message) {xxx} //条件是false,所以xxx不会执行

Number
前导零表示八进制数,当变量中出现了8或者大于8的数字,则忽略前导零,解析为十进制数字。(八进制字面量再严格模式下是无效的,会导致JavaScript引擎抛出错误)

十六进制前面必须是0x

保存浮点数所需的内存空间是整数的两倍。小数点后没有数字或者小数点后都为0则解析为整数

浮点数值的最高精度是17位小数

浮点数值计算产生的舍入误差:0.1+0.2 != 0.3

数值范围
负无穷和正无穷
isFinite()函数可以确定某个Number类型的数值是否在最大和最小数值之间

Nan:非数值,是一个特殊的数值,用于表示一个本来要返回数值的操作数未返回数值的情况(这样就不会抛出错误了)。在其他语言中,任何数值除以0都会导致错误,代码停止执行,但是在ECMAScript中,会返回Nan

任何设计Nan的操作都返回Nan,Nan和任何值都不相等,包括Nan本身

alert(Nan == Nan); //false

isNan()函数:任何可以被转换成数值的值都返回false,只有不能被转换为数值的值会返回true

数值转换的三个函数:Number()parseInt()parseFloat()

3.5 操作符

相等操作符:

相等和不相等:进行强制转换后比较两个操作数

全等和不全等:不进行强制转换,直接比较两个操作数 ===

逗号操作符:

var num = (0,1,2,3,4,5); //num为5

逗号操作符用于赋值时,返回表达式最后一项。

3.6 语句

for-in语句

用来枚举对象的属性:

for(var property in window) {
    document.write(property);
}

上面的示例使用了for-in循环显示了BOM中window对象的所有属性。

ECMAScript在迭代的对象的变量值为Nanundefined时,不会抛出错误,而只是不执行循环体。

label语句

定义一个标签,和breakcontinue语句一起使用。一般使用在循环嵌套下。

一般情况下单独使用break或者continue只能退出当前循环体,使用了label则可以指定退出到label所在的地方(一般是退出多层循环)。

with语句

了解即可,大量使用会导致性能下降和调试困难,不建议使用。严格模式下还会报错……

switch语句

和其他语言的switch语句相比,JavaScript的switch语句没有类型限制,甚至可以使用表达式。

注意:switch语句在比较时使用的是 全等 ,不进行类型转换

3.7 函数

函数通过函数名调用,后边跟着一对圆括号和参数列表。

由于JavaScript没有严格的数据类型,所以函数的参数不必用var关键字声明。

函数在定义时不必指定返回值,这一点和java不同,java即使没有返回值也要指定为void。但是在函数内部可以使用return返回任意值。

未指定函数返回值时,实际上函数返回了一个undefined值

严格模式下,函数名有一些限制,不能是evalarguments

理解参数
ECMAScript不介意函数传递进来多少参数,也不在乎参数是什么数据类型,因为参数在内部是通过一个arguments数组实现的,在函数体内可以通过arguments对象访问参数数组。其实,arguments只是和数组类似而不是数组的一个实例。

关于arguments对象的行为,有一点很有意思,就是它的值永远和对应的参数值相同(保持同步)。这并非说明这两个值实际上存储在相同的命名空间。当对其中一个修改时,这种修改是单向的,并不影响另一个值,但是很快另一个值将会修改以保持同步。

arguments对象的length由传入的参数个数决定,而非函数定义时的参数个数。

最后一点:没有传递值的参数将会被赋值为undefined值。

严格模式下对arguments做出了一些限制,arguments对象中的某个值不可以被重写,否则会报错;修改了参数值后,对应的arguments中的值不会再保持同步

注意:ECMAScript中的所有参数传递的都是值,不可能通过引用传递参数

没有重载
ECMAScript中没有方法签名(接受参数的类型和数量),所以不可能完成真正的重载。

但是通过检测传入参数的数量和数据类型,可以模仿重载。

第四章 变量、作用域和内存问题

4.1 基本类型和引用类型的值

ECMAScript变量可能有两种数据类型的值:基本类型值和引用类型值。基本类型值是简单的数据段,引用类型值是指由那些可能由多个值构成的对象。

引用类型的值是保存再内存中的对象,与其他语言(例如c语言)不同,JavaScript不允许直接访问对象在内存中的位置,也就是说不能直接操作对象的内存空间,在操作对象时,实际上操作的是对象的引用。

在很多语言中(例如Java),字符串以对象的形式来表示,因此被认为是引用,JavaScript则放弃了这一传统。

动态的属性 省去了java中定义属性和使用setter方法的烦恼……

复制变量值

对于基本类型的变量,复制变量值相当于添加了一个副本,两个变量在内存中处于不同的位置,只是值相同,操作上互不影响。

对于引用类型的变量,复制变量值也可以认为是添加了一个副本,不过这个副本中存储的不是值,而是一个指针(被复制的引用类型的变量同样存储了一个指针),指针指向存储在堆中的一个对象,被复制的变量和复制的变量实际上引用同一个对象,操作上会相互影响。

传递参数

ECMAScript中所有函数的参数都是按值传递的。ECMAScript函数中的参数都可以认为是局部变量,只在函数内有效,函数执行结束后即销毁。

再赞同不过的一句话:

很多开发人员认为,在局部作用域内修改的对象会在全局作用域中反应出来,就说明参数是按引用传递的。这种说法是错误的,在ECMAScript中,在函数内部修改了参数的值,其原始的引用仍未改变,在函数内部重写参数(引用类型的参数)的值时,这个变量(即参数)引用的就是一个局部对象了,而局部对象会在函数执行完毕后立即销毁。

关于上面这个说法,可以看看下面这个例子:

function setName(obj) {

obj.name = "Ethan";

obj = new Object();

obj.name = "小明";

}

var person = new Object();

setName(person);

alert(person.name); //"Ethan"

检测类型

typeof操作符可以确定一个变量类型是String、number、boolean或者是undefined值。如果检测null时,则返回Object,这在技术角度也是说得通的,null代表了一个空对象指针,即变量类型为一个Object。

使用typeof操作符检测RegExp正则表达式时,不同的浏览器有不同的结果。

通常,我们使用typeof操作符检测基本类型的变量,检测对象的具体类型则使用instanceof操作符。

alert(person instanceof Object); //person是Object吗

alert(colors instanceof Array); //colors是Array吗

alert(pattern instanceof RegExp); //pattern是RegExp吗

识别原理:根据对象的原型链来识别

基本类型并非对象,使用instanceof检测基本类型,返回false

4.2执行环境及作用域

执行环境的概念
window、function

作用域链(scope chain)

延长作用域链
try……catch语句和with块

重点:
没有块级作用域

和其他类c语言不一样,ECMAScript没有块级作用域。在for循环中尤其需要注意:

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

xxxx……

}

对于有块级作用域的语言来说,初始化的i变量只会存在于循环的环境当中。而在JavaScript中,创建的i变量会一直存在,不会因为循环结束被销毁。

使用var声明的变量会被自动的添加到最接近的环境当中。在函数内部,最接近的环境就是函数的局部环境;在with语句中,最接近的环境也是函数环境;如果变量没有使用var声明,则变量会被自动添加到全局环境。

4.3 垃圾收集

JavaScript的自动垃圾回收机制

方式一:标记清除(marked and sweep)

方式二:引用计数(reference counting)循环引用带来的麻烦

性能问题

管理内存

手工解除引用:一般用在全局环境变量中。解除引用(dereferencing)不代表会回收变量所占用的内存,只是切断了变量与执行环境的

联系,便于下次垃圾回收器自动运行时回收这一部分内存。

小结:栈内存中保存的是基本类型变量的值,堆内存中保存的是引用类型的值(对象)。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值