本数据类型
JavaScript脚本语言同其它语言一样,有它自身的基本数据类型、表达式和算术运算符以及程序的基本框架结构。
JavaScript提供了四种基本的数据类型用来处理数字和文字, 而变量提供存放信息的地方, 表达式则可以完成较复杂的
信息处理。
1、基本数据类型
在JavaScript中四种基本的数据类型:数值(整数和实数)、字符串型(用“”号或‘’括起来的字符或数值)、
布尔型(使True或False表示)和空值。在JavaScript的基本类型中的数据可以是常量,也可以变量。由于JavaScript
采用弱类型的形式,因而一个数据的变量或常量不必首先作声明,而是在使用或赋值时确定其数据的类型的。当然也可
以先声明该数据的类型,它是通过在赋值时自动说明其数据类型的。
2、常量
整型常量
JavaScript的常量通常又称字面常量,它是不能改变的数据。其整型常量可以使用十六进制、八进制和十进制表示
其值。
实型常量
实型常量是由整数部分加小数部分表示,如12.32、193.98 。可以使用科学或标准方法表示:5E7、4e5等。
布尔值
布尔常量只有两种状态:True或False。 它主要用来说明或代表一种状态或标志,以说明操作流程。它与C++是
不一样的,C++可以用1或0表示其状态,而JavaScript只能用True或False表示其状态。
字符型常量
使用单引号(‘)或双引号(“)括起来的一个或几个字符。如 "This is a book of JavaScript
"、"3245"、"ewrt234234" 等。
空值
JavaScript中有一个空值null,表示什么也没有。如试图引用没有定义的变量,则返回一个Null值。
特殊字符
同C语言一样,JavaScript中同样以有些以反斜杠(/)开头的不可显示的特殊字符。通常称为控制字符。
3、变量
变量的主要作用是存取数据、提供存放信息的容器。对于变量必须明确变量的命名、变量的类型、变量的声明及其
变量的作用域。
变量的命名
JavaScript中的变量命名同其计算机语言非常相似,这里要注意以下两点:
必须是一个有效的变量,即变量以字母开头,中间可以出现数字如test1、text2等。除下划线(-)作为连字符外,变
量名称不能有空格、(+)、(-)、(,)或其它符号。
不能使用JavaScript中的关键字作为变量。
在JavaScript中定义了40多个类键字,这些关键是JavaScript内部使用的,不能作为变量的名称。如Var、int、
double、true不能作为变量的名称。
在对变量命名时,最好把变量的意义与其代表的意思对应起来,以免出现错误。
变量的类型
在JavaScript中,变量可以用命令Var作声明:
var mytest;
该例子定义了一个mytest变量。但没有赋予它的值。
Var mytest=”This is a book”
该例子定义了一个mytest变量, 同时赋予了它的值。
在JavaScript中,变量以可以不作声明,而在使用时再根据数据的类型来确其变量的类型。
如:
x=100
y="125"
xy=True
cost=19.5等。
其中x整数,y为字符串,xy为布尔型,cost为实型。
变量的声明及其作用域
JavaScript变量可以在使用前先作声明,并可赋值。通过使用var关键字对变量作声明。对变量作声明的最大好处
就是能及时发现代码中的错误;因为JavaScript是采用动态编译的,而动态编译是不易发现代码中的错误,特别是变量
命名的方面。
对于变量还有一个重要性──那就是变量的作用域。在JavaScript中同样有全局变量和局部变量。全局变量是定义
在所有函数体之外,其作用范围是整个函数;而局部变量是定义在函数体之内,只对其该函数是可见的,而对其它函数
则是不可见的。
三、表达式和运算符
1、表达式
在定义完变量后,就可以对它们进行赋值、改变、计算等一系列操作,这一过程通常又叫称一个叫表达式来完成,
可以说它是变量、常量、布尔及运算符的集合,因此表达式可以分为算术表述式、字串表达式、赋值表达式以及布尔表
达式等。
2、运算符
运算符完成操作的一系列符号,在JavaScript中有算术运算符,如+、-、*、/等;有比较运算符如!=、==等;
有逻辑布尔运算符如!(取反)、|、||; 有字串运算如+ 、 +=等。
在JavaScript主要有双目运算符和单目运算符。其双目运算符由下列组成:
操作数1 运算符 操作数2
即由两个操作数和一个运算符组成。如50+40、"This"+"that"等。单目运算符,只需一个操作数,其运算符可在
前或后。
(1)算术运算符
JavaScript中的算术运算符有单目运算符和双目运算符。
双目运算符:
+(加) 、-(减)、 *(乘)、 /(除)、 %(取模) 、|(按位或)、&(按位与)、<<(左移)、 >>(右移)、
>>>(右移,零填充)。
单目运算符:
-(取反)、~(取补)、++(递加1)、--(递减1)。
(2)比较运算符
比较运算符它的基本操作过程是,首先对它的操作数进行比较,尔后再返回一个true或False值,有8个比较运算符
:
<(小于)、>(大于)、<=(小于等于)、>=(大于等于)、==(等于)、!=(不等于)。
(3)布尔逻辑运算符
在JavaScript中增加了几个布尔逻辑运算符:
!(取反)、&=(与之后赋值)、 &(逻辑与)、 |=(或之后赋值)、 |(逻辑或)、 ^=(异或之后赋值)、 ^(逻辑
异或)、 ?:(三目操作符)、||(或)、==(等于)、|=(不等于)。
其中三目操作符主要格式如下:
操作数?结果1:结果2
若操作数的结果为真,则表述式的结果为结果1,否则为结果2。
四、范例
下面是一个跑马灯效果的JavaScript文档。
<html><head><script Language="JavaScript">
var msg="这是一个跑马灯效果的JavaScript文档";
var interval=100;
var spacelen=120;
var space10=" ";
var seq=0;
function Scroll() {
len=msg.length;
window.status=msg.substring(0, seq+1);
seq++;
if ( seq >=len ) {
seq=spacelen;
window.setTimeout("Scroll2();", interval );}
else
window.setTimeout("Scroll();", interval );}
function Scroll2() {
var out="";
for (i=1; i<=spacelen/space10.length; i++) out +=
space10;
out=out + msg;
len=out.length;
window.status=out.substring(seq, len);
seq++;
if ( seq >=len ) { seq=0; };
window.setTimeout("Scroll2();", interval );}
Scroll();
</script><body></body></html>
本讲介绍了JavaScript脚本是如何加入Web页面, 并学习了JavaScript语言中的基本数据类型、变量、常量、操作
运算符等。从本讲中的内容中可以看出,对于已经掌握C++语言的人来说,学习JavaScript真是一件非常轻松愉快的
事。
第三讲 JavaScript程序构成
JavaScript脚本语言的基本构成是由控制语句、函数、对象、方法、属性等,来实现编程的。
一、程序控制流
在任何一种语言中,程序控制流是必须的,它能使得整个程序减小混乱,使之顺利按其一定的方式执行。下面是
JavaScript常用的程序控制流结构及语句:
1、if条件语句
基本格式
if(表述式)
语句段1;
......
else
语句段2;
.....
功能:若表达式为true,则执行语句段1;否则执行语句段2。
说明:
if -else 语句是JavaScript中最基本的控制语句,通过它可以改变语句的执行顺序。
表达式中必须使用关系语句,来实现判断,它是作为一个布尔值来估算的。
它将零和非零的数分别转化成false和true。 若if后的语句有多行,则必须使用花括号将其括起来。
if语句的嵌套:
if(布尔值)语句1;
else(布尔值)语句2;
else if(布尔值)语句3;
……
else 语句4;
在这种情况下,每一级的布尔表述式都会被计算,若为真,则执行其相应的语句,否则执行else后的语句。
2、For循环语句
基本格式
for(初始化;条件;增量)
语句集;
功能:实现条件循环,当条件成立时,执行语句集,否则跳出循环体。
说明:
初始化参数告诉循环的开始位置,必须赋予变量的初值;
条件:是用于判别循环停止时的条件。若条件满足,则执行循环体,否则 跳出。
增量:主要定义循环控制变量在每次循环时按什么方式变化。
三个主要语句之间,必须使用逗号分隔。
3、while循环
基本格式
while(条件)
语句集;
该语句与For语句一样,当条件为真时,重复循环,否则退出循环。
For与while语句都是循环语句,使用For语句在处理有关数字时更易看懂,也较紧凑;而while循环对复杂的语句效
果更特别。
4、break和continue语句
与C++语言相同,使用break语句使得循环从For或while中跳出,continue使得跳过循环内剩余的语句而进入下一次
循环。
二、函数
函数为程序设计人员提供了一个丰常方便的能力。通常在进行一个复杂的程序设计时,总是根据所要完成的功能,
将程序划分为一些相对独立的部分,每部分编写一个函数。从而,使各部分充分独立,任务单一,程序清晰,易懂、易
读、易维护。JavaScript函数可以封装那些在程序中可能要多次用到的模块。并可作为事件驱动的结果而调用的程序。
从而实现一个函数把它与事件驱动相关联。这是与其它语言不样的地方。
1、JavaScript函数定义
Function 函数名 (参数,变元){
函数体;.
Return 表达式;
}
说明:
当调用函数时,所用变量或字面量均可作为变元传递。
函数由关键字Function定义。
函数名:定义自己函数的名字。
参数表,是传递给函数使用或操作的值,其值可以是常量 ,变量或其它表达式。
通过指定函数名(实参)来调用一个函数。
必须使用Return将值返回。
函数名对大小写是敏感的。
2、函数中的形式参数:
在函数的定义中,我们看到函数名后有参数表,这些参数变量可能是一个或几个。那么怎样才能确定参数变量的个
数呢?在JavaScript中可通过arguments .Length来检查参数的个数。
例:
Function function_Name(exp1,exp2,exp3,exp4)
Number=function _Name . arguments .length;
if (Number>1)
document.wrile(exp2);
if (Number>2)
document.write(exp3);
if(Number>3)
document.write(exp4);
...
三、事件驱动及事件处理
1、基本概念
JavaScript是基于对象(object-based)的语言。这与Java不同,Java是面向对象的语言。而基于对象的基本特征,
就是采用事件驱动(event-driven)。它是在用形界面的环境下,使得一切输入变化简单化。通常鼠标或热键的动作我们
称之为事件(Event),而由鼠标或热键引发的一连串程序的动作,称之为事件驱动(Event Driver)。而对事件进行
处理程序或函数,我们称之为事件处理程序(Event Handler)。
2、事件处理程序
在JavaScript中对象事件的处理通常由函数(Function)担任。其基本格式与函数全部一样,可以将前面所介绍的所
有函数作为事件处理程序。格式如下:
Function 事件处理名(参数表){
事件处理语句集;
……
}
3、事件驱动
JavaScript事件驱动中的事件是通过鼠标或热键的动作引发的。它主要有以下几个事件:
(1)单击事件onClick
当用户单击鼠标按钮时,产生onClick事件。同时onClick指定的事件处理程序或代码将被调用执行。通常在下列基
本对象中产生:
button(按钮对象)
checkbox(复选框)或(检查列表框)
radio (单选钮)
reset buttons(重要按钮)
submit buttons(提交按钮)
例:可通过下列按钮激活change()文件:
<Form>
<Input type="button" Value=“ ” onClick="change()">
</Form>
在onClick等号后,可以使用自己编写的函数作为事件处理程序,也可以使用JavaScript中内部的函数。还可以直
接使用JavaScript的代码等。例:
<Input type="button" value=" " onclick=alert("这是一个例子");
(2)onChange改变事件
当利用text或texturea元素输入字符值改变时发该事件,同时当在select表格项中一个选项状态改变后也会引发该
事件。
例: <Form>
<Input type="text" name="Test" value="Test" onCharge="check('this.test)">
</Form>
(3)选中事件onSelect
当Text或Textarea对象中的文字被加亮后,引发该事件。
(4)获得焦点事件onFocus
当用户单击Text或textarea以及select对象时,产生该事件。此时该对象成为前台对象。
(5)失去焦点onBlur
当text对象或textarea对象以及select对象不再拥有焦点、而退到后台时,引发该文件,他与onFocas事件是一个
对应的关系。
(6)载入文件onLoad
当文档载入时,产生该事件。onLoad一个作用就是在首次载入一个文档时检测cookie的值,并用一个变量为其赋值
,使它可以被源代码使用。
(7)卸载文件onUnload
当Web页面退出时引发onUnload事件,并可更新Cookie的状态。
四、范例
范例1:下例程序是一个自动装载和自动卸载的例子。即当装入HTML文档时调用loadform()函数,而退出该文档进入
另一HTML文档时则首先调用unloadform()函数,确认后方可进入。
<HTML>
<HEAD>
<script Language="JavaScript">
<!--
function loadform(){
alert("这是一个自动装载例子!");
}
function unloadform(){
alert("这是一个卸载例子!");
}
//-->
</Script>
</HEAD>
<BODY OnLoad="loadform()" OnUnload="unloadform()">
<a href="test.htm">调用</a>
</BODY>
</HTML>
范例2:这是一个获取浏览器版本号的程序。该程序首先显示一个波浪一提示信息。之后显示浏览器的版本号有关信
息。
<html>
<head>
<script language="JavaScript"><!--
// -->
function makeArray(n){
this.length=n
return this
}
function hexfromdec(num) {
hex=new makeArray(1);
var hexstring="";
var shifthex=16;
var temp1=num;
for(x=1; x>=0; x--) {
hex[x]=Math.round(temp1/shifthex - .5);
hex[x-1]=temp1 - hex[x] * shifthex;
temp1=hex[x-1];
shifthex /=16;
}
for (x=1; x>=0; x--) { hexstring+=getletter(hex[x]); }
return (hexstring);
}
function getletter(num) {
if (num < 10) { return num; }
else {
if (num==10) { return "A" }
if (num==11) { return "B" }
if (num==12) { return "C" }
if (num==13) { return "D" }
if (num==14) { return "E" }
if (num==15) { return "F" }
}
}
function rainbow(text){
var color_d1;
var allstring="";
for(i=0;i<text.length;i=i+2){
color_d1=255*Math.sin(i/(text.length/3));
color_h1=hexfromdec(color_d1);
allstring+="<FONT COLOR="+color_h1+"ff"+color_h1+">"+text.substring(i,i+2)+"</FONT>";
}
return allstring;
}
function sizefont(text){
var color_d1;
var allstring="";
var flag=0;
for(i=0,j=0;i<text.length;i=i+1){
if (flag==0) {
j++;
if (j>=7) {
flag=1;}}
if (flag==1) {
j=j-1;
if (j<=0) {
flag=0; }}
allstring+="<FONT SIZE="+ j + ">" + text.substring(i,i+1) + "</FONT>";
}
return allstring;
}
document.write("<font size=8><CENTER>")
document.write("<BR><BR>")
document.write( sizefont("这是一个获取WEB浏览器的程序"))
document.write("</CENTER></font>")
document.write("浏览器名称: "+navigator.appName+"<br>");
document.write("版本号: "+navigator.appVersion+"<br>");
document.write("代码名字: "+navigator.appCodeName+"<br>");
document.write("用户代理标识: "+navigator.userAgent);
</script>
<body></body></html>
本讲介绍了JavaScript程序设计的有关内容。程序流、函数、事件是我们学习掌握JavaScript编程的重点。
第四讲 基于对象的JavaScript语言
JavaScript语言是基于对象的(Object-Based),而不是面向对象的(object-oriented)。之所以说它是一门基
于对象的语言,主要是因为它没有提供象抽象、继承、重载等有关面向对象语言的许多功能。而是把其它语言所创建的
复杂对象统一起来,从而形成一个非常强大的对象系统。
虽然JavaScript语言是一门基于对象的,但它还是具有一些面向对象的基本特征。它可以根据需要创建自己的对象
,从而进一步扩大JavaScript的应用范围,增强编写功能强大的Web文档。
一、对象的基础知识
1、对象的基本结构
JavaScript中的对象是由属性(properties)和方法(methods)两个基本的元素的构成的。前者是对象在实施其所需
要行为的过程中,实现信息的装载单位,从而与变量相关联;后者是指对象能够按照设计者的意图而被执行,从而与特
定的函数相联。
2、引用对象的途径
一个对象要真正地被使用,可采用以下几种方式获得:
引用JavaScript内部对象;
由浏览器环境中提供;
创建新对象。
这就是说一个对象在被引用之前,这个对象必须存在,否则引用将毫无意义,而出现错误信息。从上面中我们可以
看出JavaScript引用对象可通过三种方式获取。要么创建新的对象,要么利用现存的对象。
3、有关对象操作语句
JavaScript不是一纯面向对象的语言,它设有提供面向对象语言的许多功能,因此JavaScript设计者之所以把它你
“基于对象”而不是面向对象的语言,在JavaScript中提供了几个用于操作对象的语句和关键字及运算符。
1)、For...in语句
格式如下:
For(对象属性名 in 已知对象名)
说明:
该语句的功能是用于对已知对象的所有属性进行操作的控制循环。它是将一个已知对象的所有属性反复置给一个变
量;而不是使用计数器来实现的。
该语句的优点就是无需知道对象中属性的个数即可进行操作。
例:下列函数是显示数组中的内容:
Function showData(object)
for (var X=0; X<30;X++)
document.write(object[i]);
该函数是通过数组下标顺序值,来访问每个对象的属性,使用这种方式首先必须知道数组的下标值,否则若超出范
围,则就会发生错误。而使For...in语句,则根本不需要知道对象属性的个数,见下:
Function showData(object)
for(var prop in object)
document.write(object[prop]);
使用该函数时,在循环体中,For自动将的属性取出来,直到最后为此。
.with语句
使用该语句的意思是:在该语句体内,任何对变量的引用被认为是这个对象的属性,以节省一些代码。
with object{
...}
所有在with语句后的花括号中的语句,都是在后面object对象的作用域的。
.this关键字
this是对当前的引用,在JavaScript由于对象的引用是多层次,多方位的,往往一个对象的引用又需要对另一个对
象的引用,而另一个对象有可能又要引用另一个对象,这样有可能造成混乱,最后自己已不知道现在引用的那一个对象
,为此JavaScript提供了一个用于将对象指定当前对象的语句this。
.New运算符
虽然在JavaScript中对象的功能已经是非常强大的了。但更强大的是设计人员可以按照需求来创建自己的对象,以
满足某一特定的要求。使用New运算符可以创建一个新的对象。其创建对象使用如下格式:
Newobject=NEW Object(Parameters table);
其中Newobject创建的新对象:object是已经存在的对象; parameters table参数表;new是JavaScript中的命令
语句。
如创建一个日期新对象
newData=New Data()
birthday=New Data (December 12.1998)
之后就可使NewData、birthday作为一个新的日期对象了。
4、对象属性的引用
对象属性的引用可由下列三种方式之一实现:
(1)使用点(.)运算符
university.Name=“云南省”
university.city=“昆明市”
university.Date="1999"
其中university是一个已经存在的对象,Name、City、Date是它的三个属性,并通过操作对其赋值。
(2)通过对象的下标实现引用
university[0]=“云南”
university[1]=“昆明市”
university[2]="1999"
通过数组形式的访问属性,可以使用循环操作获取其值。
function showunievsity(object)
for (var j=0;j<2; j++)
document.write(object[j])
若采用For...in则可以不知其属性的个数后就可以实现:
Function showmy(object)
for (var prop in this)
docament.write(this[prop]);
(3)通过字符串的形式实现
university["Name"]=“云南”
university["City"]=“昆明市”
university["Date"]="1999"
5、对象的方法的引用
在JavaScript中对象方法的引用是非常简单的。
ObjectName.methods()
实际上methods()=FunctionName方法实质上是一个函数。 如引用university对象中的showmy()方法,则可使用:
document.write (university.showmy())
或:document.write(university)
如引用math内部对象中cos()的方法
则:
with(math)
document.write(cos(35));
document.write(cos(80));
若不使用with则引用时相对要复杂些:
document.write(Math.cos(35))
document.write(math.sin(80))
二、常用对象的属性和方法
JavaScript为我们提供了一些非常有用的常用内部对象和方法。用户不需要用脚本来实现这些功能。这正是基于对
象编程的真正目的。
在JavaScript提供了string(字符串)、math(数值计算)和Date(日期)三种对象和其它一些相关的方法。从而
为编程人员快速开发强大的脚本程序提供了非常有利的条件。
1、常用内部对象
在JavaScript中对于对象属性与方法的引用,有两种情况:其一是说该对象是静态对象,即在引用该对象的属性或
方法时不需要为它创建实例;而另一种对象则在引用它的对象或方法是必须为它创建一个实例,即该对象是动态对象。
对JavaScript内部对象的引用,以是紧紧围绕着它的属性与方法进行的。因而明确对象的静动性对于掌握和理解
JavaScript内部对象是具有非常重要的意义。
1)、串对象
string对象:内部静态性。
访问properties和methods时,可使用(.)运算符实现。
基本使用格式:objectName.prop/methods
(1)串对象的属性
该对象只有一个属性,即length。它表明了字符串中的字符个数,包括所有符号。例:
mytest="This is a JavaScript"
mystringlength=mytest.length
最后mystringlength返回mytest字串的长度为20。
(2)串对象的方法
string对象的方法共有19个。主要用于有关字符串在Web页面中的显示、字体大小、字体颜色、字符的搜索以及字
符的大小写转换。
其主要方法如下:
锚点anchor():该方法创建如用Html文档中一样的anchor标记。使用anchor如用Html中(A Name="")一样。通过下
列格式访问:string.anchor(anchorName)。
有关字符显示的控制方法
big字体显示, Italics()斜体字显示,bold()粗体字显示,blink()字符闪烁显示,small()字符用小体字显示
,fixed()固定高亮字显示、fontsize(size)控制字体大小等。
字体颜色方法;fontcolor(color)
字符串大小写转换
toLowerCase()-小写转换,toUpperCase()大写转换。下列把一个给定的串分别转换成大写和小写格式:
string=stringValue.toUpperCase和string=stringValue.toLowerCase。
字符搜索:indexOf[charactor,fromIndex]
从指定formIndtx位置开始搜索charactor第一次出现的位置。
返回字串的一部分字串:substring(start,end)
从start开始到end的字符全部返回。
2)、算术函数的math对象
功能:提供除加、减、乘、除以外的一引些自述运算。如对数,平方根等 。
静动性:静态对象
(1)主要属性
math中提供了6个属性,它们是数学中经常用到的常数E、以10为底的自然对数LN10、以2为底的自然对数
LN2、3.14159的PI、1/2的平方根SQRT1-2,2的平方根为SQRT2。
(2)主要方法
绝对值:abs()
正弦余弦值:sin(),cos()
反正弦反余弦 :asin(), acos()
正切反正切:tan(),atan()
四舍五入:round()
平方根:sqrt()
基于几方次的值:Pow(base,exponent)
...
3)、日期及时间对象
功能:提供一个有关日期和时间的对象。
静动性:动态性,即必须使用New运算符创建一个实例。例:
MyDate=New Date()
Date对象没有提供直接访问的属性。只具有获取和设置日期和时间的方法。
日期起始值:1770年1月1日00:00:00。
获取日期的时间方法
getYear(): 返回年数
getMonth():返回当月号数
getDate(): 返回当日号数
getDay():返回星期几
getHours():返回小时数
getMintes(:返回分钟数
getSeconds():返回秒数
getTime() : 返回毫秒数
(2)设置日期和时间:
setYear();设置年
setDate():设置当月号数
setMonth():设置当月份数
setHours():设置小时数
setMintes():设置分钟数
setSeconds():设置秒数
setTime ():设置毫秒数
...
2、JavaScript中的系统函数
JavaScript中的系统函数又称内部方法。它提供了与任何对象无关的系统函数,使用这些函数不需创建任何实例,
可直接用。
返回字符串表达式中的值:
方法名:eval(字串表达式),例:
test=eval("8+9+5/2");
返回字符串ASCI码:
方法名:unEscape (string)
返回字符的编码:
方法名:escape(character)
返回实数:
parseFloat(floustring);
返回不同进制的数:
parseInt(numbestring ,rad.X)
其中radix是数的进制,numbs字符串数
当今交互式网络的世界里,JavaScript(JS)扮演着至关重要的角色,它赋予了网站生命力、响应性和用户交互性。本文将深入探讨JavaScript,提供一个全面的指南,帮助你掌握网站开发的动态艺术。
什么是JavaScript?
JavaScript是一种高级、跨平台的编程语言,专门用于在网页上创建动态和交互式内容。它允许你操纵HTML元素、响应用户输入并创建复杂的网页应用程序。
JavaScript语法
JavaScript语法与其他编程语言相似,包括:
JavaScript对象
对象是JavaScript中组织和存储数据的基本单位。它们由键值对组成,其中键是属性名称,值是属性值。例如,以下JavaScript对象表示一个人的信息:
const person={
name: "John Doe",
age: 30,
occupation: "Software Engineer"
};
JavaScript事件
事件是用户与网页交互时触发的。JavaScript允许你侦听事件并相应地执行代码。最常见的事件类型包括:
JavaScript DOM
文档对象模型(DOM)是JavaScript与网页交互的接口。它允许你访问和修改HTML元素及其属性。例如,以下JavaScript代码获取页面中所有段落元素并将其文本设置为红色:
const paragraphs=document.querySelectorAll("p");
paragraphs.forEach((paragraph)=> {
paragraph.style.color="red";
});
学习JavaScript
学习JavaScript相对容易,有许多在线资源和教程可供使用。以下是一些提示:
掌握JavaScript的好处
掌握JavaScript有很多好处,包括:
结论
JavaScript是赋予网站生命力的编程语言。通过理解其语法、对象和事件,你可以解锁创建动态、交互式和用户友好的网页的能力。无论你是想增强现有网站的功能还是从头开始开发新的应用程序,掌握JavaScript都是必不可少的。
本文主要理理js模块化相关知识。
涉及到内联脚本、外联脚本、动态脚本、阻塞、defer、async、CommonJS、AMD、CMD、UMD、ES Module。顺带探究下Vite。
假设你是一个前端新手,现在入门,那么我们创建一个html页面,需要新建一个index.html文件:
<!DOCTYPE html>
<html>
<head>
<title>test</title>
</head>
<body>
<p id="content">hello world</p>
</body>
</html>
如果需要在页面中执行javascript代码,我们就需要在 HTML 页面中插入 <script> 标签。
有2种插入方式:
1、放在<head>中
2、放在<body>中
比如,点击hello world之后,在hello world后面加3个感叹号的功能,我们在head中加入script标签,并给hello world绑定点击事件:
<!DOCTYPE html>
<html>
<head>
<title>test</title>
<script>
function myFunction() {
document.getElementById('content').innerHTML='hello world!!!'
}
</script>
</head>
<body>
<p id="content" onclick="myFunction()">hello world</p>
</body>
</html>
如果加在body中,一般放在body的最后面:
<!DOCTYPE html>
<html>
<head>
<title>test</title>
</head>
<body>
<p id="content" onclick="myFunction()">hello world</p>
<script>
function myFunction() {
document.getElementById('content').innerHTML='hello world!!!'
}
</script>
</body>
</html>
简单的逻辑我们可以用这2种方式写,这种方式叫做内联脚本。
当逻辑复杂时,我们可以把上面的script标签中的代码抽取出来,比如在html的同级目录创建一个js文件夹,里面新建一个a.js的文件。
a.js中写上面script标签中的代码:
function myFunction() {
document.getElementById('content').innerHTML='hello world!!!'
}
上面的script标签则可以改成:
<script src="./js/a.js"></script>
上面的2种写法,浏览器在加载html时,遇到script标签,会停止解析html。
内联脚本会立刻执行;外联脚本会先下载再立刻执行。
等脚本执行完毕才会继续解析html。
(html解析到哪里,页面就能显示到哪里,用户也能看到哪里)
比如下面的代码:
<p>...content before script...</p>
<script src="./js/a.js"></script>
<p>...content after script...</p>
解析到第一个p标签,我们能看到...content before script...显示在了页面中,然后浏览器遇到script标签,会停止解析html,而去下载a.js并执行,执行完a.js才会继续解析html,然后页面中才会出现...content after script...。
我们可以通过Chrome的Developer Tools分析一下index.html加载的时间线:
这会导致2个问题:
1、脚本无法访问它下面的dom;
2、如果页面顶部有个笨重的脚本,在它执行完之前,用户都看不到完整的页面。
对于问题2,我们可以把脚本放在页面底部,这样它可以访问到上面的dom,且不会阻塞页面的显示:
<body>
...all content is above the script...
<script src="./js/a.js"></script>
</body>
但这不是最好的办法,我们接着往下看。
我们给script标签加defer属性,就像下面这样:
<p>...content before script...</p>
<script defer src="./js/a.js"></script>
<p>...content after script...</p>
defer 特性告诉浏览器不要等待脚本。于是,浏览器将继续解析html,脚本会并行下载,然后等 DOM 构建完成后,脚本才会执行。
这样script标签不再阻塞html的解析。
这时再看时间线:
需要注意的是,具有 defer 特性的脚本保持其相对顺序。
比如:
<script defer src="./js/a.js"></script>
<script defer src="./js/b.js"></script>
上面的2个脚本会并行下载,但是不论哪个先下载完成,都是先执行a.js,a.js执行完才会执行b.js。
这时,如果b.js依赖a.js,这种写法将很有用。
另外需要注意的是,defer 特性仅适用于外联脚本,即如果 script标签没有 src属性,则会忽略 defer 特性。
我们可以给script标签加async属性,就像下面这样:
<script async src="./js/a.js"></script>
这会告诉浏览器,该脚本完全独立。
独立的意思是,DOM 和其他脚本不会等待它,它也不会等待其它东西。async 脚本就是一个会在加载完成时立即执行的完全独立的脚本。
这时再看时间线:
可以看到,虽然下载a.js不阻塞html的解析,但是执行a.js会阻塞。
还需要注意多个async时的执行顺序,比如下面这段代码:
<p>...content before script...</p>
<script async src="./js/a.js"></script>
<script async src="./js/b.js"></script>
<p>...content after script...</p>
两个p标签的内容会立刻显示出来,a.js和b.js则并行下载,且下载成功后立刻执行,所以多个async时的执行顺序是谁先下载成功谁先执行。
一些比较独立的脚本,比如性能监控,就很适合用这种方式加载。
另外,和defer一样,async 特性也仅适用于外联脚本。
我们可以动态地创建一个script标签并append到文档中。
let script=document.createElement('script')
script.src='/js/a.js'
document.body.append(script)
append后脚本就会立刻开始加载,表现默认和加了async属性一致。
我们可以显示的设置script.async=false来改变这个默认行为,那么这时表现就和加了defer属性一致。
上面的这些写法,当script标签变多时,容易导致全局作用域污染,还要维护书写顺序,要解决这个问题,需要一种将 JavaScript 程序拆分为可按需导入的单独模块的机制,即js模块化,我们接着往下看。
很长一段时间 JavaScript 没有模块化的概念,直到 Node.js 的诞生,把 JavaScript 带到服务端,这时,CommonJS诞生了。
CommonJS定义了三个全局变量:
require,exports,module
require 读入并执行一个 js 文件,然后返回其 exports 对象;
exports 对外暴露模块的接口,可以是任何类型,指向 module.exports;
module 是当前模块,exports 是 module 上的一个属性。
Node.js 使用了CommonJS规范。
比如:
// a.js
let name='Lily'
export.name=name
// b.js
let a=require('a.js')
console.log(a.name) // Lily
由于CommonJS不适合浏览器端,于是出现了AMD和CMD规范。
AMD(Asynchronous Module Definition) 是 RequireJS 在推广过程中对模块定义的规范化产出。
基本思想是,通过 define 方法,将代码定义为模块。当这个模块被 require 时,开始加载依赖的模块,当所有依赖的模块加载完成后,开始执行回调函数,返回该模块导出的值。
使用时,需要先引入require.js:
<script src="require.js"></script>
<script src="a.js"></script>
然后可以这样写:
// a.js
define(function() {
let name='Lily'
return {
name
}
})
// b.js
define(['a.js'], function(a) {
let name='Bob'
console.log(a.name) // Lily
return {
name
}
})
CMD(Common Module Definition) 是 Sea.js 在推广过程中对模块定义的规范化产出。
使用时,需要先引入sea.js:
<script src="sea.js"></script>
<script src="a.js"></script>
然后可以这样写:
// a.js
define(function(require, exports, module) {
var name='Lily'
exports.name=name
})
// b.js
define(function(require, exports, module) {
var name='Bob'
var a=require('a.js')
console.log(a.name) // 'Lily'
exports.name=name
})
UMD (Universal Module Definition) 目的是提供一个前后端跨平台的解决方案(兼容全局变量、AMD、CMD和CommonJS)。
实现很简单,判断不同的环境,然后以不同的方式导出模块:
(function (root, factory) {
if (typeof define==='function' && (define.amd || define.cmd)) {
// AMD、CMD
define([], factory);
} else if (typeof module !=='undefined' && typeof exports==='object') {
// Node、CommonJS
module.exports=factory();
} else {
// 浏览器全局变量
root.moduleName=factory();
}
}(this, function () {
// 只需要返回一个值作为模块的export
// 这里我们返回了一个空对象
// 你也可以返回一个函数
return {};
}));
AMD 和 CMD 是社区的开发者们制定的模块加载方案,并不是语言层面的标准。从 ES6 开始,在语言标准的层面上,实现了模块化功能,而且实现得相当简单,完全可以取代上文的规范,成为浏览器和服务器通用的模块解决方案。
ES6 的模块自动采用严格模式。模块功能主要由两个命令构成:export和import。
export命令用于规定模块的对外接口;
import命令用于输入其他模块提供的功能。
比如上面的代码,我们可以这样写:
// a.js
const name='Lily'
export {
name
}
// 等价于
export const name='Lily'
// b.js
import { name } from 'a.js'
console.log(name) // Lily
// b.js
import * as a from 'a.js'
console.log(a.name) // Lily
此外,还可以用export default默认导出的写法:
// a.js
const name='Lily'
export default {
name
}
// b.js
import a from 'a.js'
console.log(a.name) // Lily
如果只想运行a.js,可以只import:
// b.js
import 'a.js'
我们可以给script标签加type=module让浏览器以 ES Module 的方式加载脚本:
<script type="module" src="./js/b.js"></script>
这时,script标签会默认有defer属性(也可以设置成async),支持内联和外联脚本。
这时我们运行打开index.html,会发现浏览器报错了:
这是因为 type=module 的 script 标签加强了安全策略,浏览器加载不同域的脚本资源时,如果服务器未返回有效的 Allow-Origin 相关 CORS 头,会禁止加载改脚本。而这里启动的index.html是一个本地文件(地址是file://路径),将会遇到 CORS 错误,需要通过一个服务器来启动 HTML 文件。
在浏览器支持 ES Module 之前,我们用工具实现JavaScript模块化的开发,比如webpack、Rollup 和 Parcel 。但是当项目越来越大后,本地热更新越来越慢,而 Vite 旨在利用ESM解决上述问题。
Vite使用简单,可以去官网(https://cn.vitejs.dev/)看看。
老的规范了解即可,未来是ES Module的,用Vite可以极大的提升开发时的体验,生产环境用Rollup打包。
*请认真填写需求信息,我们会在24小时内与您取得联系。