JavaScipt 学习笔记(1)
学习笔记。
Java 基本介绍
JavaScipt 的历史
在使用互联网时,我们常常遇到会填写并提交一些表单的情况,HTML 对提交表单有默认的支持,把表单提交到服务器端,服务器端对表单进行检查,如果有不符合要求的值就返回给客户端,客户端修改后再次提交。但是如果能直接在客户端进行验证,验证无误之后再提交给客户端就能节省很多时间。尤其是1995年左右,当时的上网速度还很慢,如果能在客户端进行数据的验证,那么能节省不少时间,JavaScipt就是在这种需求下诞生的。
后来,随着这种语言的发展,语言的标准化被提上日程,1997年,以 JavaScipt 1.1 为蓝本提交给 ECMA(European Computer Manufacturers Association)进行标准化的工作。ECMA 成立了一个技术委员会 TC39,该委员会制定了 ECMA-262 标准,该标准定义了一门新的语言 ECMAScipt(通常发音为“ek-ma-scipt”)。
JavaScipt 实现
JavaScipt 实现包括三个独立的部分
- 核心(ECMASCript)
- The Document Object Model(DOM)
- The Browser Object Model
ECMASCript
ECMA-262 中定义的 ECMAScipt 语言是独立于浏览器的。
ECMA-262主要定义了一下内容:
- 语法
- 类型
- 语句
- 关键字
- 保留字
- 操作符
- 对象
The Document Object Model
DOM
The Browser Object Model
原本关于 BOM 没有什么标准,但是 HTML5 中定义了一些标准。
在 HTML 中运行 JavaScipt
<scipt> 标签
<scipt>
标签有6个属性。
- src - 指定脚本位置
- type - 指定脚本的 MIME 类型。这一项可省略,根据惯例,这一项为
text/javascipt
。 - async - 异步。只对使用 src 来引入外部脚本有效。
- defer - 说明该脚本可以推迟到页面加载完成之后再执行,只对使用 src 来引入外部脚本有效。
- charset - 说明 src 引用的的脚本文件的字符集,很少用,因为很多浏览器不支持。
- language - 已弃用。
将代码直接放在标签中
将代码直接放入标签中时,注意,代码中不能出现 </script>
标签,因为这个标签会被当作脚本结束的标签,从而导致代码不完整运行。
错误示例:
1 | <script> |
如果确实需要在代码中加入 HTML 标签,可以在 <
等符号前加 \
转义。
使用 src 引用脚本文件
当浏览器下载并运行脚本文件时,会暂停页面的渲染等工作。
不要在使用 src 引用脚本文件的同时在 <scipt>
标签中包含代码,如果同时使用,那么 <scipt>
标签中包含的代码会被忽略。
使用 src 引用外部脚本的时候一定要确保来源是可信的,因为有可能会加载到恶意代码。
如果 <scipt>
标签没有开启 async
或者 defer
选项,那么所有 <scipt>
标签是按照他们在 HTML 中出现的顺序依次执行的。
标签的位置
在加载 <scipt>
标签中制定的 JavaScipt 脚本的时候,浏览器是停止渲染的,所以如果有很多脚本放在网页正文之前,那么用户可能能够明显感受到页面加载的延迟。所以一般把 <scipt>
脚本放在 <body>
标签的最下方,这样就不会影响页面的渲染。
Deferred Scripts 延迟脚本
HTML 4.01 标准为 <scipt>
标签添加了 defer
属性,当一个 <scipt>
标签带上了 defer
,那么就是说这个脚本执行后不会影响 HTML 页面的结构,所以可以延迟执行。
HTML5 标准规定所有 defer
的脚本会按照顺序执行,但是实际上并不一定,所以最好不要指望他们按照顺序执行。
从 Intenet Explorer 4,FireFox 3.5,Safari 5,Chrome 7 开始才支持 defer
属性,有的浏览器直接忽略 defer
属性,所以有时候为了兼容性,最好还是把脚本放在 <body>
标签的末尾。
Asynchronous Scipts 异步脚本
HTML5 标准为 <scipt>
标签添加了 async
属性。
指定了 async
属性的脚本不会按照顺序执行,相互之间互不影响,所以不要让脚本之间有执行顺序上的依赖关系。
异步脚本一定会在网页的 load
事件之前执行,可能在 DOMContentLoaded
事件之前或者之后执行。
Inline Code VS External Files (内嵌脚本 VS 外部脚本文件)
- 可维护性。维护成体系的 JavaScipt 项目文件比维护分散在 HTML 文件中的代码更方便。
- 缓存。多个网页使用同样的脚本文件时,浏览器可以方便地使用缓存,提高网页加载速度。
- 兼容性。由于历史原因,使用内嵌脚本可能有一些兼容性问题需要考虑。
<noscript> 标签
当浏览器不支持 JavaScipt 或者 浏览器的 JavaScipt 支持功能被关闭时,<noscipt>
标签中的内容就会被渲染并显示。
语言基础
语法
ECMAScipt 的语法和 C 语言以及类C语言比如 Java、Perl 相似,如果对以上语言有了解,那么应该很容易熟悉。
区分大小写
ECMAScipt 中的一切都是区分大小写的。
标识符
对标识符有以下规定:
- 标识符的第一个字符必须是一个字母、下划线(
_
)或者美元符号($
)。 - 其他的字符可以是字母、下划线、美元符号或者数字
字母可以是拓展的 ASCII 字符,也可以是 Unicode 字符,不过并不推荐使用这些字符。
注释
注释方式和 C 语言一样,支持单行注释和块注释两种形式。
1 | // 第一种注释:单行注释 |
Strict Mode 严格模式
ECMAScipt 5 中引入了严格模式。在严格模式下,ECMAScipt 3 中的一些不确定的行为将得到处理,而且对于不安全的操作也会抛出错误。
要在整个脚本中开启严格模式,在脚本顶部添加:
1 | ; |
也可以只针对某个方法开启严格模式:
1 | function doSomething(){ |
语句
JavaScipt 可以使用分号来标记语句结尾,也可以不加分号,推荐加分号。
加分号之后因为可以准确知道每句的结尾,还可以对脚本进行压缩,删去空白字符。在某些情况下还可以改善性能表现。
关键字和保留字
关键字
1 | break do instanceof typeof case else |
保留字
1 | abstract enum int short boolean export |
在 ECMAScipt5 中规定,在非严格模式下,保留字只有以下这些:
1 | class enum extends super |
如果开启了严格模式,那么以下的也是保留字:
1 | implements package public |
其中,let
和 yield
是 ECMAScipt5 引入的,其他的都是 ECMAScipt3 引入的。
ECMAScipt5 中还对 eval
和 arguments
两个关键字的使用做了限制,不能用作标识符和属性名。
变量
变量可以存储任何类型的值。
使用 var message;
这种形式来定义变量,可以在定义变量的同时初始化,比如 var message = "Hello";
,如果不在定义变量的时候初始化,那么变量的值就是 undefined
。
使用一个字符串为一个变量赋值,并不代表这个变量变成了字符串类型,此时还可以把任何类型赋值给变量,比如:
1 | var messages = "Hello"; |
这样是合法的,但是不推荐这么写。
使用 var
关键字定义的变量的作用域是有限的,如果是在函数中定义的变量,那么函数推出之后,变量自动被销毁。
如果不使用 var
关键字,在函数中直接对一个标识符赋值,那么这个标识符自动变成一个全局变量。如:
1 | function test(){ |
但是不建议在函数内部定义全局变量,这样不利于程序的可维护性。
可以同时定义多个变量:
1 | var message = "hi", |
数据类型
ECMAScipt 有5种简单数据类型,也叫基本数据类型:Undefined,Null,Boolean,Number,String。还有一种复杂数据类型叫 Object,是一个包含 name-value 键值对的无序列表。
typeof 操作符
可以使用 typeof
操作符确定一个变量的类型。
typeof 的返回值如下:
- “undefined” if the value is undefined
- “boolean” if the value is a Boolean
- “string” if the value is a string
- “number” if the value is a number
- if the value is an object (other than a function) or null
- “function” if the value is a function
因为 typeof
是运算符不是函数,所以 typeof
后便可以不跟括号,也可以跟括号。
Undefined 类型
如果不对一个变量初始化,那么变量就被初始化为 undefined
。
对未初始化的变量调用 typeof
,会返回 undefined
,对未定义的变量调用 typeof
也会返回 undefined
。所以建议定义变量的时候进行初始化,这样当 typeof
操作符返回 undefined
时我们就知道是因为这个变量没有定义。
Null 类型
Null 类型的变量有一个特殊的值:null
。
当要定义一个指向对象的变量的时候,最好在初始化的时候显式地初始化为 null
。
undefined
其实是 null
类型派生出来的一种类型,所以 ECMA-262 规定两者相等。