JavaScript简介
# 文档对象模型DOM
1.为什么要使用DOM
形成统一标准,方便使用
2.基于XML,DOM标准
- SVG(可伸缩矢量图)
- MathML(数学标记语言)
- SMIL(同步多媒体集成语言)
# 浏览器对象模型DOM
**Browser Object Model**
从根本上讲,BOM 只处理浏览器窗口和框架;但人们习惯上也吧所有针对浏览器的JavaScript扩展算作BOM 的一部分
- 弹出新浏览器窗口的功能
- 移动、缩放和关闭浏览器窗口的功能
- 提供浏览器详细信息的navigator对象
- 提供浏览器所加载页面的详细信息的location对象
- 提供用户显示器分辨率详细信息的screen对象
- 对cookies的支持
- 像XMLHttpRequest和IE的ActiveXObject这样的自定义对象
在Html中使用JavaScript
# <script>元素
- async:可选。表示应该立即下载脚本,但不应妨碍页面中的其他操作。
- charset:可选。表示通过src属性指定的代码的字符集。
- defer:可选。表示脚本可以延迟到文档完全被解析和显示后再执行
- src:可选。外部文件路径
- type:可选。语言类型,默认text/javascript
# 异步脚本与延迟脚本
1.现实中,延迟脚本并不一定会按照顺序执行,也不一定会在DOMContentLoaded事件触发前执行,因此最好只包含一个延迟脚本。
2.异步脚本也不会确定加载时序,因此,确保两者之间相互不依赖非常重要。建议异步脚本不要在加载期间修改DOM。
3.异步脚本一定会在页面的load事件前执行,但可能会在DOMContentLoaded事件触发之前或之后执行。
# 文档模式
通过使用文档类型(doctype)切换实现
# 小结
- 在包含外部JavaScript文件时,必须将src属性设置为指向相应文件的url。
- 所有<script>元素都会按照它们在页面中出现的先后顺序依次被解析。
- 使用defer属性可以让脚本在文档完全呈现之后再执行。
- 使用async属性可以表示当前脚本不必等待其他脚本,也不必阻塞文档呈现。不能保证异步脚本按照它们在页面中出现的顺序执行。
基本概念
# 严格模式
1.在严格模式下,ECMAScript3中的一些不确定的行为将得到处理,而且对某些不安全的操作也会抛出错误。
2.使用:“use strict”
# 语句
1.语句结束添加“;”,加上分好也会在某些情况下增进代码的性能,因为这样解析器就不必再花时间推测应该在哪里插入分号了。
# 变量
1.初始化数据默认值为undefined
2.var操作符定义的变量将成为定义该变量的作用域中的局部变量。
# 数据类型
5种简单数据类型:Undefined,Null,Boolean,Number,String
1中复杂数据类型:Object(无序的名值对组成)
**typeof操作符**
用于检测数据类型
- “undefined” 值未定义
- “boolean” 布尔值
- “string” 字符串
- “number” 数值
- “object” 对象或null
- “function” 函数
**Number**
1.由于保存浮点数值需要的内存空间是保存整数倍的两倍。因此ECMAScript会不失时机地将浮点数值转换为整数值。
2.关于浮点数值计算会产生摄入误差的问题,有一点需要明确:这是使用基于IEEE754数值的浮点计算的通病,ECMAScript并非独此一家,其他使用相同数值格式的语言也存在这个问题。
3.Number.MIN_VALUE:5e-324 Number.MAX_VALUE:1.7976931348623157e+308,如果计算超出取值范围则为正无穷或负无穷
4.NaN:一个特殊的数值。用于表示一个本来要返回数值的操作数未返回数值的情况(程序就不会报错宕机),任何涉及NaN的操作都会返回NaN,NaN与任何值都不相等,包括NaN本身。
5.使用isNaN()判断是不是数值
**String**
1.String类型用于表示由零或多个16位Unicode字符组成的字符序列,即字符串。
2.转移字符:"\n","\t","\b","\r","\\","\xnn","\unnnn"
3.字符串是不可变的,字符串一旦被创建,它们的值就不能改变。
4.转换字符串方法:
(1)toString(),null与undefined不能使用
(2)String(),null与undefined可以使用
**Object**
对象可以通过执行new操作符后跟要创建的对象类型的名称来创建。而创建Object类型的实例并为其添加属性和方法,就可以创建自定义对象
var o = new Object();
在ECMAScript中,Object类型是所有它的实例的基础。Object类型是所有对象的基类。
每个Object实例都包含以下属性和方法:
- constructor:保存着创建当前对象的函数。
- hasOwnProperty(propertyName):用于检查给定的属性在当前对象实例中(不是在实例的原型中)是否存在。参数propertyName为字符串形式
- isPototypeOf(object):用于检查传入的对象是否是传入对象的原型。
- propertyIsEnumerable(propertyName):用于检查给定的属性是否能够使用for-in语句来枚举。
- toLocaleString():返回对象的字符串表示,该字符串与执行环境的地区对应。
- valueOf():返回对象的字符串、数值或布尔值表示。
在浏览器环境中,BOM和DOM中的对象不一定会继承Object
# 操作符
**一元操作符**
1.递增和递减操作符
2.一元加和减操作符
**位操作符**
1.位操作用于在最基本的层次上,即按内存中表示数值的位来操作数值。
2.ECMAScript中所有数值有以IEEE-754 64位格式存储,但位操作符并不能直接操作64位的值。而是将64位转换为32位的整数,然后执行操作,最后再将结果转换回64位。
3.有符号整数,32位前31位表示整数的值,第32位表示符号,0表示正,1表示负数。
4.负数以二进制补码的方式存储。
(1)首先求得负数对应正数的二进制码
(2)在求得的二进制反码加1
5.在ECMAScript中,当对数值应用位操作时会导致一个严重的副效应,即在对特殊的NaN和Infinity值应用位操作时,这两个值都会被当做0处理。
6.位操作运算
(1)按位非(NOT):~
执行按位非的结果就是返回数值的反码
用途:
求得一个数的相反数:~x + 1 = x * -1
(2)按位与(AND):&
按位与操作只有在两个数值的对应位都是1时才返回1,任何一位是0,结果都是0
用途:
将一个数的某些位置零,只需要&运算需要置0位为0即可
(3)按位或(OR):|
按位或操作在有一个位是1的情况下就返回1,只有在两个位都是0的情况下才返回0
用途:
将一个数的某些位置1
(4)按位异或(XOR):^
按位异或与按位或的不同之处在于,这个操作在两个数值对应位上只有一个1时才返回1,如果对应的两位都是1或都是0,则返回0
(5)左移:<<
将数值的所有位向左移动指定的位数。左移操作会以0来填充这些空位,以便得到一个完整的32位二进制数。
左移不会影响操作数的符号位,负数左移了还是负数
(6)有符号的右移:>>
将数值向右移动,但保留符号位。在移位过程中,空位填充在符号位右侧。
(7)无符号的右移:>>>
对正数来说,无符号右移的结果与有符号右移相同。
对负数来说,无符号右移会将符号位作为空位进行填充,而且由于负数以其绝对值的二进制补码形式表示,因此就会导致无符号右移的结果非常之大。
**布尔操作符**
- 逻辑非:!
- 逻辑与:&&
- 逻辑或:||
**乘性操作符**
- 乘法:*
- 除法:/
- 求模:%
**加性操作符**
- 加法:+
- 减法:-
**关系操作符**
- 小于:<
- 大于:>
- 小于等于:<=
- 大于等于:>=
**相等操作符**
ECMAScript提供两组操作符:
相等和不相等——先转换再比较
全等和不全等——仅比较不转换
1.相等和不相等
- 如果一个操作数是布尔值,则在比较相等性之前先将其转换为数值——false转换为0,而true转换为1
- 如果一个操作数是字符串,另一个操作数是数值,在比较相等性之前先将字符串转换为数值
- 如果一个操作数是对象,另一个不是,则调用对象的valueOf()方法,用的到的基本类型值按照前端的规则进行比较
- null 和 undefined 是相等的
- 要比较相等性之前,不能将null 和undefined转换为其他任何值
- NaN == NaN 返回false
2.全等和不全等
除了在比较之前不转换操作数之外,全等和不全等操作符与相等和不相等操作符没有什么区别。
# 函数
函数对任何语言来说都是一个核心的概念。
ECMAScript中的函数在定义时不必指定是否返回值。
**参数理解**
1.ECMAScript函数不介意传递进来多少个参数,也不在乎传进来参数是什么数据类型。参数在内部使用数组来表示。可以通过arguments对象来访问这个参数数组。
2.ECMAScript函数命名的参数只提供便利,但不是必需的。另一方面解析器不会验证命名参数。
3.没有传递值的命名参数将自动被赋予undefined值。
4.ECMAScript中的所有参数传递的都是值,不可能通过引用传递参数。
# 小结
- ECMAScript中的基本数据包括:Undefined,Null,Boolean,Number,String
- Number类型可用于表示所有数值
- 实际上,未指定返回值的函数返回的是一个特殊的undefined值
- ECMAScript没有函数签名的概念,函数参数是以一个包含零或多个值的数组的形式传递的
- 由于没有函数签名的特性,ECMAScript函数不能重载
变量、作用域和内存问题
# 基本类型和引用类型的值
基本类型值:简单的数据段
引用类型值:可能由多个值构成的对象
引用类型的值是保存在内存中的对象。与其他语言不通,JavaScript不允许直接访问内存中的位置,也就是说不能直接操作对象的内存空间。实际上在操作对象的引用而不是实际的对象。因此,引用类型的值是按引用访问的。
1.复制变量值
(1)如果从一个变量向另一个变量复制基本类型的值,会在变量对象上创建一个新值,然后把该值复制到为新变量分配的位置上。
var num1 = 5; var num2 = num1; 这时更改num2并不会更改num1
(2)当一个变量复制引用类型的值时,同样也会将存储在变量对象中的值复制一份到新变量分配的空间中。不同的是,这个副本是指向源对象的一个指针。
2.传递参数
参数传递同复制变量一样,基本类型会重新创建,引用类型会持有源对象的一个指针。
在向参数传递基本类型的值时,被传递的值会被复制给一个局部变量(arguments数组中的一个元素)
可以把ECMAScript函数的参数想象成局部变量
# 执行环境及作用域
**执行环境是JavaScript中最为重要的一个概念**
- 执行环境定义了变量或函数有权访问的其他数据
- 每个执行环境都有一个与之关联的变量对象,环境中定义的所有的变量和函数都保存在这个对象中。
- 根据ECMAScript实现所在的宿主环境不同,表示执行环境的对象也不一样。在Web浏览器中,全局执行环境是window对象。
- 每个函数都有自己的执行环境。当执行流进入一个函数时,函数的环境就会被推入一个环境栈中。而在函数执行之后,栈将其环境弹出,把控制权返回给之前的执行环境。
- 当代码在一个环境中执行时,会创建变量对象的一个作用域链。(_proto)
- 全局执行环境的变量对象始终都是作用域链中的最后一个对象。
- 标识符解析是沿着作用域链一级一级地搜索标识符的过程。搜索过程始终从作用域链的前端开始,然后逐级地向后回溯,直到找到标识符为止。
- 内部环境可以通过作用域链访问所有的外部环境,但外部环境不能访问内部环境中的任何变量和函数。这些环境之间的联系是线性、有次序的。
**没有块级作用域**
其他类C语言中,由花括号封闭的代码块都有自己的作用域(自己的执行环境),但在JavaScript中,变量只会在函数结束后被销毁。
1.声明变量
使用var声明的变量会自动被添加到最接近的环境中。在函数内部,最接近的环境就是函数的局部环境。如果没有var声明,该变量会自动被添加到全局变量
2.查询标识符
访问局部变量要比访问全局变量更快,因为不用向上搜索作用域链。
# 垃圾收集
JavaScript具有自动垃圾收集机制。执行环境会负责管理代码执行过程中使用的内存。垃圾收集器按照固定时间间隔,周期性地执行垃圾回收(引用计数回收机制、标记清除)
局部变量只在函数执行的过程中存在。而在这个过程中,会为局部变量在栈(或堆)内存上分配相应的空间,以便存储它们的值。
**管理内存**
在Web应用中,分配得到的内存数量通常要比分配给桌面应用程序的少。这样做的原因主要出于安全方面的考虑,目的是防止JavaScript的网页耗尽全部系统内存而导致系统崩溃。
内存限制问题不仅会影响给变量分配内存,同时还会影响调用栈以及在一个线程中能够同时执行的语句数量。
数据一旦不用,将其引用置为null
# 小结
基本类型的值:Undefined,Null,Boolean,Number,String。基本数据值和引用类型值具有以下特点:
- 基本类型值在内存中占据固定大小的空间,因此被保存在栈内存中。
- 从一个变量向另一个变量复制基本类型的值,会创建这个值的一个副本(在另一个内存空间存放了相同的值)
- 引用类型的值是对象,保存在栈内存中。
- 包含引用类型值的变量实际上包含的并不是对象本身,而是一个指向该对象的指针。
- 从一个变量向另一个变量复制引用类型的值,复制的其实是指针,因此两个变量最终都指向同一个对象。
- 确定一个基本类型可以用typeof操作符,确定一个值是哪种引用类型可以使用instanceof操作符
关于执行环境的总结:
- 执行环境有全局执行环境和函数执行环境之分
- 每次进入一个新执行环境,都会创建一个用于搜索变量和函数的作用域链。
- 函数的局部环境不仅会有权访问函数作用域中的变量,而且有权访问其包含(父)环境,乃至全局环境
- 全局环境只能访问在全局环境中定义的变量和函数,而不能直接访问局部环境中的任何数据
- 变量的执行环境有助于确定应该何时释放内存