最近有些空闲时间觉得前端框架虽然提高了开发效率,却让人的基础变得薄弱,所以打算再去学习一下原生JS。
第二章 使用JavaScript开发
2.1、编写第一个JavaScript脚本‘
开发工具:MyEclipse
新建web项目命名Chapter2,在WebRoot目录下新建myfirstpage.htm文件,添加如下内容
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>My First Page</title> <script type="text/javascript"> function yetAnotherAlert(textToAlert){ alert(textToAlert); } yetAnotherAlert("This is Chapter2."); </script> </head> <body> </body> </html>
DOCTYPE元素是用来定义文档类型的,注意内容是否正确。在<head>标签中定义了一段js脚本,作用是在加载页面时弹出一个警告框。
修改web.xml,在<welcome-file-list>标签的第一行添加<welcome-file>myfirstpage.htm</welcome-file>,这样在启动项目时默认的加载页面就是myfirstpage.htm。
2.2、使用<script>标签的src属性引入外部js脚本文件
为了便于管理以及重用js脚本,可以将脚本定义在单独的文件中,然后在使用时通过<script>标签的src属性引入外部js脚本文件。定义WebRoot/webresources/js目录,然后在其中新建一个myscript.js文件。文件内容为:function yetAnotherAlert(textToAlert){ alert(textToAlert); } yetAnotherAlert("This is Second Example.");
然后修改myfirstpage.htm文件中的<script>标签的内容如下:
<script type="text/javascript" src="webresources/js/myscript.js"></script>
其中的src属性的值就是定义的myscript.js文件的文件路径,项目的根目录是WebRoot及Chapter2,所以这里的路径就相当于http://localhost:8080/Chapter2/webresources/js/myscript.js,注意这里使用的是相对路径,如果是“/”开始,就不能定义为"/webresources/js/myscript.js",因为斜杠开头的路径是绝对路径,需要定义为src=” /Chapter2/webresources/js/myscript.js”才能正确解析。
注:如果是用记事本编写html文件,那么在保存时记事本可能会默认为文档添加一个.txt的扩展名,这时可以用引号把文件名引用起来—例如,”myfirstpage.htm”。如果不加引号,记事本会添加.txt扩展名将文件保存为”myfirstpage.htm.txt”。
第三章 JavaScript的语法和语句
3.1语法特点
1、区分大小写
2、忽略空白,JavaScript会忽略增加可读性的空格、缩进。这里有一些列外是一些关键字(比如return)被单独放在一行时,会被JavaScript解释器误解。
3、注释,分为单行注释(以两个正斜线开始没有结束标记,因为它只占一行)和多行注释(以”/*”开始,以”*/”结束,可以包含多行)。
4、分号,在JavaScript里,分号用来描述表达式。对于大多数语句和表达式,分号都不是必须的,然而,不使用分号可能会遇到一些莫名其妙的问题。比如,考虑下面的语句:
return
(varName);
很可能你想输入的是:
return(varName);
但JavaScript根据自己的理解,在return语句后插入了一个分号。对于JavaScript解释器,这段代码看起来就像这样:
return;
(varName);
这段代码将不会执行,在函数中它将返回undefined给调用者。因此在应该使用分号的地方最好不要省略。
5、正确放置JavaScript
JavaScript可以被放置在HTML页面中的几个位置:在<head>和</head>部分,或在<body>和</body>标签之间。不过,将<script>段放在<body>部分变得越来越常见。在声明为可扩展超文本标记语言(XHTML)的页面中使用JavaScript时,<script>标签必须在CDATA部分中声明。否则XHTML会将<script>标签解析为另一个XML标签,因此,在严格XHTML中使用的JavaScript应该做如下声明:<script type=”text/javascript”> <!CDATA[ //JavaScript goes here ]]> </script>
较早的浏览器可能不能正确解析CDATA部分。这个问题可以通过将CDATA的开始和结束放在JavaScript的注释内解决,就像下面这样:
<script type=”text/javascript”> //<!CDATA[ //JavaScript goes here //]]> </script>
如果把实际的JavaScript代码放在一个独立的文件中,那么根本不需要使用这个难看的CDATA部分。
将JavaScript放置到外部文件具有下面几个优点:
1、代码从标记分离:将JavaScript代码 保存在一个单独的文件中使得HTML的维护变得更加容易,并且它还保留了HTML结构,不必在XHTML中使用CDATA部分。
2、更容易的维护:把JavaScript作为一个单独的文件,这样修改该文件时就不会触及网站的其他文件。
3、缓存:为JavaScript使用独立文件允许web浏览器缓存该文件,这样可以为用户加快网页的加载。
3.2JavaScript语句
3.2.1语句的结构包括简单语句和复合语句
简单语句如下:x = 4;
复合语句包含多层逻辑,比如下面的if/then/else判断语句:if(something==1){ //some code here } else{ //some other code here }
3.3JavaScript的保留字
JavaScript中的保留字在程序中不能用作变量、标示符或者常量名,比如:
//Don’t do this;
var var = 4;
该代码不会对浏览器造成直接错误,但它也不会按照你的意图执行。
目前ECMA-262规范中的保留字如下:
break delete if this while case do in throw with catch else instanceof try continue finally new typeof debugger for return var default function switch void
下面这些是为将来的使用保留的,因此也不可以用于程序中:
class enum extends super const export import
下面列出的单词是为将来在严格模式下使用而保留的:
implements let private public yeild interface package protected static
3.4函数简介
在用户自定义函数中使用JavaScript
创建名为example.htm文件,页面内容如下:<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.1 //EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>A Chapter 3 Example</title> <script type="text/javascript"> function cubeme(incomingNum){ if(incomingNum==1){ return "what are you doing?"; }else{ return Math.pow(incomingNum, 3); } } </script> </head> <body> <script type="text/javascript"> var theNum = 2; var finalNum = cubeme(theNum); if(isNaN(finalNum)){ alert("You should know that 1 to any power is 1."); }else{ alert("When cubed, "+theNum+" is "+finalNum); } </script> </body> </html>
以上是一个简单的创建自定义函数及调用函数的过程。
3.5JavaScript的新增严格模式
ECMA-262version5引入了一个严格体,一般也叫做严格模式(strict mode),它增加了增强的错误检查和安全。例如,为了帮助抵制输入错误的变量名,变量声明需要使用var关键字。另外,对eval()函数以及其他地方的改变也有助于程序员改善他们的代码。严格模式使用如下代码打开:
“use strict”;
严格模式是局部范围的,也就是说,如果把usestrict行放在脚本的开始处,那么严格模式可以在全局打开;否则把该行放在函数体内部,则严格模式仅在函数内部打开,就像下面这样:function doSomething(){ “use strict”; //function’s code goes here; }
严格模式下所有的变量在使用前必须被实例化。例如,考虑如下代码:
“use strict”; x=4; // Produces a syntax error
这段代码会出现错误,因为变量x还没有被var关键字声明,正确代码如下:
“use strict”; var x=4;//This syntax is ok
严格模式提供的显著安全性增强是对eval()函数处理的改变。在严格模式下,eval()不能实例化一个eval()语句外使用的新的变量或函数。例如:
“use strict”; eval(“var testVar=2;”); alert(testVar);//Produces a syntax error
在这段代码实例中,会发生一个语法错误,因为严格模式被打开,并且testVar变量在eval()语句外是不可用的。
严格模式还预防了对象内或者函数内变量名的重复:
“use strict”; var myObject={ testVar: 1; testVar: 2; }
前面的代码在严格模式下会产生一个语法错误,因为testVar在对象定义中被设置了两次。
严格模式不可能在所有浏览器中可用,并且很可能在旧浏览器中不可用。
第四章 使用变量和数据类型
4.1JavaScript中的数据类型
这里介绍JavaScript中使用的6种数据类型,如下所示:
数字(Number)
字符串(String)
布尔值(Boolean)
Null
未定义(Undefined)
对象(Object)
4.1.1、数字
整数和浮点数都没有专门的或者单独的类型。在JavaScript中,这些都是完全有效的数字:
4
51.50
-14
0xd
最后一个示例0xd是一个十六进制数。十六进制和八进制在JavaScript中都是有效的。
用JavaScript执行十六进制运算
创建一个example.htm文件,内容如下:<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.1 //EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>Hexadecimal Numbers</title> <script type="text/javascript"> var h=0xe; var i=0x2; var j=h*i; alert(j); </script> </head> <body> </body> </html>
在浏览器中查看网页,将得到如下图所示的对话框:
从结果可以看到,即使把两个十六进制数相乘得到的也是基于十进制格式的。
4.1.1.1JavaScript中有一些和数值一起使用的内建函数(还有对象),比如isNaN()函数。
NaN是Not a Number的缩写,代表一个非数字。可以使用isNaN()函数判断一个数字针对ECMA-262规范是否合法和有效。例如一个数字被0除将得到一个非法数字,字符串值”Thisis not a number”很明显也不是一个数字。
测试isNaN()函数:
打开浏览器,在地址栏中输入如下代码:
javascript:alert(isNaN(“4”));
将收到一个带有单词”false”的警告框,函数isNaN()从这个表达式返回false,是因为整数4是一个数字。
继续在浏览器地址栏中输入如下代码:
javascript:alert(isNaN(“four”));
函数返回”true”,因为four不是一个数字,在每个代码示例中都使用了双引号(即”4”和”four”),从而证明引号对函数不会有什么影响。因为JavaScript能够识别出来”4”是一个数字,JavaScript为我们完成了类型转换。
验证输入以便确定某变量(可能是一个表单变量)是被作为数字还是文本输入时,会经常使用jsNaN()函数。
JavaScript中还包含一些数值常量:
Infinity:表示正无穷大
Number.MAX_VALUE:JavaScript中可表示的最大数
Number.MIN_VALUE:JavaScript中可表示的最小数
Number.NEGATIVE_INFINITY:一个表示负无穷大的值
Number.POSITIVE_INFINITY:一个表示正无穷大的值
4.1.1.2Math对象
Math对象有几个非常有用的属性:
Math.PI
Math.random():返回一个伪随机数
Math.abs(x):返回x的绝对值
Math.pow(x,y):返回x的y次幂
Math.round():将x取值为最接近的整数
4.1.2字符串的用法
字符串是由引号引起来的一个或多个字符组成。如下所示:
“Hello World”
“B”
“This is ‘anotherstring’”
字符串要么被单引号引起来要么被双引号引起来,单引号引起来的字符串可以包含双引号,双引号引起来的字符串也可以包含单引号。如下所示:
‘The cow says “mo”’
“’Everyone had agood time’ was the official slogan.”
4.1.2.1转义引号
如果字符串内使用的引号和用来包围字符串的引号是同一种引号,那么引号必须被转义,使其能被JavaScript引擎忽略。用一个反斜杠字符来转义引号,示例如下:
“This is a \”great\”example of using \”double quotes\” within a string that’s enclosed with \”doublequotes\” too.”
4.1.2.2其他转义字符
\b:退格
\t:水平制表符
\n:换行符
\v:垂直制表符
\f:换页
\r:回车
4.1.2.3字符串方法和属性
字符串的length属性指出字符串的长度,示例代码如下:alert(“This is a string.”.length); var x = “This is a string.”; alert(x.length);
在浏览器地址栏中 输入javascript:var x = “This is a string.”; alert(x.length);
substring方法返回从第一个参数到第二个参数(但不包括第二个参数)之间的字符,如下所示:
alert(x.substring(0,3));
修改字符串的方法包括:slice、sbustring、substr和concat。slice和substring方法返回基于另外一个字符串的字符串。它们接受两个参数:开始位置和可选的结束位置。如下所示:var myString = “This is a string.”; alert(myString.substring(3)); //Returns “s is a string.” alert(myString.substring(3,9)); // Returns “s is a” alert(myString.slice(3)); //Returns “s is a string.” alert(myString.slice(3,9)); //Returns “s is a”
substr函数也接受两个参数:第一个是返回字符串的开始位置,与substring/slice不同的是,第二个参数是返回字符的个数,而不是结束的位置。因此,包含substring/slice的代码示例结果与substr的稍有不同:
var myString = “This is a string.”; alert(myString.substr(3)); //Returns “s is a string.” alert(myString.substr(3,9)); // Returns “s is a st”
concat函数将两个字符串连接到一起:
var firstString = “Hello ”; var finalString = firstString.concat(“World”); alert(finalString);
toUpperCase和toLowerCase方法及其兄弟方法toLocaleUpperCase和toLocaleLowerCase分别将字符串转换为全部大写或者全部小写:
var myString = “this is a string”; alert(myString.toUpperCase()); //”THIS IS A STRING” alert(myString.toLowerCase()); //”this is a string”
toLocale方法以语言环境特定模式执行转换
4.1.3布尔值
布尔值一般用于像if/then/else语句这样的测试中。
4.1.4null
null就是没有,它表示并且等于false。当一个值是null,就表明它没有值,也不包含任何值。它和空是不同的,一个空值或者变量仍然充满了空,null是彻底没有。例如定义一个变量并将其设置为空字符串:
var myVariable =‘’;
变量myVariable是空的,但它不是null。
4.1.5未定义
未定义是一种状态,有时会像使用值一样使用它,表示一个还没有包含值的变量。这个状态和null不同,尽管null和未定义都可以用同样的方法求值。
4.1.6对象
JavaScript中的对象是很多属性的集合,每个属性都有一个原始值。这些属性可视为键,使我们能够访问到值。保存在属性中的值可以是一个值、另一个对象,或者甚至可以是一个函数。
对象使用花括号创建,下面代码创建了一个名为myObject的空对象:var myObject={};
这里有一个带有几个属性的对象:
var dvdCatalog = { “identifier”: “1”, “name”: “Coho Vineyard” }
访问对象中的属性:alert(dvdCatalog. identifier);
下面是一个更完整的示例:
//Create a new object with curly braces var star={}; //Create named objects for each of four stars star[“Polaris”]=new Object; star[“Deneb”]=new Object; star[“Vega”]=new Object; star[“Altair”]=new Object;
4.1.7数组
var star = new Array(); star[0]= “Polaris”; star[1]= “Deneb”; star[2]= “Vega”; star[3]= “Altair”;
也可以写成下面这样:
var star=[ “Polaris”, “Deneb”, “Vega”, “Altair”];
数组也可以包含嵌套的值,如下所示:
var star=[ [“Polaris”,”Ursa Minor”], [“Deneb”,”Cygnus”], [“Vega”,”Lyra”],[ “Altair”,”Aquila”]];
最后,尽管不常用,但也可以调用带参数的Array()构造函数:
var star=new Array(“Polaris”, “Deneb”, “Vega”, “Altair”);
4.2定义和使用变量
4.2.1声明变量
在JavaScript中使用var声明变量:
var x; var myVar; var counter1;
如下变量名是无效的:
var 1stCounter; //以数字开头 var new variable; //包含关键字和空格 var new.variable; //包含关键字和非下划线的特殊字符 var var;
如下是同一行代码声明多个变量,以及初始化这些变量:
var x,y,z; var x=1,y=”Hello”,z=14;
4.2.2变量类型
JavaScript是弱类型的,不需要预先指定变量的类型
4.2.3变量作用域
当变量在函数之外使用时它是全局作用的,函数内定义的变量的作用域被限制在那个函数内。函数的参数也被限制在函数内。如下代码所示:
<script type="text/javascript"> var h=0xe; var i=0x2; var j=h*i; alert(j); </script> <script type="text/javascript"> var aNewVariable = "I'm Global."; function doSonething(incomingBits){ alert(aNewVariable); alert(incomingBits); } doSonething("A argument"); </script
这段代码定义了一个名为aNewVariable的全局变量和一个名为incomingBits的变量,后者是doSonething()函数的局部变量。
下面是一个更复杂的示例:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.1 //EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>Scoping Example</title> <script type="text/javascript"> var aNewVariable = "is a Global."; function doSomething(incomingBits){ alert("Global variable within the function:"+aNewVariable); alert("Local variable within the function:"+incomingBits); } </script> </head> <body> <script type="text/javascript"> doSonething("is a local variable"); alert("Global var outside the function:"+aNewVariable); alert("Local var outside the function:"+incomingBits); </script> </body> </html>
结果在屏幕上显示三个警告框。
第一个警告框如下:
第二个警告框如下:
第三个警告框如下:
实际代码中定义了四个alert()语句,却只弹出来三个警告框,在打开页面之前,点击F12出现开发者工具,IE中有一个控制台按钮,可以看到输出的错误信息,其他浏览器类似,输入信息如下:
上图已经指错误是incomingBits未定义,是因为它是局部变量,而我们在作用域外部引用导致未定义。
4.2.4Date对象
对于JavaScript中的Date对象,其方法的执行随浏览器和操作系统的不同变化很大。例如下面的代码返回当前时间的日期,这里的时间被调整为当地时区并且被toLocaleDateString()方法自动格式化:var myDate=new Date(); alert(myDate.toLocaleDateString());
在IE中显示的日期格式如下:
而在Chrome浏览器中显示的日期格式如下:
并且Date对象的getYear()方法的返回结果根据不同的浏览器也会返回不同的结果。
var myDate=new Date(); alert(myDate.getYear());
在低版本IE中返回的结果是2018(当前年),而在高版本的IE或者Chrome中返回的是118,是当前年减去1900得到的结果。如果我们想要得到整个年份可以使用getFullYear()方法
注:无论何时使用Date对象中的任何方法,它们反映的都是访问者计算机上的时间,所以获取的时间可能不是准确时间(如果访问者有意修改本机时间的话)。
Date对象可以附带0~7个参数。如果传递给Date对象构造函数的是一个字符串参数,那么字符串应包含日期。如果传递给它的是一个数字类型的参数,那么参数应该是自1970年1月1日起按毫秒数计算的日期。如果传递给它的是7个参数,那么它应该是下面的样子:
new Date(year,month,day,hours,minutes,seconds,milliseconds);
注意:只有年和月是必需参数,其他都是可选参数。
使用Date对象时,请记住下面的几点:
1、年应该以四位数字提供,除非想指定1900年到2000年之间的年,这种情况只需提供两位数的年,0到99,随后它们被加上1900,所有2008等于2008年,但是98就变成了1998年了。如var myDate=new Date(1998,0);和var myDate=newDate(98,0);获得的都是1998年,如果只传一个年份的参数,那么无论传的哪一年获取的都是1970年。
2、月由0到11之间的整数表示,0是1月,11是12月。
3、日是一个1到31之间的整数。
4、小时由0到23间的整数表示,23表示晚上11点。
5、分和秒都是0到59间的整数。
6、毫秒是0到999间的整数。
将日期和时间写入网页
页面中的内容如下所示:<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.1 //EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>the date</title> </head> <body> <p id="dateField"> </p> <script type="text/javascript"> var mydate=new Date(); var dateString=mydate.toLocaleDateString()+" "+mydate.toLocaleTimeString(); var dateLoc=document.getElementById("dateField"); dateLoc.innerHTML ="Hello - Page Randered on "+dateString; </script> </body> </html>
页面显示如下:
不同浏览器显示的时间格式会稍有不同。
倒计时到将来某一时间
页面代码如下:<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.1 //EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>the date</title> </head> <body> <p id="dateField"> </p> <script type="text/javascript"> var now=new Date(); var then=new Date(); then.setFullYear(2019, 0, 1); var diff=then.getTime()-now.getTime(); diff=Math.floor(diff/(1000*60*60*24)); var dateLoc=document.getElementById("dateField"); dateLoc.innerHTML ="There are "+diff+" day until 1/1/2019"; </script> </body> </html>
页面显示结果如下:
计算渲染时间
下面是粗略计算将网页载入个人浏览器所花费的时间。页面代码如下:<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.1 //EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>the date</title> <script type="text/javascript"> var started=new Date(); var now =started.getTime(); </script> </head> <body> <p id="dateField"> </p> <script type="text/javascript"> var bottom=new Date(); var diff=(bottom.getTime()-now)/1000; var finalTime=diff.toPrecision(5); var dateLoc=document.getElementById("dateField"); dateLoc.innerHTML ="Page rendered in "+finalTime+" seconds"; </script> </body> </html>
这样看不出来有多少加载时间,可以通过加入延迟来方便测试,比如for循环。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.1 //EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>the date</title> <script type="text/javascript"> var started=new Date(); var now =started.getTime(); for(var i=0;i<1000000;i++){ //delay } </script> </head> <body> <p id="dateField"> </p> <script type="text/javascript"> var bottom=new Date(); var diff=(bottom.getTime()-now)/1000; var finalTime=diff.toPrecision(5); var dateLoc=document.getElementById("dateField"); dateLoc.innerHTML ="Page rendered in "+finalTime+" seconds"; </script> </body> </html>
页面显示如下:
Date对象的get方法
1、getDate():返回月中的某天
2、getDay():返回星期中的某天
3、getFullYear():返回四位数年份表示
4、getHours(0:返回日期中的小时
5、getMilliseconds():返回日期中的毫秒
6、getMinutes():返回日期中的分钟
7、getMonth():返回日期中的月
8、getSeconds():返回日期中的秒
9、getTime():返回自1970年1月1日起的毫秒
10、getTimezoneOffset():返回UTC和本地时间之间差值所对应的分钟数
很多get…()方法都有以set为前缀的兄弟方法。
Date对象还有几个能将日期转换成不同格式字符串的方法:javascript:var myDate=new Date();alert(myDate.toLocaleDateString()); javascript:var myDate=new Date();alert(myDate.toLocaleString()); javascript:var myDate=new Date();alert(myDate.toGMTString()); javascript:var myDate=new Date();alert(myDate.toLocaleTimeString()); javascript:var myDate=new Date();alert(myDate.toString()); javascript:var myDate=new Date();alert(myDate.toISOString()); javascript:var myDate=new Date();alert(myDate.toDateString()); javascript:var myDate=new Date();alert(myDate.toUTCString()); javascript:var myDate=new Date();alert(myDate.toTimeString());
4.3使用RegExp对象
偷个懒,实在不想在把每个章节的内容贴进来了,直接将文档和代码上传了。。。