《Javascript 高级程序设计(第三版)》笔记0x6 引用类型(1)
目录
引用类型的值(对象)是引用类型的一个实例。在 ECMAScript 中, 引用类型是一种数据结构,用于将数据和功能组织在一起。不能称作类,它不具备传统的面向对象语言所支持的类和接口等基本结构。引用类型有时候也被称为对象定义,因为它们描述的是一类对象所具有的属性和方法。
var person = new Object();
/*
* 这行代码创建了 Object 引用类型的一个新实例,然后把该实例保存在了变量 person 中。使用
* 的构造函数是 Object,它只为新对象定义了默认的属性和方法。
*/
Object类型
//new 操作符后跟 Object 构造函数
var person = new Object();
person.name = "Nicholas";
person.age = 29;
//对象字面量表示法
var person = {
name : "Nicholas",
age : 29
};
var person = {//属性可用字符串,数字会自动转字符串
"name" : "Nicholas",
"age" : 29,
5 : true
};
var person = {}; //与 new Object()相同
person.name = "Nicholas";
person.age = 29;
function displayInfo(args) {
var output = "";
if (typeof args.name == "string"){
output += "Name: " + args.name + "\n";
}
if (typeof args.age == "number") {
output += "Age: " + args.age + "\n";
}
alert(output);
}
displayInfo({
name: "Nicholas",
age: 29
});
displayInfo({
name: "Greg"
});
//使用方括号表示法来访问对象的属性
alert(person["name"]); //"Nicholas"
alert(person.name); //"Nicholas"
var propertyName = "name";//方括号语法的主要优点是可以通过变量来访问属性
alert(person[propertyName]); //"Nicholas"
//如果属性名中包含会导致语法错误的字符,或者属性名使用的是关键字或保留字,也可以使用方括号表示法。
person["first name"] = "Nicholas";
Array 类型
ECMAScript 数组的每一项可以保存任何类型的数据,大小是可以动态调整的,即可以随着数据的添加自动增长以容纳新增数据。
//使用 Array 构造函数创建数组
var colors = new Array();
var colors = new Array(20);
var colors = new Array("red", "blue", "green");
var colors = Array(3); // 创建一个包含 3 项的数组
var names = Array("Greg"); // 创建一个包含 1 项,即字符串"Greg"的数组
//数组字面量表示法创建数组
var colors = ["red", "blue", "green"]; // 创建一个包含 3 个字符串的数组
var names = []; // 创建一个空数组
var values = [1,2,]; // 不要这样!这样会创建一个包含 2 或 3 项的数组
var options = [,,,,,]; // 不要这样!这样会创建一个包含 5 或 6 项的数组
//读取和设置数组
var colors = ["red", "blue", "green"]; // 定义一个字符串数组
alert(colors[0]); // 显示第一项
colors[2] = "black"; // 修改第三项
colors[3] = "brown"; // 新增第四项
//数组项数
var colors = ["red", "blue", "green"]; // 创建一个包含 3 个字符串的数组
var names = []; // 创建一个空数组
alert(colors.length); //3
alert(names.length); //0
//利用设置数组项数删除末尾项
var colors = ["red", "blue", "green"]; // 创建一个包含 3 个字符串的数组
colors.length = 2;
alert(colors[2]); //undefined
var colors = ["red", "blue", "green"]; // 创建一个包含 3 个字符串的数组
colors.length = 4;
alert(colors[3]); //undefined
//利用 length 属性也可以方便地在数组末尾添加新项
var colors = ["red", "blue", "green"]; // 创建一个包含 3 个字符串的数组
colors[colors.length] = "black"; //(在位置 3)添加一种颜色
colors[colors.length] = "brown"; //(在位置 4)再添加一种颜色
数组最多可以包含 4 294 967 295 个项。
检测数组
//确定某个对象是不是数组,假定只有一个全局执行环境
if (value instanceof Array){
//对数组执行某些操作
}
//最终确定某个值到底是不是数组,而不管它是在哪个全局执行环境中创建的。
if (Array.isArray(value)){
//对数组执行某些操作
}
转换方法
toString(),valueOf()
var colors = ["red", "blue", "green"]; // 创建一个包含 3 个字符串的数组
alert(colors.toString()); // red,blue,green
alert(colors.valueOf()); // red,blue,green
alert(colors); // red,blue,green
toLocaleString()
//调用了数组每一项的toLocaleString()方法
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); //Nicholas,Greg
alert(people.toString()); //Nicholas,Greg
alert(people.toLocaleString()); //Nikolaos,Grigorios
join()
//用 join()方法重现了 toString()方法的输出
var colors = ["red", "green", "blue"];
alert(colors.join(",")); //red,green,blue
alert(colors.join("||")); //red||green||blue
如果数组中的某一项的值是 null 或者 undefined,那么该值在 join()、toLocaleString()、 toString()和 valueOf()方法返回的结果中以空字符串表示。
栈方法
栈是一种 LIFO(Last-In-First-Out,后进先出)的数据结构
push(),pop()
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,先进先出)
push(),shift(),unshift()
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
//unshift()与 shift()的用途相反:它能在数组前端添加任意个项并返回新数组的长度。
var colors = new Array(); //创建一个数组
var count = 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
重排序方法
reverse()
//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进行字符串比较时, "10"则位于"5"的前面
//比较函数
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()
//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", "yellow", "purple"];
var colors2 = colors.slice(1);
var colors3 = colors.slice(1,4);
alert(colors2); //green,blue,yellow,purple
alert(colors3); //green,blue,yellow
如果 slice()方法的参数中有一个负数,则用数组长度加上该数来确定相应的位置。例如,在一个包含 5 项的数组上调用 slice(-2,-1)与调用 slice(3,4)得到的结果相同。如果结束位置小于起始位置,则返回空数组。
splice()
var colors = ["red", "green", "blue"];
var removed = colors.splice(0,1); // 删除第一项
alert(colors); // green,blue
alert(removed); // red,返回的数组中只包含一项
removed = colors.splice(1, 0, "yellow", "orange"); // 从位置 1 开始插入两项
alert(colors); // green,yellow,orange,blue
alert(removed); // 返回的是一个空数组
removed = colors.splice(1, 1, "red", "purple"); // 插入两项,删除一项
alert(colors); // green,red,purple,orange,blue
alert(removed); // yellow,返回的数组中只包含一项
位置方法
indexOf()、lastIndexOf()
//全等操作符
var numbers = [1,2,3,4,5,4,3,2,1];
alert(numbers.indexOf(4)); //3
alert(numbers.lastIndexOf(4)); //5
alert(numbers.indexOf(4, 4)); //5
alert(numbers.lastIndexOf(4, 4)); //3
var person = { name: "Nicholas" };
var people = [{ name: "Nicholas" }];
var morePeople = [person];
alert(people.indexOf(person)); //-1
alert(morePeople.indexOf(person)); //0
迭代方法
every():
//every():对数组中的每一项运行给定函数,如果该函数对每一项都返回 true,则返回 true。
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
filter()
//filter():对数组中的每一项运行给定函数,返回该函数会返回 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]
forEach()
//forEach():对数组中的每一项运行给定函数。这个方法没有返回值。
var numbers = [1,2,3,4,5,4,3,2,1];
numbers.forEach(function(item, index, array){
//执行某些操作
});
map()
//map():对数组中的每一项运行给定函数,返回每次函数调用的结果组成的数组。
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]
some()
//some():对数组中的每一项运行给定函数,如果该函数对任一项返回 true,则返回 true。
var numbers = [1,2,3,4,5,4,3,2,1];
var someResult = numbers.some(function(item, index, array){
return (item > 2);
});
alert(someResult); //true
归并方法
这个函数返回的任何值都会作为第一个参数自动传给下一项。第一次迭代发生在数组的第二项上,因此第一个参数是数组的第一项,第二个参数就是数组的第二项。
reduce()
//reduce()
var values = [1,2,3,4,5];
var sum = values.reduce(function(prev, cur, index, array){
return prev + cur;
});
alert(sum); //15=(((1+2)+3)+4)+5
reduceRight()
//reduceRight()
var values = [1,2,3,4,5];
var sum = values.reduceRight(function(prev, cur, index, array){
return prev + cur;
});
alert(sum); //15=(((5+4)+3)+2)+1
Date类型
ECMAScript 中的 Date 类型是在早期 Java 中的 java.util.Date 类基础上构建的。为此, Date类型使用自 UTC (Coordinated Universal Time,国际协调时间) 1970 年 1 月 1 日午夜(零时)开始经过的毫秒数来保存日期。在使用这种数据存储格式的条件下, Date 类型保存的日期能够精确到 1970 年 1月 1 日之前或之后的 285 616 年。
//创建时间对象
var now = new Date();
Date.parse()
//Date.parse()方法接收一个表示日期的字符串参数,然后尝试根据这个字符串返回相应日期的毫秒数。
var someDate = new Date(Date.parse("May 25, 2004"));//美国
var someDate = new Date("May 25, 2004");
Date.UTC()
//Date.UTC()方法同样也返回表示日期的毫秒数
/ GMT 时间 2000 年 1 月 1 日午夜零时
var y2k = new Date(Date.UTC(2000, 0));
// GMT 时间 2005 年 5 月 5 日下午 5:55:55
var allFives = new Date(Date.UTC(2005, 4, 5, 17, 55, 55));
// 本地时间 2000 年 1 月 1 日午夜零时
var y2k = new Date(2000, 0);
// 本地时间 2005 年 5 月 5 日下午 5:55:55
var allFives = new Date(2005, 4, 5, 17, 55, 55);
Data.now()
//Data.now(),返回表示调用这个方法时的日期和时间的毫秒数。
//取得开始时间
var start = Date.now();
//调用函数
doSomething();
//取得停止时间
var stop = Date.now(),
result = stop – start;
继承的方法
Date 类型的 toLocaleString()方法会按照与浏览器toString()方法则通常返回带有时区信息的日期和时间,其中时间一般以军用时间(即小时的范围是 0 到 23)表示。设置的地区相适应的格式返回日期和时间。valueOf()方法,则根本不返回字符串,而是返回日期的毫秒表示。
var date1 = new Date(2007, 0, 1); //"January 1, 2007"
var date2 = new Date(2007, 1, 1); //"February 1, 2007"
alert(date1 < date2); //true
alert(date1 > date2); //false
日期格式化方法
Date 类型还有一些专门用于将日期格式化为字符串的方法,这些方法如下。
toDateString()——以特定于实现的格式显示星期几、月、日和年;
toTimeString()——以特定于实现的格式显示时、分、秒和时区;
toLocaleDateString()——以特定于地区的格式显示星期几、月、日和年;
toLocaleTimeString()——以特定于实现的格式显示时、分、秒;
toUTCString()——以特定于实现的格式完整的 UTC 日期。
日期/时间组件方法
RegExp 类型
ECMAScript 通过 RegExp 类型来支持正则表达式。
//创建一个正则表达式
var expression = / pattern / flags ;
标志 | 说明 |
g | 表示全局(global)模式,即模式将被应用于所有字符串,而非在发现第一个匹配项时立即停止 |
i | 表示不区分大小写(case-insensitive)模式,即在确定匹配项时忽略模式与字符串的大小写 |
m | 表示多行(multiline)模式,即在到达一行文本末尾时还会继续查找下一行中是否存在与模式匹配的项 |
字面量形式
/*
* 匹配字符串中所有"at"的实例
*/
var pattern1 = /at/g;
/*
* 匹配第一个"bat"或"cat",不区分大小写
*/
var pattern2 = /[bc]at/i;
/*
* 匹配所有以"at"结尾的 3 个字符的组合,不区分大小写
*/
var pattern3 = /.at/gi;
与其他语言中的正则表达式类似,模式中使用的所有元字符都必须转义。正则表达式中的元字符包括:( [ { \ ^ $ | ) ? * + .]}
RegExp 构造函数
/*
* 匹配第一个"bat"或"cat",不区分大小写
*/
var pattern1 = /[bc]at/i;
/*
* 与 pattern1 相同,只不过是使用构造函数创建的
*/
var pattern2 = new RegExp("[bc]at", "i");
由于 RegExp 构造函数的模式参数是字符串,所以在某些情况下要对字符进行双重转义。所有元字符都必须双重转义,那些已经转义过的字符也是如此,例如\n(字符\在字符串中通常被转义为\\,而在正则表达式字符串中就会变成\\\\)。
ECMAScript 5 明确规定,使用正则表达式字面量必须像直接调用 RegExp 构造函数一样,每次都创建新的 RegExp 实例。
//实际上只为/cat/创建了一个 RegExp 实例。由于实例属性不会重置,所以在循环中再次调用 test()方法会失败。
var re = null,
i;
for (i=0; i < 10; i++){
re = /cat/g;
re.test("catastrophe");//
}
//每次迭代都会创建一个新的RegExp 实例,所以每次调用 test()都会返回 true。
for (i=0; i < 10; i++){
re = new RegExp("cat", "g");
re.test("catastrophe");
}
RegExp实例属性
RegExp 的每个实例都具有下列属性,通过这些属性可以取得有关模式的各种信息。
global:布尔值,表示是否设置了 g 标志。
ignoreCase:布尔值,表示是否设置了 i 标志。
lastIndex:整数,表示开始搜索下一个匹配项的字符位置,从 0 算起。
multiline:布尔值,表示是否设置了 m 标志。
source:正则表达式的字符串表示,按照字面量形式而非传入构造函数中的字符串模式返回。
var pattern1 = /\[bc\]at/i;
alert(pattern1.global); //false
alert(pattern1.ignoreCase); //true
alert(pattern1.multiline); //false
alert(pattern1.lastIndex); //0
alert(pattern1.source); //"\[bc\]at"
var pattern2 = new RegExp("\\[bc\\]at", "i");
alert(pattern2.global); //false
alert(pattern2.ignoreCase); //true
alert(pattern2.multiline); //false
alert(pattern2.lastIndex); //0
alert(pattern2.source); //"\[bc\]at"
RegExp实例方法
RegExp 对象的主要方法是 exec(),该方法是专门为捕获组而设计的。 exec()接受一个参数,即要应用模式的字符串,然后返回包含第一个匹配项信息的数组;或者在没有匹配项的情况下返回 null。返回的数组虽然是 Array 的实例,但包含两个额外的属性: index 和 input。其中, index 表示匹配项在字符串中的位置,而 input 表示应用正则表达式的字符串。在数组中,第一项是与整个模式匹配的字符串,其他项是与模式中的捕获组匹配的字符串(如果模式中没有捕获组,则该数组只包含一项)。
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"
exec()
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
test()
var text = "000-00-0000";
var pattern = /\d{3}-\d{2}-\d{4}/;
if (pattern.test(text)){
alert("The pattern was matched.");
}
toLocaleString()和 toString()
var pattern = new RegExp("\\[bc\\]at", "gi");
alert(pattern.toString()); // /\[bc\]at/gi
alert(pattern.toLocaleString()); // /\[bc\]at/gi
正则表达式的 valueOf()方法返回正则表达式本身。
RegExp构造函数属性
var text = "this has been a short summer";
var pattern = /(.)hort/g;
/*
* 注意: Opera 不支持 input、 lastMatch、 lastParen 和 multiline 属性
* Internet Explorer 不支持 multiline 属性
*/
if (pattern.test(text)){
alert(RegExp.input); // this has been a short summer
alert(RegExp.leftContext); // this has been a
alert(RegExp.rightContext); // summer
alert(RegExp.lastMatch); // short
alert(RegExp.lastParen); // s
alert(RegExp.multiline); // false
}
模式的局限性
ECMAScript 正则表达式不支持的特性:
匹配字符串开始和结尾的\A 和\Z 锚①
向后查找(lookbehind) ②
并集和交集类
原子组(atomic grouping)
Unicode 支持(单个字符除外,如\uFFFF)
命名的捕获组③
s(single,单行)和 x(free-spacing,无间隔)匹配模式
条件匹配
正则表达式注释