今天将学习上篇提到的数据类型中的三种引用型数据:数组(Array)、对象(Object)和函数(Function) 这三个包含的方法和细节比较多,慢慢食用(手动滑稽),建议多看w3cschool的教程。
函数
Javascript是函数式编程语言。
定义函数:
- 使用function语句声明函数 如: 或
1
2
3function f(){ //命名函数
alert('hello,world!');
}命名函数的方法也被称为声名式函数,匿名函数的方法也被称为引用式函数或函数表达式(可理解为讲一个复杂的表达式赋给了变量)1
2
3var f = function(){ //匿名函数
alert('hello,world!');
} - 通过Function对象来构造函数 每一个arg为一个参数。最后一个参数为函数主体。所有参数必须为字符串 如:
1
var f = function_name = new Function(arg1, arg2, ..., argN, function_body)
1
2var say = new Function("name", "say", "document.write('<h1>' + name + ': ' + say + '</h1>');");
say("李四", "Hi!"); //调用函数
但是function定义方法更为简单,执行效率高,第二种定义方法仅用于特定的动态环境。改为function定义:
1 | function f(name, say){ |
效果相同,但结构更清晰。
调用方法、参数、应用
- 调用方法很简单,使用小括号
()
包含参数列表即可,可参考上面的代码。 - 参数可分为两种:实参和形参。如果接触过C语言的话,理解起来就很简单了。
- 形参:即定义函数时的参数,称为形参,形式上的参数,实际上没东西(手动滑稽)
- 实参:调用函数时传给形参的参数,即实际参数,如上面代码中函数f的name和say就是形参,表示我这个函数需要两个参数才能执行,后面的李四和Hi!才是真正的参数,即实参。
- 注意
Javascript没有规定实参数量和形参相等,所以含有两个形参的函数,如果在调用时传三个参数,第三个参数是没有用的。相反的你如果只传了一个参数的话,另一个会默认为
undefined
,返回值是会出错的。这里有一个检测方法确保参数数量正常,使用js定义的Arguments对象,用它来操控实参,使用arguments.length可以获取函数实参的个数,使用数组下标可以获取实际传输的参数的值。再使用异常处理语句(try/catch)来捕获异常信息,并显示出来。如:1
2
3
4
5
6
7
8
9
10
11
12function f(a, b){
if(f.length != arguments.length) //检测形参和实参的个数是否形同
throw new Error("形参和实参数量不相同!");
else
return a + b;
}
try{
alert(f(2)); //尝试调用函数
}
catch(e){
alert(e.message); //捕捉异常信息
} - 函数应用:
匿名函数:即没有名称的函数,一次性使用时更加有效率。
函数作为值:函数也属于一种数据,可以作为值付给其他变量
1
2
3var z = function(x, y){
return (x + y) /2;
}(23, 35);1
2
3
4var a = function(x,y) {
return (x+y)/2;
}
alert( a(12,33) );
函数作为参数
函数作为值可以进行传递,可以将函数作为参数传递给另一个函数,也可以作为返回值。
1
2
3
4
5
6
7var a = function (f, x, y) {
return f(x, y);
};
var b = function(x, y) {
return x + y;
};
alert( a(b, 3, 4) ); //返回值为71
2
3(function(x) {
alert(x);
})(50);
闭包函数即被外部函数调用之后,它的变量不会消失,仍被内部函数所使用,而且所有的内部函数拥有对外部函数的访问权限。闭包可以用在许多地方。它的最大用处有两个,一个是下面提到的可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中。
简单来说吧,如果你能理解全局变量和局部变量的概念就简单了。一般来说我们在外部函数中定义的变量(私有变量),外部是不能读取的。那如何读取呢?方法就是在外部函数内部再定义一个内部函数,在其内部输出外部函数的私有变量。如:
1
2
3
4
5
6 function f1(){
var n=999;
function f2(){
alert(n); // 输出结果999
}
}
那么在外部读取内部函数私有变量值的方法就有了!只要把f2作为返回值,我们就可以在f1外部读取它的内部变量了。
如该例中,定义了一个函数a,该函数包含一个私有函数b。内部函数b把自身参数m递加给外层函数的私有变量n上,然后返回n的值。外层函数a的返回值为内部函数b,从而形成了一种内层引用外层的闭包关系,于是外层函数就是一个典型的闭包函数。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16function a() { //外层函数,闭包函数
var n = 0; //右边变量n
function b(m){ //内部函数,私有函数
n = n + m; //递加上级私有变量的值
return n; //返回改变的值
}
return b; //返回私有函数
}
var b = a(); //调用外层函数,返回内部函数
document.write(b(3)); //输出3
document.write("<br>");
document.write(b(3)); //输出6
document.write("<br>");
document.write(b(3)); //输出9
document.write("<br>");
document.write(b(3)); //输出12
对象
对象(Object)是面向对象编程的核心概念,它是已经命名的数据集合。
创建对象
在Javascript中,对象由new运算符生成,生成对象的函数被称为类(或称为构造函数、对象类型)。生成的对象被称为类的实例,简称为对象。 如我们调动系统内置类型函数,实例化几个特殊对象。
1 | var o = new Object(); //构造原型对象 |
也可以通过大括号定义对象直接量。如下: 1
2
3
4{
name : value,
name1 : value1,
......1
2
3
4var point = { //定义对象
x:2.3, //属性值
y:-1.2 //属性值
};
我们通过点好运算符.
来访问对象的属性。如: 1
2
3
4
5var point = { //定义对象
x:2.3, //属性值
y:-1.2 //属性值
};
var x = point.x; //访问对象的属性值1
2
3
4
5
6
7var point = {
f : function(){
return this.y;
},
y : -1.2
};
var y = point.f(); //返回值为-1.2this
关键字可以代表当前对象,这里指的便是point。
也可以使用多个.
来访问嵌套的对象。 1
2
3
4
5
6
7
8
9var point = {
x : {
a : 1,
b : 2
},
y : -1.2
};
var a = point.x.a; //返回值为1
//也可以使用集合运算符[]来访问,var a = point["x"]["a"];
数组
上面得对象是无序的数据集合,而数组(Array)则是有序的。
创建数组
定义数组通过构造函数Arry()和运算符new来实现,如下:
- 定义空数组
var a = new Arry();
- 定义含有参数的数组
var a = new Array(1,2,3,"4","5");
,每一个参数都是数组的一个元素值,数组的元素类型没有类型限制。 - 定义指定长度的数组
var a = new Array(6);
这时所有的元素初始值都为undefined。 - 定义数组是也可以省略new运算符,如
var a = Arry(6);
- 定义数组直接量
var a = [1,2,3,"4","5"];
,这样定义快一点。
存取元素
使用[]可以存取数组元素的值,在方括号的左边是数组的引用,方括号内是非负整数值的表达式。如:
1
2
3var a = [1,2,3,"4","5"];
alert(a[2]);
a[2] = 0; //对单个元素重新赋值
常用的一些方法
- push()和pop() 使用push()可以在数组的末尾插入一个或多个元素,使用pop()方法可以以此把他们丛数组中删除。
1 | var a = []; //定义一个空数组 |
push()可以带多个任意类型的参数,按顺序插入数组的尾部,pop()方法不带参数,并返回数组中最后一个参数。
- unshift()和shift()方法 与上面的两个类似,但是作用于头部。
1 | var a = []; //定义一个空数组 |
splice()方法 该方法是一个通用删除和插入的方法,可以在数组指定的位置开始删除或插入元素,splice包含三个参数:
array.splice(index,howmany,item1,.....,itemX)
。第一个为参数指定插入的指定位置,第二个参数为指定要删除元素的个数,第三个参数开始标识要插入的具体参数。如下,我们从第二个元素后开始截取2个元素,然后将截取的子数组赋予变量b。
1 | var a = [1,2,3,4,5,6]; |
这次加入第三个参数来增加数组元素: 1
2
3
4var a = [1,2,3,4,5,6];
var b = a.splice(2,2,7,8,9); //截取第二个位置开始的2个元素赋给b,即[3,4]
document.write(a + "<br />"); //输出[1,2,7,8,9,5,6]
document.write(b); //输出[3,4]
下面将列举几个常用的数组方法:输出:使用 for...in 声明来循环输出数组中的元素。 如:
1 | var x |
输出结果:
或者直接使用document.write()输出。
分割或连接:使用join()方法和split()方法
Array对象的join()方法可以将数组元素转换为多种形式的字符串,其包含一个参数,用于连接各个元素,不写时默认为使用逗号,
连接。如:
1 | var a = [1,2,3,4,5]; |
可以看到,每个元素都被参数所指定的连接符所连接,并且原类型也变为了字符串类型。spilt()方法包含两个参数,第一个可以作为切割的标志,分割字符串,第二个用于指定返回的数组的长度。
1 | var a = [1,2,3,4,5]; |
可以看出,进行了分割,并且只返回前三个元素。
数组排序 使用reverse()方法来进行数组元素顺序的颠倒,sort()方法来进行数组元素的排序。
1 | var a = [1,2,3,4,5]; |
sort()方法排序也要分为两种情况,数字排序,其他(如单词)排序,该方法包括一个参数,排序方法由其参数(一个闭包)来决定,没有的话默认从小到大排序。注意,该操作是在原始数组上进行的。数字排序:
1 | var a = [3,2,5,1,4]; |
字母排序:默认升序排列
1 | var fruits = ["Banana", "Orange", "Apple", "Mango"]; |
连接数组
使用方法concat()方法,该方法会将参数追加到指定数组中,形成一个新的连接数组。
1
2
3
4var a = [1,2,3];
var b = a.concat(4,[5,6],[7,[8,9]]);
document.write(a + '<br>');
document.write(b);
可以看出a数组没有变化,只是将这种变化赋值给了b,另外,参数中如果含有数组的话,该方法会自动将其分解,按顺序加入。
截取子数组
slice()方法可以截取子数组,语法:array.slice(start, end)
含有两个参数,第一个规定从何处开始选取。如果是负数,那么它规定从数组尾部开始算起的位置。也就是说,-1指最后一个元素,-2指倒数第二个元素,以此类推。第二个参数为可选参数,规定从何处结束选取。该参数是数组片断结束处的数组下标。如果没有指定该参数,那么切分的数组包含从start到数组结束的所有元素。如果这个参数是负数,那么它规定的是从数组尾部开始算起的元素。如:
1 | var a = [1,2,3,4,5,6]; |