以下内容可能存在个人理解的部分,并非完全参照原文
如有疑问,请以书中内容为准
接着上一篇的内容
第五章 引用类型
对象是引用类型的实例
5.1 Object类型
用对象字面量表示法创建的是Object的实例
一般来说,访问对象属性时使用的都是点表示法。不过,在JavaScript当中也可以使用方括号来访问对象的属性。
方括号语法的优点是可以通过变量来访问属性,例如
var propertyName = "name";
alert(person[propertyName]);
5.2 Array类型
数组可以说是面试必问了
ECMAScript数组的每一项可以保存任何类型的数据,而且数组大小是可以动态调整的。
var colors = new Array();
var colors = new Array(20);
var colors = new Array("red","blue","green");
也可以省略new
操作符
var colors = Array(3);
var names = Array("Greg");
这里其实有一个问题,我们知道
new
会在这个函数的原型上构造一个对象,然后最后返回这个对象,那么这里的Array
函数究竟做了什么呢?为什么可用new
也可以不用
也可以用字面量表示法
var colors = ["red","blue","green"];
var names = [];
用方括号访问数组时,如果这个值存在则会返回对应项的值,如果是设置数组则会改变这个值
var colors = ["red","blue","green"];
alert(colors[0]);
colors[2] = "black";
colors[3] = "brown";
alert(colors); // red,blue,green,brown
如果值不存在则会扩充数组长度,并添加这个值
当把一个值放在超出当前数组大小的位置上时,数组就会重新计算其长度值
var colors = ["red","blue","green"];
colors[99] = "black";
alert(colors.length); // 100
中间生成的项会被设置为undefined
数组的length是可以被修改的
var colors = ["red","blue","green"];
colors.length = 2;
alert(colors[2]); // undefined
如果减少数组的length,那么多出来的项将会被移除
同理如果增加length,会在数组后新增项
检测数组
经典问题,被问过两次了
在一般情况下,使用instanceof
操作符就可以检测数组
但是instanceof
操作符假定只存在一个全局执行环境
如果网页中包含多个frame
,那么实际上就存在两个以上不同的全局执行环境,从而存在两个以上不同版本的Array构造函数。如果你从第一个frame
向另一个frame
传一个数组,那么传入的数组与在第二个框架中原生创建的数组分别具有各自不同的构造函数。
为了解决这个问题,ES5新增了Array.isArray()
方法可以判断一个值是不是数组,而不管它是在哪个全局环境中创建的。
还可以使用
Object.prototype.toString.call(value)
的方法检测数组
转换方法
所有对象都具有toLocaleString()
、toString()
和valueOf()
方法
这里的说法是否太绝对呢?暂且保留这个疑问
其中,调用valueOf()
返回的还是数组本身,而调用数组的toString()
方法会返回由数组中每个值调用toString()
并使用逗号分隔符拼接而成的字符串。
var colors = ["red","blue","green"];
alert(colors.toString()); // red,blue,green
alert(colors.valueOf()); // red,blue,green
alert(colors); // red,blue,green
由于alert()
要接受字符串参数,所以它会在后台调用toString()
方法
另外,toLocaleString()
方法经常也会返回与toString()
和valueOf()
方法相同的值
区别是,当数组调用toLocaleString()
方法时,它的每一项调用的是toLocaleString()
方法
数组继承的toLocaleString()
、toString()
方法在默认情况下都会以逗号分隔字符串的形式返回,而如果使用join()
方法,则可以使用不同的分隔符
var colors = ["red","green","blue"];
alert(colors.join(",")); // red,green,blue
alert(colors.join("||")); // red||green||blue
栈方法
栈是一种LIFO(Last-In-First-Out,后进先出)的数据结构,也就是最新添加的项最早被移除。
ECMAScript为数组专门提供了push()
和pop()
方法,以便实现类似栈的行为
push()
方法可以接收任意数量的参数,并把它们逐个添加到数组末尾,并返回修改后数组的长度。而pop()
方法则从数组末尾移除最后一项,减少数组的length值,然后返回移除的项。
var colors = new Array();
var count = colors.push("red","green");
alert(count); // 2
count = colors.push("black");
alert(count); // 3
var item = colors.pop();
alert(item); // "black"
alert(colors.length); // 2
队列方法
队列数据结构的访问规则是FIFO(First-In-First-Out,先进先出)。队列在列表的末端添加项,从列表的前端移除项。
shift()
方法能够移除数组中的第一项并返回该项,同时将数组长度减1
结合shift()
和push()
方法,可以像使用队列一样使用数组
var colors = new Array();
var count = colors.push("red","green");
alert(count); // 2
count = colors.push("black");
alert(count); // 3
var item = colors.shift();
alert(item); // "red"
alert(colors.length); // 2
ECMAScript还为数组提供了一个unshift()
方法,与shift()
用途相反:它能在数组前端添加任意个项并返回新数组的长度。因此,同时使用unshift()
和pop()
方法,可以从相反的方向来模拟队列。
重排序方法
数组当中存在两个可以直接用来重排序的方法:reverse()
和sort()
reverse()
方法会反转数组项的顺序
var values = [1,2,3,4,5];
values.reverse();
alert(values); // 5,4,3,2,1
在默认情况下,sort()
方法按升序排列数组项。为了实现排序,sort()
会调用每个数组项的toString()
方法,然后比较得到的字符串。
注意:即使数组的每一项都是数值,sort()
方法比较的也是字符串
var values = [0,1,5,10,15];
values.sort();
alert(values); //0,1,10,15,5
这样不是我们想要的结果。因此sort()
方法可以接收一个比较函数作为参数,以便我们指定哪个值位于哪个值前面。
function compare(value1,value2){
if(value1 < value2){
return -1; // value1位于value2前面
}else if( value1 > value2){
return 1; // value1位于value2后面
}else{
return 0;
}
}
reverse()
和sort()
方法返回的是排序后的数组
对于数值类型或其valueOf()
方法会返回数值类型的对象类型,可以使用一个更简单的比较函数。
function compare(value1,value2){
return value2 - value1;
}
操作方法
concat()
方法会创建当前数组的一个副本,然后将接收到的参数添加到这个副本的末尾,最后返回新构建的数组。
var colors = ["red","green","blue"];
var colors2 = colors.concat("yellow",["black","brown"]);
alert(colors); // red,green,blue
alert(colors2); // red,green,blue,yellow,black,brown
slice()
方法能够基于当前数组中的一或多个项创建一个新数组。slice()
方法可以接受一或两个参数,即要返回项的起始和结束位置。
var colors = ["red","green","blue"]
var colors2 = colors.slice(1);
var colors3 = colors.slice(1,4);
alert(colors2); // green,blue,yellow,purple
alert(colors3); // green,blue,yellow
如果
slice()
方法的参数中有一个负数,则用数组长度加上该数来确定相应的位置。如果结束位置小于起始位置,则返回空数组。
splice()
方法有很多种使用方式:
- 删除:传入要删除的第一项的位置和要删除的项数。如
splice(0,2)
。 - 插入:传入起始位置、0(删除0项)和要插入的项。如
splice(2,0,"red")
。 - 替换:传入起始位置、要删除的项数和插入项。如
splice(2,1,"red")
。
splice()
方法始终会返回一个数组,为从原始数组中删除的项(没有则返回空数组)。
位置方法
ES5添加了两个位置方法:indexOf()
和lastIndexOf()
indexOf()
从数组开头开始查找,lastIndexOf()
方法从数组末尾向前查找
两个方法都返回要查找的项在数组中的位置,没找到则返回-1。
在比较时会使用全等操作符
迭代方法
ES5为数组定义了5个迭代方法。每个方法都接收两个参数:要在每一项上运行的函数和运行该函数的作用域对象(可选)。
什么时候需要传入作用域对象呢?
-
every()
:对数组中的每一项运行给定函数,如果函数对每一项都返回true
,则返回true
-
filter()
:返回该函数 -
forEach()
:对数组中的每一项运行给定函数,没有返回值 -
map()
:返回每次函数调用的结果组成的数组 -
some()
:如果函数对任一项返回true
,则返回true
传入的函数会接收三个参数:数组项的值、该项在数组中的位置和数组本身。
这一般会在forEach()
中用到
var numbers = [1,2,3,4,5,6,1,2,3];
numbers.forEach(function(item,index){
//do something
});
归并方法
ES5还新增了两个归并数组的方法:reduce()
和reduceRight()
reduce()
是从左到右遍历数组,reduceRight()
是从右到左
这两个方法都接收两个参数:一个在每一项上调用的函数和作为归并基础的初始值(可选)。
传入的函数接收4个参数:前一个值、当前值、项的索引和数组对象。
var values = [1,2,3,4,5];
var sum = values.reduce(function(prev,cur,index){
return prev + cur;
})
这里第一次执行prev
是1,cur
是2,也就是说没有默认值时第一项被当成了默认值
别问我怎么知道的,试出来的