Javascript简介
Javascript实现
虽然Javascript和ECMAscript通常都被人们用来表达相同的含义,但是Javascript的含义要比ECMA-262中规定的要多得多。
一个完整的Javascript实现由三部分组成:
- 核心(ECMAscript)
- 文档对象模型(DOM)
- 浏览器对象模型(BOM)
ECMAscript
ECMA-262定义的只是这门语言的基础。Web浏览器只是ECMAscript实现可能的宿主环境之一。
宿主环境不仅提供基本的ECMAscript实现,同时也会提供该语言的扩展,以便语言与环境之间对接交互。其他宿主环境包括Node和Adobe Flash。
ECMAscript规定了以下组成部分:
- 语法
- 类型
- 语句
- 关键字
- 保留字
- 操作符
- 对象
什么是ECMAscript兼容?
要想成为ECMAscript的实现,则该实现必须做到:
- 支持ECMA-262描述的所有“类型、值、对象、属性、函数以及程序句法和语义”
- 支持Unicode字符标准
此外,兼容的实现还可以进行下列扩展。
- 添加ECMA-262没有描述的“更多类型、值、对象、属性和函数”
- 支持ECMA-262没有定义的“程序和正则表达式语法”
Web浏览器对ECMAscript的支持
文档对象模型(DOM)
文档对象模型(DOM,Document Object Model)是针对XML但经过扩展用于HTML的应用程序编程接口(API,Application Programming Interface)。
为什么要使用DOM?
防止浏览器互不兼容的情况。
DOM级别
DOM1级由两个模块组成:DOM核心(DOM core)和DOM HTML。
DOM核心规定如何映射基于XML的文档结构,以便简化对文档中任意部分的访问和操作。
DOM HTML模块则在DOM核心的基础上加以扩展,添加了针对HTML的对象和方法。
DOM2级在原来的DOM的基础上有扩充了一些模块,而且通过对象接口增加了对CSS的支持。DOM1级中的DOM核心模块也经过了扩展开始支持XML命名空间。
DOM3级则进一步扩展了DOM,引入了以统一方式加载和保存文档的方法---在DOM加载保存(DOM Load and Save)模块中定义;新增了验证文档的方法---在DOM验证(DOM Validation)模块中定义。DOM3级也对DOM核心进行了扩展,开始支持XML1.0规范,涉及XML Infoset、XPath和XML Base。
其他DOM标准
- SVG
- MathML
- SMIL
Web浏览器对DOM的支持
浏览器对象模型(BOM)
从根本上讲,BOM只处理浏览器窗口和框架;但人们习惯上也把所有针对浏览器的JavaScript扩展算作BOM的一部分。
- 弹出新浏览器窗口的功能;
- 移动、缩放和关闭浏览器窗口的功能
- 提供浏览器详细信息的navigator对象;
- 提供浏览器所加载页面的详细信息的location对象;
- 提供用户显示器分辨率详细信息的screen对象;
- 对cookies的支持
- 像XMLHttpRequest或IE的ActiveXObject这样的自定义对象。
由于没有BOM标准可以遵循,每个浏览器都有自己的实现。但在HTML5中,BOM的实现细节朝着兼容性越来越高的方向发展。
JavaScript 版本
Mozilla公司是目前唯一还沿用最初的JavaScript版本编号序列的浏览器开发商。
Script标签
在HTML页面中插入JavaScript的主要方法是使用标签。
HTML4.01为定义了6个属性:
- async:可选
- charset:可选
- defer:可选
- language:已废弃
- src:可选
- type:可选
有两种使用的方法:
- 直接嵌入JavaScript代码
- 包含外部JavaScript代码
按照惯例,JavaScript文件的后缀名是.js。但这个不是必须的,浏览器不会检查包含JavaScript的文件的扩展名。但是服务器还是需要看扩展名来决定响应哪种MIME类型。如果不使用.js扩展名,请确保服务器能返回正确的MIME类型。
在带有src
属性的标签中间不应该包含额外的JavaScript代码。如果包含了嵌入的代码,则只会下载执行外部脚本文件,嵌入的代码会被忽略。
元素的
src
属性还可以包含来自外部域的JavaScript文件。
无论如何包含代码,只要不存在defer
和async
属性,浏览器都会按照出现的顺序对他们进行解析。
标签的位置
在元素中的JavaScript文件,页面会等到全部的JavaScript代码被下载、解析和执行完后,才开始呈现页面内容。对于很多JavaScript的页面会产生明显的延迟。所以最好把JavaScript代码放在
元素中内容的后面。
延迟脚本
当元素中定义了
defer
属性,脚本立刻下载,但是延迟到整个页面解析完毕后在运行。
异步脚本
在XHTML中的用法
下列代码在HTML中是有效的,但在XHTML中是无效的。
a中的
<
会被XHTML当做开始一个新标签来解析,所以会导致语法错误。
有两种方法可以避免:
- 用相应的HTML实体(<)来替换小于号
- 用一个CData片段来包含JavaScript代码。
嵌入代码与外部文件
使用外部文件有一些优点:
- 可维修性
- 可缓存
- 适应未来
文档模型
IE5.5引入了文档模式的概念,通过使用文档类型(doctype)切换实现。最初由两种:
- 混杂模式(quirks mode),会让IE的行为与IE5相同。
- 标准模式(standards mode),会更接近标准行为。
之后IE又提出了所谓的准标准模式(almost standards mode)。
如果在文档开始处没有发现文档类型声明,则所有的浏览器都会默认开启混杂模式。
标准模式可以用下面任何一种文档类型来开启:
而对于准标准模式,则可以通过过渡型(transitional)或框架集型(frameset)来触发:
只有在下列情况
- 浏览器不支持脚本
- 浏览器支持脚本,但脚本被禁用
基本概念
区分大小写
ECMAScript中的一切(变量、函数名和操作符)都区分大小写。
标识符
标识符是按照下面的规则组合起来的一或多个字符。
- 第一个字符必须是一个字母、下划线(_)或一个美元符($)。
- 其他字符可以是字母、下划线、美元符号和数字。
标识符中的字母也可以包含扩展的ASCII或Unicode字母字符,但是不推荐。
按照惯例,ECMAScript标识符采用驼峰大小写格式。
注释
ECMAScript使用C风格的注释,包括单行注释和块级注释。
//单行注释
/*多行注释*/
严格模式
ECMAScript5引用了严格模式(strict mode)的概念。
严格模式定义了一种不同的解析与执行模型。在严格模式下,ECMAScript3中一些不确定的行为将得到处理,而且对某些不安全的操作也会抛出错误。
在顶部添加下面的代码启用严格模式。
"use strict";
也可以指定函数在严格模式下执行:
function dosomething () {
""use strict;
//函数体
}
语句
ECMAScript中的语句以一个分号结尾;如果省略分号,则由解析器确定语句的结尾。
关键字和保留字
ECMAScript5对使用关键字和保留字的规则进行了一些修改。关键字和保留字虽然仍然不能作为标识符使用,但现在可以用作对象的属性名。
ECMAScript5在严格模式下,还不能把eval
和arguments
作为标识符或属性名,否则抛出错误。
变量
使用操作符var
:
var message = "1";
数据类型
ECMAscript中有5种简单的数据类型:
- Number
- Boolean
- String
- Null
- Undefined
1种复杂类型:
- Object
ECMAscript不支持任何创建自定义类型的机制,所有的值最终都将是上述6中数据类型之一。
typeof操作符
用来检测给定变量的数据类型。typeof操作符可能返回下列值:
- "undefined"
- "boolean"
- "string"
- "number"
- "object"
- "function"
var a1 ="变量一";
alert(typeof a1);
alert(typeof(a1));
alert(typeof 81);
typeof的操作数可以是变量或者直接量。typeof是一个操作符而不是函数,所以括号可有可无。
Safari5及之前的版本、Chrome7及之前版本在对正则表达式调用typeof
操作符是会返回function
,而其他浏览器在这种情况下回返回Object
。
undefined 类型
在使用var
声明的变量但没有对其初始化时,变量的值为undefined。
在ECMA-262第3版之前并没有这个值。第3版引入是为了区分空对象指针和未初始化的变量。
包含undefined值得变量与尚未定义的变量还是不一样的。
var message;
alert(message); //"undefined"
alert(age); //产生错误
typeof操作符对于未初始化的变量和未声明的变量都返回undefined。
var message;
alert(typeof message); //"undefined"
alert(typeof age); //"undefined"
null 类型
typeof操作符检测null值时会返回object。
实际上,undefined值派生自null值,因此ECMA-262规定对他们的相等性测试要返回true。
alert(null == undefined); //true
boolean 类型
该类型只有两个字面量true和false。
true和false是区分大小写的。
将一个值转化为boolean值,可以使用Boolean()
函数:
var str = "string";
var b = Boolean(str);
数据类型 | 转化为true的值 | 转化为false的值 |
---|---|---|
Boolean | true | false |
String | 任何非空字符串 | ""(空字符串) |
Number | 任何非零数字值(包括无穷大) | o和NaN |
Object | 任何对象 | null |
Undefined | n/a | undefined |
转化规则:
数据类型 | 转化为true的值 | 转化为false的值 |
---|---|---|
Boolean | true | false |
String | 任何非空字符串 | ""(空字符串) |
Number | 任何非零数字值(包括无穷大) | o和NaN |
Object | 任何对象 | null |
Undefined | n/a | undefined |
number 类型
ECMAScript使用IEEE754格式来表示整数和浮点数。
除了十进制外,整数还可以通过八进制或十六进制来表示。
八进制的字面量在严格模式下是无效的,会导致JavaScript引擎抛出错误。
浮点数值
var floatNum1 = 1.1;
var floatNum2 = 0.1;
var floatNum3 = .1; // 有效,但是不推荐
var floatNum1 = 1.; // 小数点后面没有数字,解析为1
var floatNum2 = 10.0; // 解析为整数10
默认情况下,ECMAScript会将那些小数点后面带有6个零以上的浮点数值转换为以e表示法表示的数值。
浮点数值的最高精度是17位小数,但在进行算术计算时其精确度远远不如整数。
if (a + b == 0.3) { //不要做这样的测试
alert("You got 0.3.");
}
数值范围
由于内存的限制,ECMAScript不能保存所有的数值。
Number.MIN_VALUE
ECMAScript中能够表示的最小值。
Number.MAX_VALUE
ECMAScript中能够表示的最大值。
如果某次计算的结果超过了JavaScript数值范围,那么结果会自动转化为特殊的Infinity
值。具体说,如果结果是正数,则转化为Infinity
(正无穷),如果是负数,则转化为-Infinity
(负无穷)。
如果计算返回了Infinity
,那么该值无法继续参加下一次计算。
可以使用isFinite()
函数来确实一个数是否有穷。函数参数位于最小和最大值之间时会返回true
。
var result = Number.MAX_VALUE + Number.MAX_VALUE;
alert(isFinite(result)); //false
NaN
NaN(not a number)是一个特殊的数值,用来表示一个本来要返回数值的操作数未返回数值的情况(这样就不会抛出错误)。
任何涉及NaN
的操作都会返回NaN
。
NaN
与任何值都不相等,包括NaN
本身。
使用isNaN()
来判断是否是 NaN
值。
isNaN()
会将参数转化为数值,不能转化的则返回true
。
alert(isNaN(NaN)); //true
alert(isNaN(10)); //false
alert(isNaN("10")); // false
alert(isNaN("blue")); //true
alert(isNaN(true)); //false
数值转换
有3个可以把非数值转化为数值的函数:Number()
、parseInt()
、paresFloat()
。Number()
用于任何数据类型,而另外两个则专门用于把字符串转化为数值。
Number()
转换规则:
- 如果是Boolean值,true转化为1,false转化为0。
- 如果是数字,则只是简单的传入和返回。
- 如果是
null
,返回0。 - 如果是
undefined
,返回NaN。 - 如果是字符串,则
- 如果字符串中只包含数字(包括前面带正号或负号的情况),则将其转化为十进制数值。
- 如果字符串中包含有效的浮点格式,则将其转化为对应的浮点数值。
- 如果字符串中包含有效的十六进制格式,则将其转化为相同大小的十进制整数。
- 如果字符串为空,则将其转化为0。
- 如果字符串中包含除上述格式之外的字符,则将其转化为NaN。
- 如果是对象,则调用对象的
valueOf()
,然后依照前面的规则转化返回的值。如果转化结果是NaN,则调用对象的toString()
方法,然后在依照前面的规则转化为字符串值。
var num1 = Number("Hello world!"); //NaN
var num2 = Number(""); //0
var num3 = Number("000011"); //11
var num4 = Number(true); //1
一元加操作符的操作和
Number()
函数相同。
parseInt()
会忽略字符串前面的空格,直到找到第一个非空字符。如果第一个字符不是数字字符或者负号,则返回NaN。如果第一个字符是数字字符,则会接着解析第二个字符,直到解析完所有后续字符或者遇到了一个非数字字符。如果字符串的第一个字符是数字字符,parseInt()
也能够识别出各种整数格式。
var num1 = parseInt("1234blue"); //1234
var num2 = parseInt(""); //NaN
var num3 = parseInt(0xA); //10
var num4 = parseInt(22.5); //22
var num5 = parseInt("070"); //56
var num6 = parseInt("70"); //70
var num7 = parseInt("0xf"); //15
ECMAScript3和5在解析上存在分歧。
//ECMAScript3认为是56,ECMAScript5认为是0。
var num = parseInt("070");
为了消除上述的困惑,可以为这个函数提供第二个参数;转化时使用的基数。
var num = parseInt("AF", 16);
parseFloat()
和parseInt()
一样解析字符串,但是parseFloat()
会忽略前导的零。它可以识别所有的浮点数据格式,也包括十进制的整数。但十六进制格式的字符串则始终会被转化为0。它没有第二个参数,当字符串是一个整数时,它会返回整数。
var num1 = parseFloat("1234blue"); //1234整数
var num1 = parseFloat("0xA"); //0
var num1 = parseFloat("22.5"); //22.5
var num1 = parseFloat("22.34.5"); //22.34
var num1 = parseFloat("0908.5"); //908.5
var num1 = parseFloat("3.125e7"); //31250000
String 类型
String类型由零或多个16位Unicode字符组成。
双引号和单引号没有区别。
字符串长度可以通过length
属性来访问。
var text = "This is the letter sigma: \u03a3.";
alert(text.length); //输出28
这个属性返回的字符数包括16位字符的数目。如果字符串中包含双字节字符,那么length
属性可能不会精确的返回字符串中的字符数目。
ECMAScript中的字符串是不可变的,字符串一旦创建,它们的值就不能改变。
要把一个值转化为字符串有两种方式:
- 使用
toString()
方法。
数值、布尔值、对象和字符串值(字符串的toString()返回字符串的一个副本
)都有toString()
方法。但null
和undefined
没有这个方法。
一般情况下调用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()
。规则如下:- 如果值有
toString()
方法,则调用该方法(没有参数)并返回相应的结果。 - 如果值是
null
,则返回null
。 - 如果值是
undefined
,则返回undefined
。
- 如果值有
Object 类型
ECMAScript中的对象其实就是一组数据和功能的集合。
var o = new Object();
如果不给构造函数传递任何的参数,后面的括号可以省略(但是不推荐)。
Object类型所具有的任何属性和方法同样也存在于更具体的对象中。
Object的每个实例都具有下列属性和方法:
- Constructor:保存着用于创建当前对象的函数。
- hasOwnProperty(propertyName):用于检查给定的属性在当前对象(而不是实例的原型)中是否存在。参数必须为字符串。
- isPrototypeOf(object):用于检查传入的对象是否是另一个对象的原型。
- propertyIsEnumerable(property):用于检查给定的属性是否能够使用for-in语句。参数必须为字符串。
- toLocaleString():返回对象的字符串表示,该字符串与执行环境的地区对应。
- toString():返回对象的字符串表示。
- valueOf():返回对象的字符串、数值或布尔值。
操作符
一元操作符###
递增和递减
递增和递减不仅用于数值,还可以用于字符串、布尔值、浮点数和对象。应用与不同的值时,规则如下:
- 包含有效数字字符的字符串时,先将其转化为数字值,在执行加减1操作。字符串变量变成数值变量。
- 布尔值false,先将其转化为0再执行加减1操作。布尔值变成数值变量。
- 布尔值true,先将其转化为1再执行加减1的操作。布尔值变成数值变量。
- 浮点数值,执行加减1的操作。
- 对象,先调用对象的
valueOf()
方法以取得一个可供操作的值。然后在对该值应用前述的规则。如果结果是NaN,则在调用toString()
方法再应用前述的规则。
一元加和减操作符
一元加操作符以一个加号(+)表示,放在数值前面,对数值不会产生任何影响:
var num = 25;
num = +num; //仍然是25
一元减操作符主要用于表示负数。
一元减操作符应用于数值时,该值会变成负数。而当应用于非数值时,一元减操作符遵循与一元加操作符相同的规则,最后将得到的数值转化为负数。
布尔操作符###
布尔操作符一共三个:非(NOT)、与(OR)和或(AND)。
逻辑非
逻辑非操作符由一个感叹号(!)表示,可以应用与ECMAScript中的任何值。无论这个值是什么数据类型,这个操作符都会返回一个布尔值。逻辑非操作符首先会将它的操作数转化为一个布尔值,然后再对其求反。规则如下:
- 对象,返回false
- 空字符串,返回true
- 非空字符串,返回false
- 数值0,返回true
- 任意非0数值(包括Infinity),返回false
- null,返回true
- NaN,返回true
- undefined,返回true
同时使用两个非操作符,实际上就会模拟Boolean()
转型函数的行为。
逻辑与
逻辑与操作符由两个和号(&&)表示。
逻辑与可以操作任何类型的数据,不仅仅是布尔值。在有一个操作数不是布尔值的情况下,逻辑与操作就不一定返回布尔值;规则如下:
- 第一个操作数是对象,则返回第二个操作数
- 第二个操作数是对象,则只有在第一个操作数的求值结果为true的情况下才会返回该对象
- 两个操作数都是对象,则返回第二个操作数
- 有一个操作数是null,则返回null
- 有一个操作数是NaN,则返回NaN
- 有一个操作数是undefined,则返回undefined
逻辑或
逻辑或操作符由两个竖线符号(||)表示。
与逻辑与相似,规则如下:
- 第一个操作数是对象,则返回第一个操作数
- 第一个操作数的求值结果为false,则返回第二个操作数
- 两个操作数都是对象,则返回第一个操作数
- 两个操作数都是null,则返回null
- 两个操作数都是NaN,则返回NaN
- 两个操作数都是undefined,则返回undefined
函数
ECMAScript中的函数在定义时不必指定是否返回值。
函数会在执行完return
语句后停止并退出。
一个函数可以有多个return
。
return
语句也可以不带任何返回值。
严格模式对函数有一些限制:
- 函数不能命名为:eval或argument
- 函数参数不能命名为:eval或argument
- 不能出现相同的参数命名
函数参数
ECAMScript函数不介意传递进来多少个参数,也不在乎参数的数据类型。因为ECMAScript中的参数在内部是用一个数组来表示的。在函数体内可以通过argument
对象来访问这个数组。
命名参数只是提供便利,但不是必须。
其他语言可能要先创建一个函数签名,将来调用必须和签名一致。但是ECMAScript中解析器不会验证命名参数。
argument
对象可以和命名参数一起使用。
没有重载
ECMAScript不能像传统意义上那样实现重载。
如果在ECMAScript中定义了两个名字相同的函数,则该名字属于后者。