JavaScript
是一种脚本语言,可以在浏览器中执行,和 Java
需要先编译成字节码文件然后再运行不同,JavaScript
直接由浏览器解释执行,即解释一句执行一句,不过 JavaScript
一般都是在客户机的浏览器上面运行,相比于需要集中处理众多请求的后台 Java
代码来说,运行效率相对来说就还好,因为毕竟只需要负责客户机这一个终端。
JavaScript
是由三部分组成,分别是 ECMAScript
、DOM
和 BOM
,ECMAScript
的产生是有原因的,因为虽然 JavaScript
是由Netscape
(网景)公司开发出来,但在浏览器的使用中可不止这一种,还有微软公司的 JScript
,当然主要就是用在 IE
浏览器之中了,除此之外,就还有 CEnvi
的 ScriptEase
,这三种不同的实现对于程序员开发可就是麻烦事了,必须要先使用大量的嗅探程序判断出当前运行的是什么浏览器以及使用的是哪一种 JavaScript
,其中一个最常见的例子就是获取网页中的一个元素在不同的浏览器中都是不同的实现,为了解决这个问题,欧洲计算机制造商协会(ECMA)就想根据大家的各自情况,提出一种大家都能遵从的标准,该标准主要定义的就是 JavaScript
的核心语法,这样也就能让这种语言更好的发展,不然肯定会被其它优秀的脚本语言所取代,现在网景公司已经不存在了,IE
浏览器的市场份额也下降了很多,不过新出现的浏览器,比如苹果公司的 Safari
浏览器和谷歌公司的 Chrome
浏览器都很好地实现了上面的标准,值得说一下的是网景公司,产生了许多的优秀的产品和想法,其实之前乔布斯的自传中也提到过,他去网景公司参观,有很多优秀的理念,比如图形化界面、面向对象编程,而乔布斯带回苹果公司的就是图形化界面,当然面向对象编程的重要性对于我们程序员来说就不在这里赘述了,大家有兴趣的可以去查一下这家公司。说完了 ECMAScript
,JavaScript
的第二部分就是 DOM
了,也就是文档对象模型,就是将一个页面看做是一个文档,而页面中的标签也就看做是文档的元素,当然使用JavaScript
操作起网页中的元素也就十分简单了,最后一部分是 BOM
,浏览器对象模型,就是用来和浏览器来打交道的,是一组用来操作浏览器的预定义对象。
JavaScript组成部分:
ECMAScript:定义了JavaScript中的核心语法
DOM:文档对象模型
BOM:浏览器对象模型
1.ECMAScript(核心语法)
1.1 引入JavaScript脚本的方式
要在页面中使用 JavaScript
,其实就是将 JavaScript
代码引用到相应的页面中,第一种方式就是直接在页面中写代码,具体方式就是将 JavaScript
代码使用 script
标签括起来,至于应该将代码具体放在什么位置,学习阶段可以直接放在 head
标签之中,开发阶段放在 body
标签结束之前比较好,这么做的原因是因为 JavaScript
代码是由浏览器从上往下依次解释执行的,如果 script
标签中有代码是获取某个页面元素对象的,而这时代码是放在 body
标签之前的,那么获得的只是 null
,因为浏览器还没有加载之后的页面,也就当然不可能获得页面之中的元素了,当然注意一下就好,并且以后开发都会将代码组织到函数之中,调用函数就不会出现这个问题了。
第一种方式:
<script>
js代码
</script>
引入 JavaScript
的第二种方式就是外部引用了,就是将 JavaScript
代码抽取为一个独立的文件,而在需要使用的页面进行引用。
第二种方式:
<script src=”001.js” type=”text/javascript”>
</script>
001.js
alert(“hello”);
需要注意的一点是如果使用外部引用的方式,那么在页面引用外部文件的 script
标签之间是一定不能写代码的,浏览器不会那么聪明地认为我们是想既引用外部文件,也使用页面之中的 JavaScript
代码。
1.2 JavaScript中的注释、变量以及基本数据类型
注释:
每种语言都会有注释,因为使用注释可以极大地提高代码的可阅读性,Java
之中有三种注释,而 JavaScript
与之相比的话则没有文档注释,就只有单行注释和多行注释。
单行注释://
多行注释:/* */
变量:
首先说一下,JavaScript
中的变量使用什么关键字声明,Java
之中可是有很多种关键字可以接受变量声明的,但是在 JavaScript
这里,由于它是一种弱类型语言,不管是基本数据类型还是变量类型,都统一使用 var
关键字进行接受,不过需要注意的一点就是 JavaScript
也是区分大小写的。
var i = 10;
var j = "hello";
var k = true;
var l = 10.34;
上面这几种写法都是正确的,因为 var
关键字可以接受所有的变量类型。至于变量名的取名规则就不在这里说明了,其实和 Java
中是一样的,并且在实际的开发过程中,最好使用见名知意的名字,并且使用驼峰式命名。
基本数据类型:
JavaScript
中的基本数据类型如下:
String 字符串类型。””和’’都是字符串。 JavaScript中没有单个字符
Boolean 布尔类型。 固定值为true和false
Number 数字类型。 任意数字
Null 它只有一个专用值 null,即它的字面量
Undefined 未定义类型,该类型只有一个固定值,即undefined,表示变量声明却未定义具体的值。
主要需要注意的一点就是:由于 undefined
是从 null
中派生出来的,所以 undefined = null
在 JavaScript
的编程当中,是可以将一个字符串复制给一个引用着数字的变量的,在 JavaScript
中这是合法的,而且为了判断一个变量当前引用的是什么类型的数据,也提供了一个运算符,那就是 typeof
, typeof s =="string"
则是判断 s
是否是一个字符串。
1.3 JavaScript中的运算符
JavaScript
中的运算符对比与 Java
中的,大部分运算符的功能都是一样的,需要注意一下的就是比较运算符和逻辑运算符了。
比较运算符:
这里说明的便是 ==
和 ===
,==
运算符比较两个变量是否相等的时候只比较两个变量的值,只要其中的值相等就返回 true
,否则就返回 false
;而 ===
运算符在进行比较两个变量的时候,不仅会比较两个变量的值是否相等,而且会比较这两个变量的数据类型,只有当值和数据类型都相等的时候才会返回 true
,否则就会返回 false
.
逻辑运算符:
逻辑运算符主要就是进行与运算和或运算,只不过在 JavaScript
中比较特殊的一点就是,没有 &
和 |
,只有 &&
和 ||
。
1.4 JavaScript中的正则表达式对象和数组对象
正则表达式对象:
JavaScript
创建正则表达式的两种方式如下:
第一种(创建对象方式):
var patt1=new RegExp("正则表达式");
第二种(直接量方式):
/^正则表达式$/
第一种方式因为要创建对象,所以并不常用,使用的比较多的还是第二种方式,其实也是一个正则对象,不用引号包裹。是用一对 /
包裹,^
表示字符串开始,$
表示字符串结束。
使用对象的 test(字符串)
方法,返回 true
就代表字符串符合正则表达式,否则就是不符合。
还有一种情况就是像 /正则表达式/
这样的正则对象,与之前的差别就是没有开始和结束标记,使用这种正则对象的 test()
方法就表示只要字符串中的其中一个字符符合正则表达式就会返回 true
,因此带有开始和结束标记的正则对象适合用于表单验证,而没有开始和结束标记的则适合用于字符串的查找和替换。
数组对象:
声明数组的几种方式:
1.var arr = [“hello”,3,5,true];
2.var arr2 = new Array();
3.var arr3 = new Array(3); //不推荐 数组的长度是3
4.var arr4 = new Array(“hello”,”a”);//不推荐
使用的最多的还是前两种方式,要么直接给出元素值,要么就只是创建,具体的操作还是看程序的执行。
数组长度:
在开发的过程中,数组的长度是十分有用的,比如遍历数组,其实每个数组都会有一个 length
属性,可以获得数组的元素个数,也就是数组的长度。
不过如果想在 JavaScript
中直接清空数组的话那就要简单的多,直接将数组长度设置为 0
就好了。
数组的相关方法:
join()
方法:将数组之中的元素放入一个字符串当中,并且元素之间使用指定的分隔符进行分隔
reverse()
方法:将数组中的元素进行反转,即第一个元素和最后一个元素位置互换,第二个元素和倒数第二个元素位置互换,依次类推
pop()
方法:将数组中的最后一个元素删除并返回
push()
方法:向数组中添加一个或多个元素并返回数组的长度
1.5 JavaScript中的全局函数和自定义函数
其实很多东西都可以直接在 W3CSchool
的文档中查到,比如之前的数组和现在要说的全局函数,实际编程的时候,也最好像之前写 Java
程序一样,多去查询 API
等文档。
全局函数:
eval()
函数:这个函数需要传入的参数是一个字符串,而这个函数的作用就是将这个字符串转换为一个 JavaScript
表达式或者可执行的语句,可以是 "1+2"
这样的字符串,也可以是像 "var i =10;"
这样的语句,其实在这里举的两个例子都只是为了说明这个函数确实可以做到将字符串转换为像上面这样的 JavaScript
脚本去执行,但是在开发过程中,使用的最多的还是使用这个函数去解析 json
格式的字符串,就是将这一个字符串转换为一个 json
对象,因为前后台的交互使用 json
会十分方便,因此后台传过来的 json
数据就可以像这样直接传给前台的 JavaScript
去解析了,非常方便。
encodeURI()
和 decodeURI()
这两个方法主要是用于对数据的编码和解码,之前已经提到过,我们在用 get
方式提交表单数据的时候,就可以看到诸如 "?username=kobe&password=lakers"
这样的数据,也提到过一个问题,那就是如果 username
对应的值如果是 kobe&paul
,那是不是在提交到后台的时候就会发生解析错误呢?可是并没有啊,那是为什么呢?就是因为在前台提交的时候经过了 encodeURI()
函数编码,然后在后台的时候经过了 decodeURI()
解码,因此 username
对应的值中即使存在像 &
这样的字符,也会被转换成别的字符序列,因此就不会出现问题了。
parseInt(string)
和 parseFloat(string)
这两个函数一看到就感觉很熟悉,就是因为之前在 Java
中存在类似的方法,也是将字符串转换为对应字面的整形数值或者浮点型数值,那进行转换的过程是怎样的呢?其实是一个字符一个字符进行转换的,直到碰到不能转换的字符为止,就将前面能够转换的字符转换成数值,并作为结果进行返回,那要是一开始就碰到一个不能转换的字符呢?那就会直接返回一个 NaN
,意思就是 Not a Nomber
,表明不是一个数字。
自定义函数:
自定义函数有两种创建方式,如下可以看出区别:
方式一:
function 函数名(函数参数列表){
函数体;
}
例子:
function sum(a,b){
return a+b;
}
方式二:
var 函数名 = function(参数列表){
函数体;
}
例子:
var sum = function(a,b){
return a+b;
}
关于函数需要注意的几点:
JavaScript
的函数其实都是有返回值的,当函数体中没有写return
和只写return;
的时候,其实是默认的返回undefined
JavaScript
中不存在函数重载,即使有多个函数重名,那也只会发生覆盖,即后面一个函数覆盖前面一个函数,所以只会保留最后一个函数JavaScript
中的函数被调用的时候不会看参数列表的个数,而只会看函数名,即使参数列表有两个参数,而调用的时候没有传入参数,那也是可以的,只是其中的参数没有值而已
1.6 自定义对象
先看自定义对象的第一种方式吧,格式和自定义函数是一样的
function Animal(){
}
function Person(name,age){
this.name = name;
this.age = age;
}
这两种方式都是可以的,与 Java
中的对象不同,Java
中创建对象是以类为模板的,而类定义了哪些成员变量和成员方法,那每一个新建出来的对象就有哪些成员变量和成员方法,但是 JavaScript
中却不一样,像上面的 Animal
对象,里面一个成员变量都没有,但是在接下来的编程中还是可以这样写:
var animal = new Animal();
animal.name = "大熊猫";
animal.age = 3;
alert(animal.name+","+animal.age);
这样写一点问题都没有,而且还可以在浏览器中完美运行,打印出对象的姓名和年龄,有时候感觉 JavaScript
真是太灵活了,不仅在这里可以看出来,其实在之前的数组中也可以看出,JavaScript
中的数组和 Java
中的集合很像,但是关于 JavaScript
的数组,如果最开始声明一个数组只有 3
个元素,当我想直接给这个数组的第 5
个元素赋值的时候,绝不会像 Java
中那样出现数组下标越界异常,它会直接给这个数组的第 5
个元素赋值,而且数组的长度也变成了 5
,其中没有赋值的元素仍然默认是 undefined
,并且在 JavaScript
的数组取值也是一样的,数组长度是 3
,取第 5
个元素,也不会发生异常。
关于第二个对象 Person
的声明,运行下面的程序也没有问题。
var person = new Person("博人",10);
alert(person.name+","+person.age);
关于上面创建自定义对象的方式,理解起来还是和 Java
中的方式有的像的,不过下面创建自定义对象的直接量方式,也就是 json
方式,也是很重要的内容,因为以后开发中 json
会用到很多。
var person = {
name:"kobe",
age:40
};
对,就是这一种方式,属性与属性值之间以键值对的方式排列,而且不同的属性之间使用逗号 ,
相分割。还可以看一下下面的代码:
person.name = "paul";
person.age = 34;
person.sex = "男";
alert(person.name+","+person.age+","+person.sex);
也是可以完美运行,这样就可以看出 json
这种方式的灵活性。
2.BOM(浏览器对象模型)
这就是想介绍的关于 JavaScript
的第二部分—浏览器对象模型,听名字就可以猜出,这个的主要作用是和浏览器打交道的,之前我们输出自定义对象的各个属性值时,是使用的 alert(person.name+","+person.age+","+person.sex);
这样的方式将值在浏览器中弹出显示的,其实这个 alert()
方法就是 BOM
中的 window
对象的一个方法,作用就是就是在浏览器中弹框显示数据。
上面的 alert()
就是一个警告框,其实 window
对象中还有一个确认框,那就是 confirm()
方法,其中也可以传入一个字符串参数,一般都是一个询问的语句,在浏览器的显示效果就是一个弹框,显示上面的询问语句,语句下面就还有两个按钮,一个确认按钮,一个取消按钮,如果用户选择的是确认按钮,那么 confirm()
方法将会返回 true
,而如果用户选择的是取消,则会返回 false
。
BOM
的 window
对象还有两个定时器方法,一个是循环定时器,另一个则是一次性定时器。
循环定时器:
设置:var id = setInterval("函数名()",时间(以毫秒为单位));
清除:window.clearInterval(id);
一次性定时器:
设置:var id = setTimeout("函数名()",时间(以毫秒为单位));
清除:window.clearTimeout(id);
关于浏览器的话就还有一个很常见的功能,便是页面的前进和后退,这次要使用的便是 window
中的 history
对象,先看下面的代码示例:
window.history.go(-1); //返回上一页
history.go(1); //转到下一页
history.back(); //等效于 history.go(-1);
history.forward(); //等效于history.go(1);
当然要使用这个对象来控制浏览器中页面的上一页和下一页,前提肯定是需要浏览器之中已经有了浏览记录,这样才能展示上述的效果。
最后想说的一点是关于在 HTML
页面之间进行跳转,就要使用 window
中的 location
对象,其中的 href
属性便可以设置要跳转到的页面。
location.href = url;
3.DOM(文档对象模型)
在实际的编程开发中,除了 JavaScript
的基础语法之外,DOM
就是运用的最多的了,因为为了展示与用户进行交互的效果,就必然要使用 JavaScript
来操作 HTML
网页之中的标签、文本以及属性,而这上面的三个部分,在 DOM
的概念之中就刚好是相对应的节点(元素节点、文本节点、属性节点),使用 DOM
中的对象来操作它们会变得非常简单。
其实当一张 HTML
网页被加载到内存中时就会被看做是一棵 DOM
树,而页面之中的标签、文本以及属性就会被当做一个一个的节点,它们之间有父子关系,也有兄弟关系。
3.1 获取元素节点对象
在实际编程的过程中,只有先获得网页中的元素,才能对它进行修改,而表示当前文档对象的 document
提供了多种方法用来获取文档之中的元素对象,先列在下面:
1.getElementById()
2.getElementsByName()
3.getElementsByClassName()
4.getElementsByTagName()
第一个方法 getElementById()
是通过元素的 id
属性来获取元素对象,因为一般元素的 id
都是唯一标识一个元素的,因此调用该方法获得的是一个对象,而不会像其它方法获得一个对象数组。
第二个方法 getElementsByName()
与第一个方法相类似,这次是通过元素的 name
属性来获得对象,不过由于可以有多个元素的 name
属性取同一个值,因此这个方法返回的会是一个对象数组,想取得其中的某一个元素对象的话就要使用数组获得数组中元素的方法了。
第二种方法是通过元素的 name
属性来回去对象,而这第三种方法则是通过元素的 class
属性来获得元素对象,和第二种方法相类似的是,由于多个元素的 class
属性取值也可以是一样的,因此这个方法返回的也是一个数组。
第四种方法是通过元素的标签名来获得元素对象,比如通过 div
或者 font
标签,一个网页中有多个相同标签是十分常见的事,因此这个方法返回的也是一个数组。
其实解释完上面的四个方法,突然感觉这不是和 CSS
之中的选择器差不多吗,都是为了获得网页之中想要获取的标签,只不过 CSS
是为了美化修饰页面,而 JavaScript
是为了做与用户进行交互的动态效果之类的,不过还是很容易看出相似点的。
获取元素节点对象注意点:
有一个容易犯错的地方就是,放在 head
标签之中的 script
标签,其中也写了 JavaScript
代码,比如说是一个获取网页中某元素标签,比如 var obj = document.getElementById("oid");
,而 id
属性的属性值是 oid
的元素标签也确实存在于 body
标签之中,但是在运行的时候,上面获取元素的代码获得的一直是 null
,这是怎么回事呢?先说解决方法,将 script
标签封装的代码移到 body
结束标签之前,或者将获取元素对象的代码放在一个函数之中,当想获取那个元素的时候去调用该方法,这样就可以解决问题了。那导致问题出现的原因是什么呢?其实是和浏览器加载页面的顺序相关,浏览器是从上往下依次解析网页,当解析到 head
标签之中的 JavaScript
时,此时在该标签之后的网页内容根本就还没有加载进内存当中,现在运行代码,获得的当然是 null
了,移动 script
标签的位置就是针对的这一点,将代码封装在函数中也可以解决问题,因为只有当页面完全加载完了之后我们才会去调用方法,其实实际开发之中封装函数还是用的比较多的,因为封装函数之后,便于复用,写注释之后,也能对这块代码的作用有很好的理解,要比一大块代码简单得多。
3.2 元素对象的常见属性
元素样式相关属性:
如果想要使用 JavaScript
对某元素的显示样式进行修改,应该怎么做?步骤就是:首先获得要修改的元素对象,上面已经给出了四种方式,第二步就是修改元素样式了,在 JavaScript
中修改元素样式也主要是动态地去修改元素的与样式有关的属性,主要由下面三种:
1.元素对象.className = "ys1";
2.元素对象.style.fontSize = “50px”;
3.元素对象.value
第一种是修改元素中 class
属性的属性值,修改为假设已经定义的样式表 ys1
,那这样就可以修改元素的样式了,就是换作用样式表 ys1
中的属性值来修饰被选中的元素;第二种是直接修改元素的具体属性,而 fontSize
属性因为与样式有关,所以也就修改了样式;第三种是修改元素的值,即样式表需要修饰的值。
元素其它相关属性:
这里还有一些常见属性需要说明一下,比如使用 JavaScript
选择单选框中的一个或者复选框之中的多个,首先选中那个想要选择或者取消选择的选项,比如 option
,然后每个选项都会有一个 checked
属性,如果想选中就要将该属性赋值 true
,取消选择的话就赋值为 false
。
还有一个很重要的属性就是 innerHTML
,它代表的是选择标签的内容体,不仅可以赋值一些普通文本,而且还可以是 HTML
中的元素标签,比如在选择的 div
标签之中加一个 font
标签和文本,而且赋值成功后,浏览器还会将它们作为 HTML
标签来解析,那这个作用就十分大了,平常开发中也用的比较多。
4.JavaScript事件
JavaScript
中的事件是十分常见的,比如单击浏览器之中的一个按钮,然后弹出一个带有提示信息的提示框,这就是一个事件啊,当然具体实现功能的时候不会是做这样的效果啊。
4.1 JavaScript事件驱动机制
解释事件驱动机制就是为了来说明一个事件从发生到完成的过程的,主要分为以下几部分:事件源、事件、监听器和绑定监听器。以鼠标单击事件来说明:
1.事件:点击鼠标
2.事件源:Button
3.监听器:function run() {}
4.注册监听器(绑定监听器) onclick="run()"
下面介绍一下 JavaScript
已经定义好的常见事件吧。
单击事件:
绑定点击事件需要添加一个 onclick
属性,并且该属性的属性值应该设置为绑定该元素的函数方法。
onclick="run()"
焦点事件:
焦点事件分为获得得焦点和失去焦点两部分,获得焦点就是当鼠标移动到相关元素上面,而失去焦点则是鼠标离开相关元素。
获得焦点事件绑定:onfocus="run()"
失去焦点事件绑定:onblur="run2()"
域内容改变事件:
域内容改变事件就是当我们选中的元素之中的内容发生改变时,就会触发该元素绑定的函数事件,比如可以是一个文本域,每当这个文本域中的值发生改变时,就会调用相应的方法。
onchange="run()";
加载完毕事件:
之前提到过一个问题,就是由于浏览器解析代码的顺序是由上往下的,因此可能某些代码获取网页之中的对象一直为 null
,其实也可以将上面获取元素对象的代码放在一个函数之中,然后在 body
标签之中加入加载完毕属性 onload
,并将该属性的属性值设置为上面的函数,那这样就可以顺利获得元素对象了,其中的原因就在于 onload
属性的作用就是在页面加载完成之后就去调用它所绑定的函数。
表单提交事件:
表单提交属性是用在表单标签之中的,当用户点击 submit
按钮时,就会触发表单提交属性 onsubmit
中的函数,不过这里有点特殊的地方就是,这里绑定函数的时候不是直接写函数名,而是 return 函数名()
,如下面这样:
<form onsubmit="return run()" />
当调用的绑定函数返回的是 false
时,那么这个表单就会取消提交,如果是 true
,则可以进行提交,这种方式在验证表单输入的时候很有效,有不合法的输入项便取消输入。
键位事件:
下面要说明的两个事件是关于键盘输入的,我们打字时肯定会有键盘按下和键盘抬起这两个事件,在 JavaScript
中这两个事件对应的就是 onkeydown
和 onkeyup
,只要为这两个属性绑定相应的函数,那么当上面的键位事件发生时,就会调用相应的函数。
鼠标事件:
这里还想说明三个关于鼠标的事件,主要是以下这些:
onmousemove:鼠标移动事件
onmouseout:鼠标从某元素之中移开事件
onmouseover:鼠标被移动到某元素之上
4.2 JavaScript事件绑定方式
上面介绍 JavaScript
的事件驱动机制所举的例子,在绑定函数的时候都是使用的 "句柄绑定"
方式,使用句柄绑定有很多优点,第一、传参十分方便,第二、可以绑定多个方法,方法执行的顺序就是绑定时设置的顺序。
<input type="text" onclick="fun1(),fun2('hello'),fun3(this)" />
不过使用句柄绑定方式也有缺点,那就是 JavaScript
和 HTML
代码耦合度太高,不利于开发。
下面便介绍另一种方式:DOM
绑定方式。举个例子说明吧:
window.onload = function(){
var text = document.getElementById("text1");
text.onclick = function(){
alert("我确实被点击了!!!");
}
}
这样就能使 JavaScript
与 HTML
实现分离,便于多人进行开发合作。
JavaScript事件绑定方式
1.句柄绑定
2.DOM绑定
5.总结
感觉这篇文章写的有点多,不过虽然写的很多,却还是有很多重要的部分还没有涉及到,以后肯定也还是要再写别的文章介绍的,这篇文章还只是一个初级的介绍说明,想要熟练地使用 JavaScript
进行开发,还要敲很多代码去运用,以及看很多书去扩大知识面,现在就当把基础打好吧,以后学别的进阶内容也会快一点。