f10@t's blog

Javascript基础之数据类型2

字数统计: 3.7k阅读时长: 14 min
2018/08/16

今将学习上篇提到的数据类型中的三种引用型数据:数组(Array)、对象(Object)和函数(Function) 这三个包含的方法和细节比较多,慢慢食用(手动滑稽),建议多看w3cschool的教程。 ### 函数 > Javascript是函数式编程语言。

一.定义函数的方法有两种:

  1. 使用function语句声明函数 如:
    1
    2
    3
    function f(){           //命名函数
    alert('hello,world!');
    }
    1
    2
    3
    var f = function(){       //匿名函数
    alert('hello,world!');
    }
    命名函数的方法也被称为声名式函数,匿名函数的方法也被称为引用式函数或函数表达式(可理解为讲一个复杂的表达式赋给了变量)
  2. 通过Function对象来构造函数
    1
    var f = function_name = new Function(arg1, arg2, ..., argN, function_body)
    每一个arg为一个参数。最后一个参数为函数主体。所有参数必须为字符串 如:
    1
    2
    var say = new Function("name", "say", "document.write('<h1>' + name + ': ' + say + '</h1>');");
    say("李四", "Hi!"); //调用函数
    但是function定义方法更为简单,执行效率高,第二种定义方法仅用于特定的动态环境。 改为function定义:
    1
    2
    3
    4
    function f(name, say){
    document.write('<h1>' + name + ':' + say + '</h1>');
    }
    f("李四", "Hi!");
    效果相同,但结构更清晰。

二.调用方法、参数、应用

  1. 调用方法很简单,使用小括号()包含参数列表即可,可参考上面的代码。
  2. 参数可分为两种:实参和形参。如果接触过C语言的话,理解起来就很简单了。 形参:即定义函数时的参数,称为形参,形式上的参数,实际上没东西(手动滑稽) 实参:调用函数时传给形参的参数,即实际参数 如上面代码中函数f的name和say就是形参,表示我这个函数需要两个参数才能执行,后面的李四和Hi!才是真正的参数,即实参。 注意 Javascript没有规定实参数量和形参相等,所以含有两个形参的函数,如果在调用时传三个参数,第三个参数是没有用的。相反的你如果只传了一个参数的话,另一个会默认为undefined,返回值是会出错的。 这里有一个检测方法确保参数数量正常,使用js定义的Arguments对象,用它来操控实参,使用arguments.length可以获取函数实参的个数,使用数组下标可以获取实际传输的参数的值。再使用异常处理语句(try/catch)来捕获异常信息,并显示出来。如:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    function f(a, b){
    if(f.length != arguments.length) //检测形参和实参的个数是否形同
    throw new Error("形参和实参数量不相同!");
    else
    return a + b;
    }
    try{
    alert(f(2)); //尝试调用函数
    }
    catch(e){
    alert(e.message); //捕捉异常信息
    }
  3. 函数应用: 匿名函数:即没有名称的函数,一次性使用时更加有效率。
    1
    2
    3
    var z = function(x, y){
    return (x + y) /2;
    }(23, 35);
    函数作为值:函数也属于一种数据,可以作为值付给其他变量
    1
    2
    3
    4
    var a = function(x,y) {
    return (x+y)/2;
    }
    alert( a(12,33) );

函数作为参数 函数作为值可以进行传递,可以将函数作为参数传递给另一个函数,也可以作为返回值。

1
2
3
4
5
6
7
var a = function (f, x, y) {
return f(x, y);
};
var b = function(x, y) {
return x + y;
};
alert( a(b, 3, 4) ); //返回值为7
函数作为表达式 即参与表达式运算中
1
2
3
(function(x) {
alert(x);
})(50);
第一个小括号包含的是一个匿名函数,第一个小括号调用第一个小括号所包含的函数,并传递参数和返回值。 4. 闭包函数 闭包是ECMAScript (JavaScript)最强大的特性之一,闭包是指一个拥由许多变量和绑定了这些变量的环境的表达式(通常为一个函数),所以这些变量也属于表达式的一部分。

闭包函数即被外部函数调用之后,它的变量不会消失,仍被内部函数所使用,而且所有的内部函数拥有对外部函数的访问权限。闭包可以用在许多地方。它的最大用处有两个,一个是下面提到的可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中。

简单来说吧,如果你能理解全局变量和局部变量的概念就简单了。一般来说我们在外部函数中定义的变量(私有变量),外部是不能读取的。那如何读取呢?方法就是在外部函数内部再定义一个内部函数,在其内部输出外部函数的私有变量。如:

1
2
3
4
5
6
 function f1(){
    var n=999;
    function f2(){
      alert(n); // 输出结果999
    }
  }
但是注意,反过来就不行,f2内部的局部变量,对f1就是不可见的。这就是Javascript语言特有的"链式作用域"结构(chain scope),子对象会一级一级地向上寻找所有父对象的变量。所以,父对象的所有变量,对子对象都是可见的,反之则不成立。

那么在外部读取内部函数私有变量值的方法就有了!只要把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
16
function 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
如果没有闭包函数a的作用,就无法保护私有变量n,就无法实现值的递增效果。 更多

对象

对象(Object)是面向对象编程的核心概念,它是已经命名的数据集合。 #### 一. 创建对象 在Javascript中,对象由new运算符生成,生成对象的函数被称为(或称为构造函数、对象类型)。生成的对象被称为类的实例,简称为对象。 如我们调动系统内置类型函数,实例化几个特殊对象。

1
2
3
var o = new Object();     //构造原型对象
var date = new Date(); //构造日期对象
var ptn = new RegExp("ab+c", "i"); //构造正则表达式对象
也可以通过大括号定义对象直接量。如下:
1
2
3
4
{
name : value,
name1 : value1,
......
使用一个列表来构成对象直接量,这个列表的元素使用冒号分割的属性/值对,元素之间用逗号隔开,整体放在大括号中。
1
2
3
4
var point = {     //定义对象
x:2.3, //属性值
y:-1.2 //属性值
};
#### 二. 访问对象 我们通过点好运算符.来访问对象的属性。 如:
1
2
3
4
5
var point = {     //定义对象
x:2.3, //属性值
y:-1.2 //属性值
};
var x = point.x; //访问对象的属性值
对象的属性值可以是简单的值,也可以是复杂的值,如函数、对象。
1
2
3
4
5
6
7
var point = {
f : function(){
return this.y;
},
y : -1.2
};
var y = point.f(); //返回值为-1.2
this关键字可以代表当前对象,这里指的便是point。 也可以使用多个.来访问嵌套的对象。
1
2
3
4
5
6
7
8
9
var 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
3
var a = [1,2,3,"4","5"];
alert(a[2]);
a[2] = 0; //对单个元素重新赋值
注意:数组的大小不是固定的,可以动态增加或删除数组元素。 #### 三.常用的一些方法: push()和pop() 使用push()可以在数组的末尾插入一个或多个元素,使用pop()方法可以以此把他们丛数组中删除。
1
2
3
4
var a = [];      //定义一个空数组
a.push(1,2,3); //得到数组a[1,2,3]
a.push(4,5); //得到数组a[1,2,3,4,5]
a.pop(); //得到数组a[1,2,3,4]
push()可以带多个任意类型的参数,按顺序插入数组的尾部,pop()方法不带参数,并返回数组中最后一个参数。

unshift()和shift()方法 与上面的两个类似,但是作用于头部。

1
2
3
4
var a = [];      //定义一个空数组
a.unshift(1,2,3); //得到数组a[1,2,3]
a.unshift(4,5); //得到数组a[4,5,1,2,3]
a.shift(); //得到数组a[5,1,2,3]

splice()方法 该方法是一个通用删除和插入的方法,可以在数组指定的位置开始删除或插入元素 splice包含三个参数:array.splice(index,howmany,item1,.....,itemX) 第一个为参数指定插入的指定位置,第二个参数为指定要删除元素的个数,第三个参数开始标识要插入的具体参数。 如下,我们从第二个元素后开始截取2个元素,然后将截取的子数组赋予变量b。

1
2
3
4
var a = [1,2,3,4,5,6];
var b = a.splice(2,2);
document.write(a + "<br />");
document.write(b);
这次加入第三个参数来增加数组元素:
1
2
3
4
var 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
2
3
4
5
6
7
8
9
10
var x
var a = new Array()
a[0] = "a"
a[1] = "b"
a[2] = "c"

for (x in a)
{
document.write(a[x] + "<br />")
}
输出结果: 或者直接使用document.write()输出。

分割或连接:使用join()方法和split()方法 Array对象的join()方法可以将数组元素转换为多种形式的字符串,其包含一个参数,用于连接各个元素,不写时默认为使用逗号,连接。 如:

1
2
3
4
var a = [1,2,3,4,5];
a = a.join("-");
document.write("a类型 = " + typeof(a)+"<br />");
document.write("a的值 = " + a);
可以看到,每个元素都被参数所指定的连接符所连接,并且原类型也变为了字符串类型。 spilt()方法包含两个参数,第一个可以作为切割的标志,分割字符串,第二个用于指定返回的数组的长度。
1
2
3
4
5
var a = [1,2,3,4,5];
a = a.join("-");
var s = a.split("-"3);
document.write("s类型 = " + typeof(s)+"<br />");
document.write("s的值 = " + s);
可以看出,进行了分割,并且只返回前三个元素。

数组排序 使用reverse()方法来进行数组元素顺序的颠倒,sort()方法来进行数组元素的排序。

1
2
3
var a = [1,2,3,4,5];
a.reverse();
document.write(a); //输出结果:5,4,3,2,1
sort()方法排序也要分为两种情况,数字排序,其他(如单词)排序 该方法包括一个参数,排序方法由其参数(一个闭包)来决定,没有的话默认从小到大排序。 注意,该操作是在原始数组上进行的。 数字排序:
1
2
3
4
5
6
7
8
var a = [3,2,5,1,4];
var f = function(x,y){
return y-x;
};
var b = a.sort(f);
document.write(b); //输出5,4,3,2,1
var c = b.sort();
document.write(c); //输出1,2,3,4,5
字母排序:默认升序排列
1
2
3
var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.sort();
document.write(fruits); //输出:Apple,Banana,Mango,Orange

连接数组 使用方法concat()方法,该方法会将参数追加到指定数组中,形成一个新的连接数组。

1
2
3
4
var 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
2
3
4
5
var a = [1,2,3,4,5,6];
var b = a.slice(1, 3);
document.write(b); //输出:2,3 可以看出是一个左闭右开的区间
var c = a.slice(-3,-1);
document.write(c) //输出:4,5

至此javascript的基础数据类型结束,更多请移步w3cscool参考学习。

CATALOG
  1. 1. 一.定义函数的方法有两种:
  2. 2. 二.调用方法、参数、应用
  • 对象
  • 数组