引用类型:
今天,我们来讲一讲引用类型,
其实,在ECMAScript
中,引用类型是一种数据结构,用于将数据和功能组织在一起,因为他们描述的是一类对象所具有的属性和方法。
对于对象的创立,可以使用 new 操作符后跟一个构造函数来创建。构造函数本身就是函数,只不过该函数是出于创建新对象的目的而定义的。
var person = new Object();
对于这段代码,创建了 Object 引用类型的一个新实例,然后把该实例保存在了变量 person 中。
接下来,我将会一个一个的讲解引用类型中都有哪些知识点:
(1) Object 类型
到目前为止,我们看到的大多数引用类型值都是 Object 类型的实例
创建Object实例两种方法:
1. var person = new Object();
2 var person = {};
(2) Array 类型
对于 ECMAScript来说,Array 类型和其他语言中的数组类型差别还是比较大的,比如,ECMAScript中,数组每一项可以保存任何类型的数据,而且数组可以动态调整大小。
创建数组的方式有两种:
1. var colors = new Array();
2. var colors = [];
数组最后一项的索引始终是 length-1;
(一)、检测数组
可是,有一个问题,怎么样检测某个对象是不是数组呢?
可以使用 instanceof 来解决,value instanceof Array ,不过 instanceof 有一个问题:
如果网页中有多个框架,即存在多个全局作用域,从而存在多个不同版本的 Array 构造函数,如果从一个框架向另一个框架传入数组,那么传入的数组与在第二个框架中原生创建的数组分别具有各自不同的构造函数。
为了解决这个问题,ECMAScript5 新增 Array.isArray()方法,不过这个方法只支持 IE9+
所以,有个完美解决方案:
function isArray(value){
return Object.prototype.toString.call(value) == '[object Array]';
}
(二)、转换方法
toString()、toLocaleString()、valueOf()、join()
(三)、栈方法
Ecmascript提供的栈是一种 last-in-first-out 后进先出的数据结构,也就是最新添加的项最早被移除,栈中项的插入和移除,只发生在栈的顶部。
所以,提供了两种方法:
push():接收任意数量参数,并逐个添加到数组末尾,并返回修改后数组的长度;
pop():从数组末尾移除最后一项,减少数组的length值,然后返回移除的项;
(四)、队列方法
队列数据结构的访问规则是 first-in-first-out ,先进先出,在列表的末尾添加项,在列表的前端移除项
提供了shift方法
shift(): 移除数组中第一项,并返回该项,同时将数组长度减1
unshift(): 在数组前端添加任意个项,并返回新数组的长度
(五)、重排序方法
reverse():倒序排列
sort(): 升序排列,sort() 会调用每个数组项的 toString() 方法,然后比较得到的字符串,以确定如何排序,即使数组中的每一项都是数值,sort() 方法比较的也是字符串。
var values = [0,1,5,10,15];
values.sort();
alert(values) ==> 0,1,10,15,5
sort()比较的事字符串,所以这个方法有问题,解决方案:
接收一个compare()比较函数
function compare(value1, value2){
if ( value1 < value2 ){
return -1;
} else if ( value1 > value2 ){
return 1;
} else {
return 0;
}
}
var values = [0,1,5,10,15];
values.sort(compare);
alert(values) ==> 0,1,5,10,15
(六)、操作方法
concat(): 先创建当前数组一个副本,然后将接收到的参数添加到这个副本的末尾,最后返回新构建的数组
slice(a,b):返回数组中a到b的元素
如果a或b是一个负数,则用数组长度加上该数来确定相应的位置
splice() 很强大,大家可以自己了解。
(七)、位置方法
indexOf()和lastIndexOf() --> 直有IE9+才支持
都接收两个参数,要查找的项和表示查找起点位置的索引(可选)
(八)、迭代方法
var numbers = [1,2,3,4,5,6,3,4,5,6];
- every():该函数每一项都返回true,则返回true
var flag = numbers.every(function(item, index, array){
return (item > 2)
})
- filter():返回该函数会返回true的项组成的数组
var flag = numbers.filter(function(item, index, array){
return (item > 2)
})
forEach()
map()
some()
(九)、归并方法
reduce()和reduceRight()
接收两个参数:一个在每一项上调用的函数和(可选的)作为归并基础的初始值。
传给reduce()和reduceRight()的函数接收4个参数:前一个值、当前值、项的索引、数组对象。
var values = [1,2,3,4,5];
var sum = values.reduce(function(prev, cur, index, array){
return prev + cur;
})
这个函数返回的任何值都会作为第一个参数自动传给下一项。
(5) Function 类型
在ECMAScript中,函数实际上是对象,每个函数都是Function类型的实例,而且都和其他引用类型一样具有属性和方法。由于函数是对象,因此函数名实际上也是一个指向函数对象的指针,不会与某个函数绑定。
- 没有重载
将函数名想象为指针,就会理解了为啥没有重载的概念。
function addSome(num){
return num + 100;
}
function addSome(num){
return num + 200;
}
var result = addSome(100) ==> 300
函数声明与函数表达式
函数声明提升作为值的函数
函数内部属性
arguments,this
arguments主要用途是保存函数参数,它还有一个叫callee的属性,该属性是一个指针,指向拥有这个arguments对象的函数。
- 函数属性和方法
length 和 prototype
function sum(num1, num2){
return num1 + num2;
}
sum.length ==> 2
每个函数都包含两个非继承而来的方法:apply()和call(),两个方法都是在特定的作用域中调用函数,实际上等于设置函数体内this对象的值。
apply()接收两个参数:一个是在其中运行函数的作用域,另一个是参数数组
function sum(num1, num2){
return num1 + num2;
}
function callSum1(num1, num2){
console.log(arguments)
return sum.apply(this, arguments);
}
function callSum2(num1, num2){
return sum.apply(this, [num1, num2]);
}
alert(callSum1(10,10))
call()和apply()作用相同,区别仅仅在于接收参数的方式不同。call()的第二个参数必须逐个列举出来。
function sum(num1, num2){
return num1 + num2;
}
function callSum(num1, num2){
return sum.call(this, num1, num2);
}
alert(callSum(10,10))
call()和apply()到底用哪一个,取决于你采取哪种给函数传递参数最方便。
他两的最大作用,是能够扩充函数赖以运行的作用域。
window.color = "red";
var o = { color: "blue" };
function sayColor(){
alert(this.color);
}
sayColor.call(this) ==> "red"
sayColor.call(o) ==> "blue"
(6)、基本包装类型
Boolean、Number、String
实际上,每读取一个基本类型值时,后台就会创建一个对应的基本包装类型对象,从而让我们能够调用一些方法来操作这些数据。
引用类型和基本包装类型的主要区别就在于对象的生存期。使用 new 操作符创建的引用类型的实例,在执行流离开当前作用域之前都一直保存在内存中。而自动创建的基本包装类型的对象,则只存在于一行代码的执行瞬间,然后立即被销毁。