本系列内容由ZouStrong整理收录
整理自《JavaScript权威指南(第六版)》,《JavaScript高级程序设计(第三版)》
JavaScript是面向Web的编程语言,所有的浏览器都包含了JavaScript解释器
JavaScript是一门动态的、弱类型的、面向对象的、解释型语言,非常适合面向对象和函数式的编程风格
JavaScript的用途早已经不再局限于此,也超出了“脚本语言”本身的范畴,而是具备了与网页内容和浏览器窗口等几乎所有方面交互的能力,并且随着Node.js的普及,在非浏览器环境(服务端)的表现一样十分强大
JavaScript原名LiveScript,Netscape为了搭上媒体热炒]ava的顺风车,才把LiveScript改名为JavaScript(所以Java和JavaScript的关系,就相当于雷锋和雷峰塔的关系)
随着JavaScript的普及,IE浏览器也加入了名为JScript的JavaScript实现,由于没有语言标准,导致了不同的语法和特性支持,因此JavaScript标准化被题上日程
1997年,欧洲计算机制造商协会( ECMA)定义了名为ECMAScript(ECMA-262)的脚本语言标准,它是通用的,与平台无关的语言标准
自此以后,浏览器开发商开始致力于将ECMAScript作为各自JavaScript实现的基础(基础虽然相同,但具体实现在不同浏览器上却略有不同)
一个完整的JavaScript实现包括以下三点
ECMAScript不针对任何特定浏览器,与浏览器没有依赖关系,并且本身并不包含输入和输出定义
ECMAScript定义的只是这门语言的基础,而在此基础之上可以构建更完善的脚本语言。Web浏览器只是ECMAScript实现的宿主环境之一(其他宿主环境包括Node.js和Flash等)
宿主环境不仅实现了基本的ECMAScript语法,也对其进行了扩展(新的API),而这些扩展——如DOM,则利用ECMAScript 的核心类型和语法提供更多更具体的功能
ECMAScript规定了这门语言的下列组成部分:
文档对象模型( DOM, Document Object Model ) 是一个应用程序编程接口( API, Application Prograrmning lnterface),把整个页面映射为一个多层节点结构
借助DOM 提供的API ,可以轻松的删除、添加、替换或修改任何节点
DOM规范的最新版为——DOM 3级
浏览器对象模型( BOM, Browser Object Model ) 是一个应用程序编程接口,把整个浏览器窗口映射为一个对象
借助BOM提供的API ,可以控制浏览器窗口的表现和行为
BOM最让人头疼的是没有相关的规范和标准,每个浏览器都有独有的实现(这个问题在HTML5 中得到了解决,HTML5把很多BOM功能规范化)
JavaScript对于页面的价值应该是"有了会更好"而不是"我离不开你",也就是说使用JavaScript应尽可能提高可访问性,而关闭JavaScript后,页面仍然都能正常访问
总的来说,使用JavaScript的好处有
引入JavaScript使用<script>元素,它拥有6个可选的属性
<script type="text/javascript"></script>
表示脚本类型,一般情况值都为"text/javascript",但是HTML5已经不推荐加入该属性,因为默认都是引入JavaScript脚本
<script src="js/script.js"></script>
表示要引入的外部JavaScript文件的URL
表示通过src属性引入的脚本的字符编码(几乎不用)
已废弃,由type属性代替
表示异步脚本,页面解析到script时,该脚本会立即被下载,同时执行,但不妨碍页面其它元素的继续加载和解析
只对外部脚本文件有效
表示延时脚本,页面解析到script时,该脚本立即下载,但延迟到文档完全被解析和显示之后再执行
只对外部脚本文件有效
使用defer属性,可以让脚本在文档完全呈现之后再执行。延迟脚本总是按照指定它们的顺序执行
使用async属性,可以表示当前脚本不必等待其他脚本,也不必阻塞文档呈现(所以不要在异步脚本里处理DOM,除非脚本放在了页面底部)。但不能保证异步脚本按照它们在页面中出现的顺序执行
引入JavaScript有两种方式:
<script>
//代码在这
</script>
包含在<script>元素内部的JavaScript 代码将被从上至下依次解释,并且在解释完毕之前,其后的内容都不会被加载
使用嵌入代码时,不要在代码中的任何地方出现"</script>" 字符串,因为会被浏览器解析为闭标签</script>(外部JS文件中可以出现)
可以通过转义和字符串拼接方法来解决该问题
alert("<\ /script>");
alert("</sc"+"ript>");
<script src="example.js"></script>
与解析嵌入式JavaScript 代码一样,外部文件代码将被从上至下依次解析,在解析外部JavaScript 文件(包括下载该文件)时,页面的处理也会暂时停止
带有src属性的<script>标签之间的嵌入式JavaScript代码会被忽略
<script src="example.js">
alert(1); //永远不会执行
</script>
通过<script>元素的src属性不仅可以引入与包含它的页面位于同一个服务器上的文件,还可以包含来自外部域的JavaScript文件(不受同源策略的限制,图片也是如此),这也是不安全的因素,谁也不知道第三方脚本是否包含恶意代码
无论如何包含代码,只要不存在defer和async属性,浏览器都会按照<script>元素在页面中出现的先后顺序对它们依次进行解析
外部JavaScript文件可维护、可缓存、适应未来,因此推荐使用
一开始<script>元素都是位于<head>元素中,这样做的主要目的就是把所有外部文件(包括CSS文件和JavaScript 文件)的引用都放在相同的地方,方便管理
但是,这样做意味着必须等到全部JavaScript代码都被下裁、解析和执行完成以后,才能开始呈现页面的内容(浏览器在遇到<body>标签时才开始呈现内容),有可能会导致页面呈现出现延迟
因此把<script>元素放在闭标签</body>之前,这样,在解析JavaScript代码之前,页面的内容已经完全加载
当浏览器不支持JavaScript或者用户禁用了JavaScript功能时,才会将该元素中的内容显示出来,该元素使用的唯一目的也正是如此(元素内部可以嵌套除了script元素之外的任何元素)
JavaScript使用Unicode字符集(统一码、万国码——支持所有语言)
HTML、CSS使用的是UTF-8
JavaScript中的一切——变量、函数名、关键字以及所有标识符,都区分大小写
JavaScript会忽略程序中标识之间多余的空格和换行
因此可以采用整齐,一致的缩进来形成统一的编码风格,提高代码可读、可维护性
标识符是指变量、函数、属性的名字,或者函数的参数
标识符需符合以下规则
通常我们只使用ASCII字母(a~z,A~Z)和数字(0~9)来书写标识符,然后,要知道的是,JavaScript允许标识符使用Unicode字符全集中的字母和数字(当然包括汉字)
此外,标识符建议采用驼蜂大小写格式书写(第一个字母小写,剩下的每个有意义的单词的首字母大写,这样与内置的函数和对象命名保持一致,是一种最佳实践)
strong、getName、setAgeFull、
不能把关键字、保留字、true、false、null等用作标识符
关键字(特殊用途)和保留字(留做特殊用途)不能用作标识符或者对象属性,在此不再列举
估计没有谁会把保留字或者关键字用做标识符,因为保留字或者关键字都比较常见,退一万步讲,编辑器也会给予高亮提示的
ECMAScript 5规定:关键字和保留字不能用作标识符,但可以用作对象的属性名,呵呵哒,谁爱用谁用
// 这是 单行注释,不可换行
/*
*这是多行注释,可多行,但不可嵌套
*为了提高多行注释的可读性
*最好每一行都以星号开头
*/
注释的适当应用可以提高代码的可读性、可维护性,并且还可以用来调试程序
ECMAScript 5引入了严格模式( strict mode),对ECMAScript 3中的一些不确定的行为进行了规范
只需在代码顶部使用如下代码即可开启严格模式
"use strict";
//开启严格模式
//这是一个编译指示(pragma ),不属于JavaScript代码
//仅仅表示将JavaScript 引擎切换到严格模式
在函数顶部包含这条编译指示,可以仅让该函数在严格模式下执行
function doSome(){
"use strict"; //只在该函数内部开启严格模式
}
"use strict";是一条编译指示,不是语句,对于不支持的浏览器,它什么也不做,不产生副作用
JavaScript的语句以分号结束(控制语句除外),但如果语句各自独占一行,那么分号是可选的,如果省路了分号,则由解析器来确定语句的结尾
通常的规则是——当前语句和下一语句无法合并解析时,JavaScript才会在第一行后填补分号
var
a
=
3; //解析为 var a = 3;
总是给语句加上分号是一个最佳实践——可以增强可读性、(轻微的)提高代码的性能(解析器就不用自己判断分号位置了)、避免出现BUG、还可以放心压缩代码
之所以说可以避免BUG,是因为,如果下一行的第一个字符是下面这五个字符之一
( [ / + -
JavaScript将不对上一行句尾添加分号(因为可以合并解析)
var x = y
(function (){ ....})();
等同于
var x = y (function (){...})(); //出错
因此,在写立即执行函数的时候,总是在函数前加上分号,这样哪怕之前的语句不小心省略了分号,也不会出错
;(function(){
})();
上面提到,当前语句和下一语句无法合并解析时,JavaScript才会在当前语句后填补分号,但有两个例外
首先就是return、break、continue语句
return
true; //解析为 return; true;
也就是return、break、continue和之后的表达式之间不能有换行
另外一个例外就是自增和自减运算符
x
++
y
总是解析为 x;++y;(前缀)
所以说,语句结尾的分号不是必需的,但任何时候都不要省略它
代码块用于组织多条语句
虽然条件控制语句(如if语句)只在执行多条语句的情况下才要求必须使用代码块,但最佳实践是始终在控制语句中使用代码块——即使代码块中只有一条语句(这样增加代码的可读性、可维护性)
字面量(直接量),就是程序中直接使用的数据值
12 //数字字面量
"hello" //字符串字面量
true //布尔值字面量
[1,2,3] //数组字面量
{name:"strong"} //对象字面量
/[Ss]trong/ //正则表达式字面量
JavaScript是松散类型(弱类型)的语言,同一个变量可以用来保存任何类型的数据
每个变量仅仅是一个用于保存值的占位符而已,更确切的说,是内存中的一块空间
定义(声明)变量使用var运算符,后跟一个标识符
var myName; //声明但未初始化,自动获得undefined值
也可以在定义(声明)变量时直接赋值(初始化)
var myName = "zsz"; //声明并初始化
myName = 12 ; //修改变量值和类型,有效但不推荐
初始化变量并不会把变量标记为某种数据类型,初始化的过程就是给变量赋一个值那么简单(更本质的说,就是向变量对应的存储空间中存入一个值),变量是无类型的,类型说的只是变量中保存的值,所以永远不要说某个变量是什么类型的,而应该说该变量保存的值是什么类型的
可以使用一条语句定义多个变量,只要把每个变量(初始化或不初始化均可)用逗号分隔开
var myName = "zsz" , //换行和缩进,提高可读性
myAge = 24,
yourName;
变量也可以不经声明,直接使用,只需要省略var运算符即可,与使用var声明的变量相比,有如下不同:
此外还要注意这样一种情况
var a=b=3;
赋值运算从右往左,因此相当于
b=3; //无意中创建了一个全局变量,谨慎
var a=b;