引用类型是一种数据结构,用于将数据和功能组织在一起。有时,引用类型也被称为类,但是这种说法其实不太准确:尽管ECMAScript从技术上讲是一门面向对象的语言,但是它并不具有传统的面向对象语言所支持的类的借口等基本结构。也就是说,引用类型和类,并不是同一个概念。
1、object类型:
两种定义方式:
var person = new Object();
person.name = "Nicholas";
person.age = 29;
var person = {
name : "Nicholas",
age : 29
};
第二种定义方式需要注意,在最后一个属性的后面不可以加上逗号,否则,会在IE7和Opera中导致错误。
对于上述对象属性的访问,也有如下两种方式:
alert(person["name"]); //"Nicholas"
alert(person.name); //"Nicholas"
方括号的优点是可以通过变量访问属性:
var propertyName = "name";
alert(person[propertyName]); //"Nicholas"
但是,除非必须使用变量来访问属性,否则我们建议使用点表示法。
2、Array类型:
创建数组的方式:
var colors = new Array();
var colors = new Array(20);
var colors = new Array("red", "blue", "green");
var values = [1,2,];//不要这样创建,在不同浏览器中,会创建出不同长度的数组
数组的length属性可以返回数组的长度,而且它有一个很有趣的特点:它不是只读的。通过设置这个属性,可以为数组增加或删除元素,新增的元素就是undefined。
var colors = ["red", "blue", "green"];
colors.length = 4;
alert(colors[3]); //undefined
判断一个变量是否为数组的方法:
var value = new Array();
if (value instanceof Array){
// 对数组的操作
}
然而该方法存在一个问题:它假定只有一个全局环境。但是如果网络包含多个框架,那实际上就存在两个以上不同的全局执行环境,从而存在多个不同版本的Array构造函数。
为了解决这个问题,还新增了方法:Array.isArray()
if (Array.isArray(value)){
// 对数组的操作
}
支持这个方法的浏览器有:IE9+、Firefox 4+、Safari 5+、Opera 10.5+和Chrome。
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()方法相同的值。
var person1 = {
toLocaleString : function () {
return "Nikolaos";
},
toString : function() {
return "Nicholas";
} };
var person2 = {
toLocaleString : function () {
return "Grigorios";
},
toString : function() {
return "Greg";
} };
var people = [person1, person2];
alert(people);
alert(people.toString());
alert(people.toLocaleString());
//Nicholas,Greg
//Nicholas,Greg
//Nikolaos,Grigorios
另外,数组还有join函数
var colors = ["red", "green", "blue"];
alert(colors.join(",")); //red,green,blue
alert(colors.join("||")); //red||green||blue
注:如果数组中的某一项为空或者未定义undefined,那么上述几个函数返回的结果将以空字符串表示。
堆栈方法和队列方法:
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);
var colors = new Array();
colors.unshift("red", "green");//在数组前端添加项
alert(count); //2
count = colors.unshift("black");
alert(count); //3
var item = colors.pop();
alert(item); //"green"
alert(colors.length); //2
重排序方法:
var values = [1, 2, 3, 4, 5];
values.reverse();
alert(values); //5,4,3,2,1
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;
} 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
数组的迭代方法:
var numbers = [1,2,3,4,5,4,3,2,1];
var everyResult = numbers.every(function(item, index, array){
return (item > 2);
});
alert(everyResult); //false
var someResult = numbers.some(function(item, index, array){
return (item > 2);
});
alert(someResult); //true
var numbers = [1,2,3,4,5,4,3,2,1];
var filterResult = numbers.filter(function(item, index, array){
return (item > 2);
});
alert(filterResult);//[3,4,5,4,3]
var numbers = [1,2,3,4,5,4,3,2,1];
var mapResult = numbers.map(function(item, index, array){
return item * 2;
});
alert(mapResult); //[2,4,6,8,10,8,6,4,2]
var numbers = [1,2,3,4,5,4,3,2,1];
numbers.forEach(function(item, index, array){
// 执行某些操作
});
数组的归并方法:
支持该方法的浏览器包括:IE9+ Firefox 3+ Safari 4+ Opera 10.5和Chrome。
var values = [1,2,3,4,5];
var sum = values.reduce(function(prev, cur, index, array){
return prev + cur;
});
alert(sum); //15
3、Date类型:
var now = new Date();
var someDate = new Date(Date.parse("May 25, 2004"));// 接受一个表示日期的字符串参数,然后根据这个字符串返回相应日期的毫秒数。
var allFives = new Date(Date.UTC(2005, 4, 5, 17, 55, 55));// 2005年5月5日下午5:55:55。注意这里是5月,因为1月对应的是数字零。
var start = Date.now();// 返回当前时间
不同浏览器返回的函数值不同:
Internet Explorer 8
toLocaleString() Thursday, February 01, 2007 12:00:00 AM toString() Thu Feb 1 00:00:00 PST 2007
Firefox 3.5
toLocaleString() Thursday, February 01, 2007 12:00:00 AM
toString() Thu Feb 01 2007 00:00:00 GMT-0800 (Pacific Standard Time)
Safari 4
toLocaleString() Thursday, February 01, 2007 00:00:00
toString() Thu Feb 01 2007 00:00:00 GMT-0800 (Pacific Standard Time)
Chrome 4
toLocaleString() Thu Feb 01 2007 00:00:00 GMT-0800 (Pacific Standard Time)
toString() Thu Feb 01 2007 00:00:00 GMT-0800 (Pacific Standard Time)
Opera 10
toLocaleString() 2/1/2007 12:00:00 AM
toString() Thu, 01 Feb 2007 00:00:00 GMT-0800
4、RegExp类型
ECMAScript通过RegExp类型支持正则表达式。
var expression = / pattern / flags ;
flag:
g:表示全局模式,即模式会被用于所有字符串,而非在发现第一个字符串后立即停止。
i:不区分大小写。
m:多行模式。
栗子:
var pattern1 = /at/g; //匹配所有带at的字符串。
var pattern2 = new RegExp("at", "i"); // 另一种创建方式。
两种方法的区别:
var re = null,
var i;
for (i=0; i < 10; i++){
re = /cat/g;
re.test("catlikefish");
}
for (i=0; i < 10; i++){
re = new RegExp("cat", "g");
re.test("catlikefish");
}
第一种方式中,只会为cat创建一个实例,实例的属性不会重置,因此第二次调用test的时候会失效。
第二种方式,每次都创建一个新的实例,因此test总可以返回正确的值。
实例方法:
var text = "mom and dad and baby";
var pattern = /mom( and dad( and baby)?)?/gi;
var matches = pattern.exec(text);
alert(matches.index); //0
alert(matches.input); //mom and dad and baby
alert(matches[0]);//mom and dad and baby
alert(matches[1]);//and dad and baby
alert(matches[2]);//and baby
var text = "cat, bat, sat, fat";
var pattern1 = /.at/;
var matches = pattern1.exec(text);
alert(matches.index); //0
alert(matches[0]); //cat
alert(pattern1.lastIndex); //0
matches = pattern1.exec(text);
alert(matches.index); //0
alert(matches[0]); //cat
alert(pattern1.lastIndex); //0
var pattern2 = /.at/g;
var matches = pattern2.exec(text);
alert(matches.index); //0
alert(matches[0]); //cat
alert(pattern2.lastIndex); //3
matches = pattern2.exec(text);
alert(matches.index); //5
alert(matches[0]); //bat
alert(pattern2.lastIndex); //8
5、Function类型
Function是JavaScript最精彩的部分!
// 定义方法1、2
function sum (num1, num2) {
return num1 + num2;
}
var sum = function(num1, num2){
return num1 + num2;
};
// 函数名仅仅是指向函数的指针。
function sum(num1, num2){
return num1 + num2;
}
alert(sum(10,10)); //20
var anotherSum = sum;
alert(anotherSum(10,10)); //20
sum = null;
alert(anotherSum(10,10)); //20
js函数不重载,后写的函数会覆盖前面的函数。
// 正常运行
alert(sum(10,10));
function sum(num1, num2){
return num1 + num2;
}
// 出现错误
alert(sum(10,10));
var sum = function(num1, num2){
return num1 + num2;
};
函数可以作为参数!
function callSomeFunction(someFunction, someArgument){
return someFunction(someArgument);
}
function add10(num){
return num + 10;
}
var result1 = callSomeFunction(add10, 10);
alert(result1); //20
function getGreeting(name){
return "Hello, " + name;
}
var result2 = callSomeFunction(getGreeting, "Nicholas");
alert(result2); //"Hello, Nicholas"
同时,这也就意味着,函数也可以作为返回值!
function createComparisonFunction(propertyName) {
return function(object1, object2){
var value1 = object1[propertyName];
var value2 = object2[propertyName];
if (value1 < value2){
return -1;
} else if (value1 > value2){
return 1;
}else{
return 0;
}
};
}
函数的内部属性:
在函数内部,有两个特殊的对象,arguments和this。
关于arguments的用法,虾面两段代码是一样的:
function factorial(num){
if (num <=1) {
return 1;
} else {
return num * factorial(num-1)
}
}
function factorial(num){
if (num <=1) {
return 1;
} else {
return num * arguments.callee(num-1)
}
}
后面这个函数的好处是,在函数内部没有出现函数名factorial,这样修改函数名会变得方便。