数组、对象和函数

XiLaiTL大约 11 分钟

数组、对象和函数

在本节中我们将学习有关JavaScript数组、对象以及函数声明定义的有关知识。

数组

声明与定义

在C语言里,我们知道,数组事实上是固定空间的指针的一种语法糖,数组取值符号[]可以用在指针上。我们声明数组的方式为:数据类型 变量名[数组长度];即使使用动态数组的malloc方式,也需要为指针开空间,才能进行数组化操作。同样的,定义数组的4个关键量:数据类型、变量名、是数组[]、数组长度,在JavaScript里也有所体现。

从上一节中我们学习到,数组在JavaScript中是一种数据类型,而实际上又是一种类,为Array类。而[]也是一种语法糖,在声明中,不用声明类型,直接使用[]即可指定为数组类型。

声明方式

以下3种方式都可以声明一个数组。

var myCars=[];
var myCars=new Array();//以new 类名()的方式调用了类的构造函数,生成了新的对象
var myCars=new Array(5);//定义数组长度

定义方式

以下3种方式都可以为数组初始化。

var myCars=["Saab","Volvo","BMW"];//字面量的定义

var myCars=new Array();
myCars[0]="Saab";      
myCars[1]="Volvo";
myCars[2]="BMW";
//在这里我们并没有开空间,但是却可以引用到[0],[1],[2]这样的节点。这是和C语言不一样的地方。

var myCars=new Array("Saab","Volvo","BMW");//这样也可以直接定义

访问数组

像C语言一样,直接使用[]来访问数组元素;与C语言一样,数组第一个元素的序号也为0.

而事实上,在JavaScript中,[]用来访问类里属性名["xxx"]的属性值,而数组自然可以理解为:属性名为数字的一个列表,而没有强制指定类型。因此,JavaScript的数组可以塞进各种数据类型的数据。

var name=myCars[0];//赋值为数组的值
myCars[0]="Opel";//为数组第一个元素赋值

myCars[1]=2;//赋值不同类型的数值

数组的方法和属性

因为数组本身为一个对象,因此与C语言极大的不同是,实现数组的一些操作例如排序等,不需要引入新的库函数,而是直接使用数组自带的方法。这样节省了传递参数的麻烦。

数组的属性

属性值用法示例
lengthopen in new window设置或返回数组元素的个数。myCars.length
prototypeopen in new window允许你向数组对象添加属性或方法。
constructoropen in new window返回创建数组对象的原型函数。

数组的方法

数组的方法主要实现一些与数组内值、索引等有关的操作。

例如:

得到尾部元素并删除:pop(),尾部添加元素push("el");

得到头部元素并删除:shift(),头部添加元素unshift("el");

主要记住提供用法示例的几个方法。

方法名用法示例
concat()open in new window连接两个或更多的数组,并返回结果。var hege = ["Cecilie", "Lone"];
var stale = ["Emil", "Tobias", "Linus"];
var kai = ["Robin"];
var children = hege.concat(stale,kai);
copyWithin()open in new window从数组的指定位置拷贝元素到数组的另一个指定位置中。
entries()open in new window返回数组的可迭代对象。
every()open in new window检测数值元素的每个元素是否都符合条件。
fill()open in new window使用一个固定值来填充数组。
filter()open in new window检测数值元素,并返回符合条件所有元素的数组。
find()open in new window返回符合传入测试(函数)条件的数组元素。var ages = [3, 10, 18, 20];
function checkAdult(age) { return age >= 18; }
document.getElementById("demo").innerHTML = ages.find(checkAdult);
findIndex()open in new window返回符合传入测试(函数)条件的数组元素索引。
forEach()open in new window数组每个元素都执行一次回调函数。
from()open in new window通过给定的对象中创建一个数组。
includes()open in new window判断一个数组是否包含一个指定的值。let site = ['runoob', 'google', 'taobao']; site.includes('runoob'); // true
indexOf()open in new window搜索数组中的元素,并返回它所在的位置。var fruits = ["Banana", "Orange", "Apple", "Mango"];
var a = fruits.indexOf("Apple");
isArray()open in new window判断对象是否为数组。
join()open in new window把数组的所有元素用同一个分隔字符串连接起来,放入一个新的字符串里。var fruits = ["Banana", "Orange", "Apple", "Mango"];
var energy = fruits.join(" ");
//Banana Orange Apple Mango
keys()open in new window返回数组的可迭代对象,包含原始数组的键(key)。
lastIndexOf()open in new window搜索数组中的元素,并返回它最后出现的位置。
map()open in new window通过指定函数处理数组的每个元素,并返回处理后的数组。
pop()open in new window删除数组的最后一个元素并返回删除的元素。
push()open in new window向数组的末尾添加一个或更多元素,并返回新的长度。var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.push("Kiwi")
reduce()open in new window将数组元素计算为一个值(从左到右)。
reduceRight()open in new window将数组元素计算为一个值(从右到左)。
reverse()open in new window反转数组的元素顺序。var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.reverse();
//Mango,Apple,Orange,Banana
shift()open in new window删除并返回数组的第一个元素。
slice()open in new window选取数组的一部分,并返回一个新数组。var fruits = ["Banana", "Orange", "Lemon", "Apple", "Mango"];
var citrus = fruits.slice(1,3);
//Orange,Lemon
some()open in new window检测数组元素中是否有元素符合指定条件。
sort()open in new window对数组的元素进行排序。
如果调用该方法时没有使用参数,将按照字典序进行排序。
var arr=[10,5,40,25,1000,1];
function sortNumber(a,b) { return a - b }
document.write(arr.sort(sortNumber))
splice()open in new window从数组中添加或删除元素。
toString()open in new window把数组转换为字符串,并返回结果。fruits.toString();
unshift()open in new window向数组的开头添加一个或更多元素,并返回新的长度。var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.unshift("Lemon","Pineapple");
//Lemon,Pineapple,Banana,Orange,Apple,Mango
valueOf()open in new window返回数组对象的原始值。var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.splice(2,0,"Lemon","Kiwi");
//Banana,Orange,Lemon,Kiwi,Apple,Mango
//splice(index,howmany,item1,.....,itemX)

数组的迭代方法

以下迭代方法里都需要传入一个参数,这个参数是一个函数,这个函数则有三个参数,分别为:

  • 数组当前项的值;
  • 数组当前项的索引;
  • 数组对象本身;

三个参数顺序是固定的,不可以调整。这三个参数不是让你来调用的,而是解释过程中解释器提供的,因此可以把这些参数当成是本次循环产生的数据拿来用,例如:

var txt = "";
var numbers = [45, 4, 9, 16, 25];
numbers.forEach(myFunction);//forEach用于遍历数组

function myFunction(value, index, array) {
  txt = txt + value + "<br>"; 
}

数组的迭代方法都是传入这样的函数。有如下几个方法:

  • forEach:循环遍历数组的每一个元素,并执行方法

  • every: 循环在第一次 return false 后返回

  • some: 循环在第一次 return true 后返回

  • filter: 返回一个新的数组,该数组内的元素满足回调函数,例如:

    function myFunction(value) {return value > 18;}
    
  • map: 返回一个新的数组,将原数组中的元素处理后再返回

  • reduce: 对数组中的元素依次处理,将上次处理结果作为下次处理的输入,最后得到最终结果。

以下的例子将处理数组的数据,得到的新数组为原来数组每个值都乘以2:

var numbers1 = [45, 4, 9, 16, 25];
var numbers2 = numbers1.map(myFunction);

function myFunction(value, index, array) {
  return value * 2;
}

函数

在C语言中,我们学习了函数的声明与定义、以及函数的调用:

//声明
函数返回数据类型 函数名(参数数据类型1,参数数据类型2); 
//定义
函数返回数据类型 函数名(参数数据类型1 参数1,参数数据类型2 参数2){
    /**/
    return 函数返回值
}

//调用
a=函数名(b,c);

C语言里,函数的返回值必须按照指定数据类型,传入的参数个数固定、也必须按照指定的数据类型;但是在JavaScript中,函数既有传入参数可以缺省,又有返回类型可以不固定的特点;而声明与定义时也不需要指定返回值数据类型。

在C语言中,函数只能作为指引传值给指针;而JavaScript中,函数可以作为值传给变量!

在JavaScript里,函数既可以被广义地认为是一种数据类型,而事实上又是一种对象,这也是JavaScript与C语言的最大区别。

函数的声明与定义

以下3种方式都可以声明与定义函数

//函数声明创建函数
function 函数名(参数1,参数2) {
  /*执行的代码*/
}
//函数表达式创建函数
var 函数名 = function([形参1,形参2,...,形参N]) {
    /*执行的代码*/
}
//使用对象方式生成函数
var 函数名 = new Function("a", "b", "return a * b");

函数的参数

与C语言一样,JavaScript的函数的参数都是形式参数。与C语言参数的值传递和地址传递相似的,参数分为值与对象两种。

值传递:在函数中调用的参数是函数的形式参数。函数仅仅只是获取值。如果函数修改参数的值,不会修改实际参数的初始值(在函数外定义)。形式参数的改变在函数外是不可见的。

对象传递:函数可以传入对象,相当于引用对象的地址。因此我们在函数内部修改对象的属性就会修改其初始的值。修改对象属性可作用于函数外部(全局变量)。修改对象属性在函数外是可见的。

函数只定义了形式参数的名称和个数,对于传入的参数数据类型没有进行检测。

函数的调用

函数的调用方式与C语言相似,采用函数名(参数);的方式进行调用。

调用时,解析器也不会检查实参的数量,因此可以不填满所有的参数,可以只传入部分参数;也可以填入更多的参数。没有对应实参的形参将是undefined,而多余实参不会被赋值。

函数返回值

与C语言一样,都是使用return来返回值。

如果用if分支结构,返回值的类型甚至可以不一样!

函数返回值还可以是一个函数,这将在以后的函数柯里化里讲到。

对象

在JavaScript里,对象既是一种数据类型,又是一种数据结构,甚至可以说JavaScript的所有类型都是对象。

对象的字面量形式和C语言的哈希表有所相似,都是用一个字符型的键名去引用一个类型。与哈希表只能固定对象类型不同的是,对象的键值类型是多样的,包括数值、字符串等,甚至还包括对象还有函数!

请注意,对象和所谓的“类”有区别,对象是类的一个实例,而类是对象的抽象。我们这里只讨论“对象”这种结构。

对象的声明

花括号{}用于声明一个JavaScript对象。由于对象可以当作Object类的一个实例,所以可以采用Object类的实例化的方法去构建一个对象。

var object1={};
var object1=new Object();

对象的定义

对象包括了属性和方法两个部分。属性即是键值对,键值对通常写法为 name : value (键与值以冒号分割)。

//字面量
var car = {name:"Fiat", model:500, color:"white"};
//使用Object的方法构造
var myFather=new person("John","Doe",50,"blue");
//使用Object属性定义
var person=new Object();
person.firstname="John";
person.lastname="Doe";
person.age=50;
person.eyecolor="blue";
方法的定义
//字面量
var person = {
    firstName: "John",
    lastName : "Doe",
    id : 5566,
    fullName : function() 
	{
       return this.firstName + " " + this.lastName;
    }
};
//使用Object方法定义
...
person.showName = function(){
	alert("姓名:"+this.name);
}
person.showAge = function(){
	alert("年龄:"+this.age);
}
新属性、方法的添加

使用Object的定义方法就可以为对象添加属性。

对象属性方法的访问与调用

直接访问,或者将属性名作为字符串以数组类似的方式访问。

采用[]的方式访问的优点是,当你的属性名是一连串的序列时,可以采用for循环进行遍历;也可以进行动态地获取数据。

person.lastName;
person["lastName"];
方法的调用

方法可以作为属性被调用,也可以作为方法被调用。

document.write("不加括号输出函数表达式:"  + person.fullName);
document.write("加括号输出函数执行结果:"  +  person.fullName();)
//不加括号输出函数表达式:function() { return this.firstName + " " + this.lastName; }
//加括号输出函数执行结果:John Doe

关于类与对象构造器的知识请关注后续章节的内容

参考资料:

上次编辑于:
贡献者: XiLaiTL