javascript
**********本章大量示例和内容引用自w3cschool的javascript教程**************
本来已经快写完90%左右了,结果不小心跑了个js,不小心把浏览器弄死,不小心没保存草稿T-T一切都要从头开始写过了orz。好吧再写一遍!
■ 概述
js是一种轻量级的浏览器脚本语言,其兼容性很好(几乎可以用在所有的浏览器上)这也就意味着从PC到智能手机所有可以用浏览器的设备都可以运行js脚本了。所以说js是互联网上最受欢迎&最常用的脚本语言不为过。
js被互联网所青睐的原因在于它可以嵌入html文件中,并且可以和html中的各种元素进行互动。在html文件的<head>或者<body>中,可以加入<script>标签,而<script></script>里面就可以写js脚本的内容了。如果想引用外部脚本的话可以在script中加上src属性指向一个外部脚本,这样<script>里面就不用写任何内容直接</script>就好了
由于js没有一个专门的编译器或者集成较好的IDE之类的工具,测试js略显麻烦一点,在下面的大部分实例中,为了看到js的效果我们暂时会用document.write(...)这个js里的方法,它牵扯到HTML
DOM,意思是网一个网页上写html代码,暂时把它当成是其他语言里的print语句,用来打印出结果就好了。
■ 基本语法
● 注释
js和其他语言一样可以注释,其注释的形式和C或者java很像。注释内容用/*comment*/的形式表现,另外也可以用//comment的形式来进行一整行的注释
● 语句规则
浏览器等软件会对js语句进行解释。js是一种解释型语言,解释器对语句逐条进行解释而不是事先编译再运行。
js的语句后面可以加上分号。但是这不是语法要求而是很多程序员的习惯(像我这种写惯了python的话就经常不加分号。。)。
当然不用多说,js的语句是对大小写敏感的,不像sql一样大小写一样。
此外和C以及java一样,js用大括号来括起一些语句组成一个代码块。在函数,循环,条件语句中就要用到这些代码块了。
和python一样js可以用"\"进行代码的折行,即用这个符号跟在一行最后面,解释时下一行代码会紧跟着这一行进行解释。
在js的语句中,多余的空格都不会被解释,和python一样。所以在书写的时候可以适当地加入些空格来美化代码,比如var = 1和var=1效果是一样的。
● 变量赋值和初始化
js中有各种内建的数据类型,包括Number(包括传统意义上的int型,float型等),Boolean(true和false),String(双引号或单引号都可以表示字符串), Null(空值),Array(数组),Object(对象)
变量声明时用var关键字,声明时不必特地指出变量的类型,当声明却不赋值时(如var x)默认变量的值为undefined,即变量没有值(注意undefined和null的区别,undefined是说变量根本就没有赋过值,而null说的是变量的值是空值)。js支持在一行里声明多个变量并赋值:
var city = "北京";
var count = 100
var name
var firstname = "Frank", lastname = "Takanashi"
对于Array和Object这两种类型稍微有点不同。
Array是类似于python的list,有下列几种初始化的方法:
var cars=new Array("Audi","BMW","Volvo"); var cars=new Array();
cars[0]="Audi";
cars[1]="BMW";
cars[2]="Volvo"; var cars=["Audi","BMW","Volvo"];
而Object类似于python的dict,可以如下初始化:
*可以看到,object的key不用打引号,这点和python是不一样的。另外访问属性时可以采用obj['key']和obj.key两种形式,注意引号用法
var person={firstname:"Bill", lastname:"Gates", id:5566}; /*初始化时可以换行,让格式更清晰*/
var person={
firstname : "Bill",
lastname : "Gates",
id : 5566
};
*关于JSON和JS对象:
其实JSON全称就是javascript object notation,表名JSON格式和JS是有千丝万缕的联系的。在JS中可以调用JSON.parse('xxx')或者eval('('+'xxx'+')')来把一个JSON字符串转化为一个JS对象,而一个对象则可以调用obj.toString()之类的办法转化为JSON格式字符串。
如果想要清空变量的值,可以把null赋值给变量。再次强调,null值和undefined不一样,null是空值,而undefined是没有值。
声明变量时如果不想赋值可以用new关键字+类型名字:
var carname=new String;
var x= new Number;
var y= new Boolean;
var cars= new Array;
var person= new Object;
这样声明出来的变量其值是null
* 赋值过程的深浅拷贝
和Python中一样,Javascript中直接进行赋值的时候会涉及到深浅拷贝的问题。在讨论Javascript的时候,其实可以认为浅复制就是赋值,而深复制是深复制,这一点和Python是不太一样的(Python中明确浅复制和赋值之间的区别)。
比如令d = {'a': 1},如果令 b = d,那么在通过d.a = 2对数据做出修改后b.a也会变成2。
但是如果令 c = JSON.parse(JSON.stringify(d)) 的话,那么做出同样的修改并不会影响源数据,因为通过JSON序列化再反序列化的过程是一个深复制的过程。
● 对象的方法和属性
这个对象是广义上的对象,在js里面,和python一样,一切皆对象,然后对象有方法和属性可供调用。调用方式是用符号"."。我们可以自定义对象,js中也有很多内建的对象。总而言之,对象有点像一个类,但是js中没有类这个概念,所以我们用对象来指代这么一种实体。下文中有些时候我可能会说类怎么样怎么样,那其实是在说对象的事情。更多内建对象的详细方法和属性也会在下面讲到。
关于this:this是JS中常用的一个关键字,其指代一个对象,具体什么对象要看具体情况。比如
1.一般情况下函数中的this指向调用这个函数的对象
2.当函数没有所属对象的时候this指向顶层的全局对象
3.当函数是一个构造器时,this指向将被构造出来的新对象
……
● 函数
js中可以定义函数
function funcName(para1,para2){
//some code
}
定义函数时不必特地指出返回值的类型,函数中用return语句来规定函数的返回值。
js可以在函数中声明变量,在函数中声明的变量当然是个函数内部的局部变量。在函数外声明的一般就是全局变量了
* 在声明变量时,前面不加var关键字也可以声明,这么声明的变量默认是个全局变量,整个文件都可以访问它。
js中支持匿名函数的设置,也就是说上面格式中的funcName不是必须的。可以直接function(){...}。就像python中的lambda一样,匿名函数只能用一次,可以作为一种临时性整合语句块的手段
● 运算符
js中大多数运算符都和我们所知道的经典编程中的运算符是一致的,下面我把一些我不太熟悉,看到之后觉得是js中比较特殊的运算符相关的东西写一下:
等性运算:
js中的"=="不是经典意义上的等于。js中用==会把比较的两个对象做一个自动的类型转换,比如5 == "5"在js中是true因为它会把Number类型的5转化成String类型的"5"再和右边比较,自然对比出的结果是真。另一方面,如果不想让它自动转换类型,可以用"===",三个等号在js中指完全相等。
加减运算:
和上面等性中提到的类似,js中会把和字符串相加的类型自动转化成字符串再来相加,比如5 + "5"不会报错而得到结果"55",5 + 5得到10。
条件运算:
js中支持类似于(condition)?value1:value2这样的三元条件运算。
逻辑运算:
js中的逻辑运算用的是经典的&& ; || ; !而不是and ; or ; not
■ 常用语句
● if/else语句
if (条件 1)
{
当条件 1 为 true 时执行的代码
}
else if (条件 2)
{
当条件 2 为 true 时执行的代码
}
else
{
当条件 1 和 条件 2 都不为 true 时执行的代码
}
● switch语句
switch(n)
{
case 1:
执行代码块 1
break;
case 2:
执行代码块 2
break;
default:
n 与 case 1 和 case 2 不同时执行的代码
}
● for循环
js中可以用两种形式的for循环,第一种是比较经典的java和C里面那样的三条件语句的for循环:
for (var i=0; i<5; i++)
{
x=x + "The number is " + i + "<br>";
}
可以看到在第一个条件语句里面我们可以进行变量的声明,声明出的变量可以用于这个循环当中
第二种形式是像python中的for/in循环。但是需要注意的是,js中的for/in循环和python中的for/in循环是有很大区别的。也别忘了js中的for/in是有个小括号的。
当for/in遍历一个Object(类似dict)的时候,和python中类似,key是代表了Object中各个key的内容:
var person={fname:"John",lname:"Doe",age:25}; for (key in person)
{
txt=txt + person[key];
}
当用for/in遍历一个Array的时候就不一样了:
var list = ["a","b","c"] for (index in list){
document.write(list[index])
}
这里for/in中写的index不是list中各个成员的内容"a","b"和"c",而是指代这个list的index 0,1和2。换句话说,js中for/in处理一个数组的时候,实际上是先获取数组的长度,然后把这个长度从0到最后一次次赋给index,用这样的一个index进入循环执行的语句。所以在访问list中各个成员的时候,我们不是直接用index而是用list[index]
● while循环
js中有while循环和do/while循环两种:
while (条件)
{
需要执行的代码
}
do/while循环的执行体一定被执行一遍:
do
{
需要执行的代码
}
while (条件);
以上两种,for循环和while循环都可以再循环体中用break语句跳出循环,continue语句跳过循环
● 异常处理
js中可以进行异常处理如:
try
{
//在这里运行代码
}
catch(err)
{
//在这里处理错误
}
在合适的地方,可以用throw语句来抛出异常:
throw "some exception message"
■ 对象的说明&内建对象
正如上面所说,对象是一个类似于别的语言中的类的一个存在。因为js中一切皆对象,包括函数和各种复杂的数据结构,所以构造一个对象时可以像下面这个函数一样。这个函数也被称为一个对象构造器(有点像一个类的构造方法)
function person(firstname,lastname,age,eyecolor)
{
this.firstname=firstname;
this.lastname=lastname;
this.age=age;
this.eyecolor=eyecolor; function changeName(name)
{
this.lastname=name;
}
this.changeName=changeName;
}
● 全局对象&属性
全局属性和函数可用于所有内建的 JavaScript 对象。常用的有:
escape(...) 对字符串进行编码,这样就可以在所有的计算机上读取该字符串。比如Visit W3School!被escape之后变成Visit%20W3School%21(这种编码格式我还不是很懂。。这是什么用的编码额)
unescape(..) escape的反操作。
eval(string) 和python的eval函数一样,将一些javascript字符串解析并执行
isNaN(...) 检查某个对象是否是数字
parseInt(...) 把一个字符串解析成一个整数对象
parseFloat(...) 把一个字符串解析成浮点数对象
Number(...) 把对象的值转换为数字
下面详细说明一下各个内建类型对象的属性和方法。直属于该种类型方法或属性,其调用方法是类型名.属性或方法名,下面说明中前缀是其类型名字(事实上也是实际调用时候的写法)。如果是这种类型对象的一个实例的属性或方法的话,就用类型对象首字母小写来代表一个实例
● Number类型对象
属性:
Number.MAX_VALUE js所能表示的最大数,大约是1.7976931348623157 x 10308。
Numebr.MIN_VALUE js所能表示的最小数
Number.NaN 表示一个非数字对象,在调用Number(...)初始化一个对象的时候如果失败了就会返回这个值
Number.NEGATIVE_INFINITY 负无穷大,溢出时会返回此值
Numebr.POSITIVE_INFINITY 正无穷大,溢出时返回此值
方法:
n.toString(r) 返回数字以r进制表示的字符串,比如2.toString(2)是10
n.toFixed(p) 返回数字的字符串,取小数点后p位
n.valueOf() 返回数字值
● String类型对象 http://www.w3school.com.cn/jsref/jsref_obj_string.asp
属性:
s.length 返回字符串的长度
方法:(String类的方法较多,可以参见上面的网址,下面列出几个常用的)
s.indexOf(...) 检索字符串,返回找到第一个字串的位置,没找到返回-1
s.split(sep) 以sep为分隔符分割字符串,返回得到的数组。和python的split不同的是sep是必须的,而且当sep写""的时候不会报错,而是把字符串所有字符都分割开
s.match(pattern) 检索字符串,支持正则表达式pattern。返回的不是索引而是匹配到的内容,另外pattern也可以是个RegExp对象。同时match的行为和pattern的具体形式(比如带不带g属性)有关,下面的RegExp对象中会详细说到。*当写正则表达式的时候不能加引号,比如match("/\d/g")是不会按照你的预期匹配数字的,而应该写match(/\d/g),而匹配子字符串的时候要加引号,如match("123")。
s.search(pattern) search方法专门用来做正则匹配,而且忽略属性g,不管你有多少个匹配项我只返回发现的第一个。并且返回的是索引不是内容。
s.replace(pattern,replacement) 替换指定的子字符串或者正则式匹配到的内容。
此外,因为js要和浏览器界面互动,所以String类还有一大票修饰输出字符串的方法比如bold(),italics(),strike()(删除线输出),toLowerCase(),toUpperCase(),link()(超链接样式输出),fontSize(size),fontColor(color)等等。
● Date类型对象 http://www.w3school.com.cn/jsref/jsref_obj_date.asp
Date类型的属性全部都封装在对象里面不允许直接调用,可以通过调用相关的方法来获取和设置属性。很多方法都是顾名思义的,不详述
另外,Date类的属性是可以直接和数字相加减的。比如one_year_later = d.getDate() + 365,然后再one_year_later.getDate()的话得到的就是一年(365天)后的那一天同一时刻的Date对象了(有点像python的datetime模块里的datetime类可以比大小,可以相减得到timedelta类型)
方法:
Date() (不需要前缀加类名或实例)返回当前的Date对象
d.toString() 返回时间字符串,格式如Fri Apr 07 2017 17:18:47 GMT+0800
d.getTime() 返回时间戳(毫秒为单位)
d.getDate() 返回日期 1~31
d.getMonth() 0~11
d.getDay() 0~6
d.getFullYear() 返回四位年份
d.getHours() 0~23
d.getMinutes() 0~59
d.getSeconds() 0~59
以上所有get方法都有相对应的set方法来设置一个Date类型对象的属性的值
● Array类型对象 http://www.w3school.com.cn/jsref/jsref_obj_array.asp
属性:
a.length 返回数组的长度
方法:
a.pop() 从数组末尾删除并返回一个值
a.push(...) 在数组末尾加上一个值(注意,不是append哦)
a.shift() 从数组开头删除并返回一个值
a.unshift(...) 在数组开头加上一个或多个值(以逗号隔开即可)
a.sort() 返回一个排序好的数组(注意和python里不一样,这里是返回而不是在a本身上排序哦,reverse也是这样)
a.join([sep]) 以sep为分隔符连接起数组成员,返回连接后的字符串。当sep未指定时默认用逗号
a.reverse() 返回一个倒序的数组
● Math类型对象 http://www.w3school.com.cn/jsref/jsref_obj_math.asp
之前基本上没怎么提到过Math类型,因为与其说Math是一个类型对象,不如说它是个模块或库。它的属性和方法都由类直接调用:
属性:
Math.PI 圆周率
Math.SQRT2 根号2
Math.SQRT1_2 根号1/2
Math.LN2 2的自然对数
Math.LN10 10的自然对数
方法:
Math.abs(x) 求绝对值
Math.ceil(x) 对数字x上舍入(返回比x大的最小整数)
Math.floor(x) 对x下舍入
Math.Max(x,y) 返回x和y中的大者(自然Min也有)
Math.random() 返回0~1间随机一个实数
Math.round(x) 对x四舍五入
Math.sqrt(x) 求x方根
此外还有一大票的三角函数方法
● RegExp类型对象 http://www.w3school.com.cn/jsref/jsref_obj_regexp.asp
RegExp是Regular Expression的缩写,即正则表达式。关于正则,之前也说到过了,但是这里说的是正则表达式对象。就好比是python里re.compile返回的对象一样。
首先关于js中的正则表达式,其基本格式是/pattern/attribute。pattern就是个和python等里面一样的正则表达式,规则譬如.(通配符){}(重复次数规定)\d(数字字符)等一样的。而后面的attribute是js中特有的一个属性,其可选项有i,g,m三种。
i表示ignore case,即匹配的时候忽略大小写的区别
g表示global,默认情况下,正则表达式总是只匹配到第一个就完了,但是设置属性g之后,它就会把所有的都匹配出来。具体怎么匹配请看下面具体方法的说明。
m表示multiline,具体什么意思不知道。。
属性:
r.ignoreCase 判断这个正则对象是否设置了i属性,下面两个也是类似的。
r.global
r.multiline
r.lastIndex 和设置g属性时匹配的方式有关,下面会讲到
方法:
RegExp(pattern,attribute) 正则对象的构造方法,和String.match方法不同,这里的pattern应该用引号引起来,attribute则是写"g","i"这种。
r.test(str) 用正则对象匹配str,如果匹配到了内容就返回true,否则false
r.compile("new pattern","new attribute") 编译正则对象,通常用于更新一个正则对象的表达式或属性
r.exec(str) exec方法分成两种情况,加入r对象没有设置g属性,那么exec返回一个数组array,array[0]是第一次匹配得到的内容,array[1],array[2]这些是这个内容里对应正则表达式的第一、二子模式,以此类推。如果r对象设置了g属性,那么exec会返回匹配到的内容数组(如没有设置g属性时一样),并且将r.lastIndex设置为当前匹配内容结束时的索引位置,然后下一次再调用exec的时候,就从这个lastIndex开始继续匹配,如此一直匹配到尾巴上如果没有匹配到就返回一个null并重置lastIndex为0。所以我们可以手动设置一个循环,让r.exec一口气输出所有可匹配的内容。比如:
var str = "Visit W3School, W3School is a place to study web technology.";
var patt = new RegExp("W3Sc(.*)ool","g");
var result; while ((result = patt.exec(str)) != null) {
document.write(result);
document.write("<br />");
document.write(patt.lastIndex);
document.write("<br />");
} /****结果*****
W3School,h
14
W3School,h
24
*/