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
2
3
4
5
<script>
function sayScript(){
alert(“</script>”);
}
</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
2
3
4
5
6
// 第一种注释:单行注释

/*
* 这是
* 块注释
*/

Strict Mode 严格模式

ECMAScipt 5 中引入了严格模式。在严格模式下,ECMAScipt 3 中的一些不确定的行为将得到处理,而且对于不安全的操作也会抛出错误。

要在整个脚本中开启严格模式,在脚本顶部添加:

1
"use strict";

也可以只针对某个方法开启严格模式:

1
2
3
4
function doSomething(){
"use strict";
// function body
}

语句

JavaScipt 可以使用分号来标记语句结尾,也可以不加分号,推荐加分号。

加分号之后因为可以准确知道每句的结尾,还可以对脚本进行压缩,删去空白字符。在某些情况下还可以改善性能表现。

关键字和保留字

关键字

1
2
3
4
5
break     do    instanceof  typeof   case       else
new var catch finally return void
continue for switch while debugger* function
this with default if throw delete
in try

保留字

1
2
3
4
5
6
abstract   enum        int        short         boolean  export
interface static byte extends long super
char final native synchronized class float
package throws const goto private transient
debugger implements protected volatile double import
public

在 ECMAScipt5 中规定,在非严格模式下,保留字只有以下这些:

1
2
class  enum    extends  super
const export import

如果开启了严格模式,那么以下的也是保留字:

1
2
3
implements  package    public
interface private static
let protected yield

其中,letyield 是 ECMAScipt5 引入的,其他的都是 ECMAScipt3 引入的。

ECMAScipt5 中还对 evalarguments 两个关键字的使用做了限制,不能用作标识符和属性名。

变量

变量可以存储任何类型的值。

使用 var message; 这种形式来定义变量,可以在定义变量的同时初始化,比如 var message = "Hello";,如果不在定义变量的时候初始化,那么变量的值就是 undefined

使用一个字符串为一个变量赋值,并不代表这个变量变成了字符串类型,此时还可以把任何类型赋值给变量,比如:

1
2
var messages = "Hello";
message = 100;

这样是合法的,但是不推荐这么写。

使用 var 关键字定义的变量的作用域是有限的,如果是在函数中定义的变量,那么函数推出之后,变量自动被销毁。

如果不使用 var 关键字,在函数中直接对一个标识符赋值,那么这个标识符自动变成一个全局变量。如:

1
2
3
4
5
function test(){
message = "hi"; //global variable
}
test();
alert(message); //"hi"

但是不建议在函数内部定义全局变量,这样不利于程序的可维护性。

可以同时定义多个变量:

1
2
3
var message = "hi",
found = false,
age = 29;

数据类型

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 规定两者相等。

Boolean 类型