数组、对象和函数
数组、对象和函数
在本节中我们将学习有关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语言极大的不同是,实现数组的一些操作例如排序等,不需要引入新的库函数,而是直接使用数组自带的方法。这样节省了传递参数的麻烦。
数组的属性
属性值 | 用法示例 | |
---|---|---|
length | 设置或返回数组元素的个数。 | myCars.length |
prototype | 允许你向数组对象添加属性或方法。 | |
constructor | 返回创建数组对象的原型函数。 |
数组的方法
数组的方法主要实现一些与数组内值、索引等有关的操作。
例如:
得到尾部元素并删除:pop(),
尾部添加元素push("el");
得到头部元素并删除:shift(),
头部添加元素unshift("el");
主要记住提供用法示例的几个方法。
方法名 | 用法示例 | |
---|---|---|
concat() | 连接两个或更多的数组,并返回结果。 | var hege = ["Cecilie", "Lone"]; var stale = ["Emil", "Tobias", "Linus"]; var kai = ["Robin"]; var children = hege.concat(stale,kai); |
copyWithin() | 从数组的指定位置拷贝元素到数组的另一个指定位置中。 | |
entries() | 返回数组的可迭代对象。 | |
every() | 检测数值元素的每个元素是否都符合条件。 | |
fill() | 使用一个固定值来填充数组。 | |
filter() | 检测数值元素,并返回符合条件所有元素的数组。 | |
find() | 返回符合传入测试(函数)条件的数组元素。 | var ages = [3, 10, 18, 20]; function checkAdult(age) { return age >= 18; } document.getElementById("demo").innerHTML = ages.find(checkAdult); |
findIndex() | 返回符合传入测试(函数)条件的数组元素索引。 | |
forEach() | 数组每个元素都执行一次回调函数。 | |
from() | 通过给定的对象中创建一个数组。 | |
includes() | 判断一个数组是否包含一个指定的值。 | let site = ['runoob', 'google', 'taobao']; site.includes('runoob'); // true |
indexOf() | 搜索数组中的元素,并返回它所在的位置。 | var fruits = ["Banana", "Orange", "Apple", "Mango"]; var a = fruits.indexOf("Apple"); |
isArray() | 判断对象是否为数组。 | |
join() | 把数组的所有元素用同一个分隔字符串连接起来,放入一个新的字符串里。 | var fruits = ["Banana", "Orange", "Apple", "Mango"]; var energy = fruits.join(" "); //Banana Orange Apple Mango |
keys() | 返回数组的可迭代对象,包含原始数组的键(key)。 | |
lastIndexOf() | 搜索数组中的元素,并返回它最后出现的位置。 | |
map() | 通过指定函数处理数组的每个元素,并返回处理后的数组。 | |
pop() | 删除数组的最后一个元素并返回删除的元素。 | |
push() | 向数组的末尾添加一个或更多元素,并返回新的长度。 | var fruits = ["Banana", "Orange", "Apple", "Mango"]; fruits.push("Kiwi") |
reduce() | 将数组元素计算为一个值(从左到右)。 | |
reduceRight() | 将数组元素计算为一个值(从右到左)。 | |
reverse() | 反转数组的元素顺序。 | var fruits = ["Banana", "Orange", "Apple", "Mango"]; fruits.reverse(); //Mango,Apple,Orange,Banana |
shift() | 删除并返回数组的第一个元素。 | |
slice() | 选取数组的一部分,并返回一个新数组。 | var fruits = ["Banana", "Orange", "Lemon", "Apple", "Mango"]; var citrus = fruits.slice(1,3); //Orange,Lemon |
some() | 检测数组元素中是否有元素符合指定条件。 | |
sort() | 对数组的元素进行排序。 如果调用该方法时没有使用参数,将按照字典序进行排序。 | var arr=[10,5,40,25,1000,1]; function sortNumber(a,b) { return a - b } document.write(arr.sort(sortNumber)) |
splice() | 从数组中添加或删除元素。 | |
toString() | 把数组转换为字符串,并返回结果。 | fruits.toString(); |
unshift() | 向数组的开头添加一个或更多元素,并返回新的长度。 | var fruits = ["Banana", "Orange", "Apple", "Mango"]; fruits.unshift("Lemon","Pineapple"); //Lemon,Pineapple,Banana,Orange,Apple,Mango |
valueOf() | 返回数组对象的原始值。 | 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
关于类与对象构造器的知识请关注后续章节的内容
参考资料: