引用类型的值(对象)是引用类型的一个实例,在ECMAScript中,引用类型是一种数据结构,用于将数据和功能组织在一起。新对象是使用new操作符后跟一个构造函数来创建。
var a = new Object();
5.1 Object类型
大多数引用类型都是Object类型的实例,Object也是使用的最多的引用类型。一般通过字面量创建。
var a = {
x: 1,
y: 2
};
一般通过点表示法访问对象的属性,也可以使用方括号语法,方括号语法的优点在于可以通过变量来访问属性。
a.x;
a["x"];
a[name];
5.2 Array类型
ECMAScript中的数组可以保存任何类型的数据,并且大小可以动态调整,可以随着数据的添加自动增长以容纳新增数据。
var a = [];
数组的项数保存在length属性当中,这个属性始终返回0或者更大的值,它不是只读的,可以修改,修改它会直接修改数组的长度。
数组的最后一项索引始终是length-1,因此下一个新项的位置就是length。
5.2.1 检测数组
对于一个网页或者一个全局作用域而言,使用instanceof操作符检测数组。
if (value instanceof Array){
// 执行操作
}
当存在多个框架,即当存在多个全局作用域时,两个全局作用域之间互相传递的数组不是来源于同一个构造函数,所以会返回false。ECMAScript5新增方法isArray()用来检测数组。
if (Array.isArray(value)){
// 执行操作
}
5.2.2 转换方法
数组的toString()方法返回由数组中每个值的字符串形式拼接而成,并以逗号隔开的一个字符串(实际上是每一项分别调用toString()方法后再拼接)。数组的valueOf()方法返回数组本身。toLocaleString()方法返回与toString()方法相同,区别是每一项分别调用toLocaleString()方法。
var a =[1,2,3];
console.log(a.toString()); // "1,2,3"
console.log(a.valueOf()); // [1, 2, 3]
数组的join()方法返回与toString()方法相同,但可以接收一个参数,参数表示每一项之间的分隔符。
var a =[1,2,3];
console.log(a.join("|")); // 1|2|3
null和undefined的项在上述4个方法中返回空字符串。
5.2.3 栈方法
数组的push()方法可以接收任意数量的参数,把它们逐个添加到数组的末尾,并返回修改后的数组的长度。而pop()方法则从数组末尾移除最后一项,减少数组的length值,然后返回移除的项
var a =[1,2,3];
var b = a.push("x","y");
var c = a.pop();
console.log(b); // 5
console.log(c); // "y"
5.2.4 队列方法
数组的shift()方法用来移除数组的第一项并将其返回,unshift()方法用来在数组的前端添加任意项并返回新数组的长度。
var a =[1,2,3];
var b = a.shift();
var c = a.unshift("x","y");
console.log(b); // 1
console.log(c); // 4
5.2.5 重排序方法
数组的reverse()方法用来反转整个数组的顺序,并返回排序之后的数组。
var a =[1,2,3];
var b = a.reverse();
console.log(b); // [3,2,1]
数组的sort()方法在默认情况下按升序排列,即最小值在最前面,最大值在最后面,但排序时是调用每一项的toString()方法,所以"10"会在"5"的前面。sort()方法可以接收一个比较函数,根据整个函数的返回值来进行排序,返回负数则表示第一个值要位于第二个值前,返回0则表示两个值相等,返回正数则表示第一个值要位于第二个值之后。完成排序之后返回排序之后的数组。
var a =[5,1,10];
var b = a.sort();
// 默认不传参数
console.log(b); // [1,10,5]
// 传递一个比较函数
var a =[5,1,10];
function arr(v1, v2) {
return v1 - v2;
}
var b = a.sort(arr);
console.log(b); // [1,5,10]
5.2.6 操作方法
数组的concat()方法可以基于当前数组中的所有项创建一个新数组,当未传参数时,复制当前数组并返回副本。当传入任意参数时,先创建一个当前数组的副本,然后将接收到的参数添加到这个副本的末尾,最后返回新构建的数组,参数可以是其他数组,会将其他数组的每一项都添加到创建的副本当中。
var a =[1,2,3];
var b = a.concat();
var c = a.concat("x",["y","z"]);
console.log(b); // [1, 2, 3]
console.log(c); // [1, 2, 3, "x", "y", "z"]
数组的slice()方法用于返回当前数组的一个部分,接收一个或两个参数,当传入一个参数时,表示要返回的起始位置,返回从该起始位置到数组末尾的所有项。当传入两个参数时,返回起始位置与结束位置之间的所有项(不包括结束位置)。当传递的参数是负值的时候,会使用数组的长度加上该负值来确定相应的位置。如果结束位置小于起始位置,则返回空数组。
var a =[1,2,3,4,5];
var b = a.slice(1);
var c = a.slice(1,4);
var d = a.slice(-3,-1);
console.log(b); // [2, 3, 4, 5]
console.log(c); // [2, 3, 4]
console.log(d); // [3, 4]
数组的splice()方法有多种用法,主要用途是向数组的中部插入项。使用这种方法的方式有3种:
删除:指定两个参数,要删除的第一项的位置和要删除的项数。返回被删除的项组成的数组,会修改原数组。
var a =[1,2,3,4,5];
var b = a.splice(1,2);
console.log(a); // [1, 4, 5]
console.log(b); // [2, 3]
插入:提供3个参数,起始位置、0(即要删除的项数为0,表示不删除)、要插入的项。如果要插入多个项,则继续传递第4第5以至任意多项参数(传递的参数为数组时,不会像concat()方法一样将数组拆散,而是直接将整个数组作为一项插入),因为没有项被删除,所以修改完原数组之后返回一个空数组
var a =[1,2,3,4,5];
var b = a.splice(2,0,"x",["y","z"]);
console.log(a); // [1, 2, "x", ["x","y"], 3, 4, 5]
console.log(b); // []
替换:即当插入用法中的第二个参数不为0时,先删除对应的项,再将后续的项插入,以达到传递的参数项替换数组中原项的效果。
var a =[1,2,3,4,5];
var b = a.splice(2,2,"x",["y","z"]);
console.log(a); // [1, 2, "x", ["x","y"], 5]
console.log(b); // [3, 4]
上述3种用法中的第一个参数同样接收负值,负值用法与slice()方法相同。
5.2.7 位置方法
数组有两个位置查询方法,indexOf()和lastIndexOf(),indexOf()表示从数组的开头开始查询,lastIndexOf()表示从数组的末尾开始查询。传入的参数为需要查询的项,在查询比较时,使用的是全等(===)符号,返回查询到第一个符合条件的项的索引,未查询到则返回-1。
var a =[1,2,3,4,5,4];
console.log(a.indexOf(4)); // 3
console.log(a.lastIndexOf(4)); // 5
console.log(a.indexOf(6)); // -1
5.2.8 迭代方法
数组有5个迭代方法,每个方法都接收两个参数:要在每一项上运行的函数和运行该函数的作用域对象(第二个参数是可选的,主要影响第一个参数所传的函数中的this值)。传入的函数接收3个参数:数组的项的值,该项在数组中的位置,数组本身。
every()方法:对数组的每一项运行传入的函数,若每一项都返回true,则返回true。
var a =[1,2,3,4,5];
var b = a.every(function (item,index,arr) {
return item>0;
});
console.log(b); // true
filter()方法:对数组的每一项运行传入的函数,返回该运行该函数会返回true的项组成的新数组。
var a =[1,2,3,4,5];
var b = a.filter(function (item,index,arr) {
return item>3;
});
console.log(b); // [4,5]
forEach()方法:对数组的每一项运行传入的函数,没有返回值。
var a =[1,2,3,4,5];
a.forEach(function (item,index,arr) {
arr[index] = ++item;
});
console.log(a); // [2, 3, 4, 5, 6]
map()方法:对数组的每一项运行传入的函数,返回每次函数调用结果组成的数组。
var a =[1,2,3,4,5];
var b = a.map(function (item,index,arr) {
return item*index;
});
console.log(b); // [0, 2, 6, 12, 20]
some()方法:对数组的每一项运行传入的函数,如果该函数的任意一项返回true,则返回true
var a =[1,2,3,4,5];
var b = a.some(function (item,index,arr) {
return item>3;
});
console.log(b); // true
5.2.8 归并方法
数组的reduce()和reduceRight()方法用来归并数组,reduce()方法从数组的第一项开始,逐个遍历到最后,而reduceRight()方法则从最后一项开始,逐个遍历到第一项。两个方法都接收两个参数:一个在每一次归并时调用的函数和作为归并基础的初始值(可选)。传给两个方法的函数会接受4个参数:前一个值,当前值,当前项的索引和数组对象,逐个函数的返回值都会作为下一次迭代时函数的第一个参数,因此第一次迭代发生在数组的第二项上,第一个参数是数组第一项,第二个参数是数组第二项。
var a =[1,2,3,4,5];
var b = a.reduce(function (prev, cur, index, arr) {
return prev + cur;
});
console.log(b); // 15
5.3 Date类型
ECMAScript中的Date类型使用UTC标准来保存日期,即从1970年1月1日午夜0时开始经过的毫秒数。
// 创建日期对象
var a = new Date(); // 获取当前日期
var b = new Date("2017/09/26 12:0:0"); // 获取指定时间,传递字符串参数
var c = new Date(2017,8,26,12,0,0); // // 获取指定时间,传递数值参数
console.log(a); // Tue Sep 26 2017 14:27:32 GMT+0800 (中国标准时间)
console.log(b); // Tue Sep 26 2017 12:00:00 GMT+0800 (中国标准时间)
console.log(c); // Tue Sep 26 2017 12:00:00 GMT+0800 (中国标准时间)
Date.now()方法直接获取执行这条代码的时的时间,返回毫秒数。
var a = Date.now();
console.log(a); // 1506407948177
5.3.1 继承的方法
Date类型的valueOf()方法返回日期的毫秒表示,所以Date类型可以直接进行比较。
var a = new Date("2017");
var b = new Date("2016");
console.log(a>b); // true 日期越晚,毫秒数值就越大。
5.3.2 日期/时间组件方法
所有方法文档。
主要方法有几个:
var a =new Date();
// 返回日期毫秒数
console.log(a.getTime()); // 1506408603633
// 返回日期4位数的年份
console.log(a.getFullYear()); // 2017
// 返回日期的月份,0~11表示1月~12月
console.log(a.getMonth()); // 8
// 返回日期月份中的天数,1~31
console.log(a.getDate()); // 26
// 返回日期的星期数,星期日为0
console.log(a.getDay()); // 2
// 返回日期的小时数,0~23
console.log(a.getHours()); // 14
// 返回日期的分数,0~59
console.log(a.getMinutes()); // 50
// 返回日期的秒数,0~59
console.log(a.getSeconds()); // 3
5.4 RegExp类型
见链接
5.5 Function类型
两种方式定义函数
// 函数声明
function a() {}
// 函数表达式
var a = function () {}
函数声明会被解析器率先读取,并使其在执行任何代码之前可用。表达式必须等到解析器解析到他所在的代码行时才会执行。
函数没有重载,同名函数会被覆盖。
5.5.1作为值的函数
函数本身也可以作为值来使用,不仅可以把一个函数作为参数传递给另一个函数,而且可以将一个函数作为另一个函数的结果返回。要访问函数的指针而不执行函数的话,必须去掉函数名后面的那对括号。
// 定义一个根据对象的指定属性的值来排序的函数
function pro(proName) {
return function (obj1, obj2) {
var val1 = obj1[proName];
var val2 = obj2[proName];
if(val1<val2){
return -1;
}else if(val1>val2){
return 1;
}else{
return 0;
}
}
}
var data = [{a:"x",b:2},{a:"y",b:1}];
data.sort(pro("b"));
console.log(data[0].a); // y
5.5.2 函数内部属性
函数内部有两个特殊的对象,argument和this,argument是一个类数组对象,它保存着传入函数中的所有参数,它还拥有一个callee的属性,该属性是一个指针,指向拥有这个argument对象的函数。
// 经典阶乘函数
function a(num) {
if(num<=1){
return 1;
}else{
return num * arguments.callee(num - 1);
}
}
console.log(a(5)); // 120
this引用的是当前函数执行的环境对象,在全局作用域中调用函数时,this对象引用的就是window对象。
函数本身还有一个caller属性,他表示调用当前函数的函数的引用,即是哪个函数调用了当前函数。
function a() {
console.log(arguments.callee.caller);
}
function b() {
a();
}
// 因为b函数调用了a函数,所以执行b函数时,a函数的caller属性会指向b函数
b(); // ƒ b() { a(); }
argument对象还有caller属性,但这个属性在非严格模式下始终是undefined,在严格模式下访问会导致错误,定义这个属性是为了区分函数本身的caller属性。
5.5.3 函数属性和方法
函数包含两个属性,length和prototype,length表示函数希望接收的命名参数的个数。
函数包含两个方法,apply()和call(),apply()方法接收两个参数,一个是在其中运行函数的作用域,另一个是函数的参数数组。第二个参数可以是Array的实例,也可以是argument对象。
var x = "xyz";
var a = {x:"abc"};
function fun() {
console.log(this.x);
}
fun(); // xyz
fun.apply(a); // abc
call()方法与apply()方法的作用相同,区别仅在于接收参数方式不同,call()方法第一个参数也是在其中运行函数的作用域,之后的参数为需要传递给函数的逐个参数。使用apply()和call()能够扩充函数的运行的作用域。
ECMAScript5新定义了bind()方法,这个方法会创建一个函数的实例,这个函数的this值会被绑定到传给bind()函数的值。
var a = {x:"abc"};
function fun() {
console.log(this.x);
}
var b = fun.bind(a);
// b已经是一个函数的实例,其this值为a对象。
b(); // abc
5.6 基本包装类型
ECMAScript提供了3个特殊的引用类型,Boolean、Number和String。这些基本包装类型与各自的基本类型值相对应,每当读取一个基本类型值时,后台会自动创建一个对应的基本包装类型的对象,从而让我们能够对基本类型值使用某些方法。引用类型和基本包装类型的区别就在于对象的生存期,使用new操作符创建的引用类型实例,在执行流离开当前作用域之前都一直保存在内存中,而读取基本类型值时创建的基本包装类型的对象,在执行代码的瞬间结束后就被销毁了,所以不能对基本类型值添加属性和方法。
5.6.1 Boolean类型
永远不要使用Boolean类型
5.6.2 Number类型
Number类型的valueOf()方法返回基本类型值的数值,toString()和toLocaleString()方法返回数值的字符串表示。
var a = 10;
console.log(a.valueOf()+10); // 20
console.log(a.toString()+10); // 1010
console.log(a.toLocaleString()+10); // 1010
toFixed()方法返回指定小数位的字符串形式,本身小数位小于参数则补0,大于参数则舍入。
var a = 10.005;
var b = 10;
console.log(a.toFixed(2)); // 10.01
console.log(b.toFixed(2)); // 10.00
toExponential()方法返回指数表示法的字符串形式。
var a = 10;
console.log(a.toExponential(2)); // 1.00e+1
toPrecision()会根据处理的数值来决定到底是使用toFixed()还是toExponential()
var a = 10;
console.log(a.toPrecision(1)); // 1e+1
console.log(a.toPrecision(2)); // 10
console.log(a.toPrecision(3)); // 10.0
5.6.3 String类型
每个String类型都有一个length属性,表示字符串包含多少个字符。双字节符也算一个字符。
var a = "Hello world";
console.log(a.length); // 11
字符方法:charAt()和charCodeAt(),这两个方法接收一个参数,即基于0的字符位置,charAt()返回指定位置的字符的字符串。charCodeAt()返回指定位置的字符的字符编码。
var a = "Hello world";
console.log(a.charAt(1)); // e
console.log(a.charCodeAt(1)); // 101
字符串操作方法:concat(),用于将一个或多个字符串拼接起来,不会改变原字符串。实际操作中使用+拼接字符串更方便。
var a = "Hello";
var b = " world";
var c = "!";
var d = a.concat(b,c);
console.log(d); // Hello world!
slice()、substr()、substring()三个方法返回被操作字符串的一个子字符串,都接收一个或两个参数,第一个参数指定子字符串开始的位置,第二个参数表示子字符串到哪里结束。
slice()和substring()第二个参数指定的是子字符串最后一个字符后面的位置,substr()第二个参数指定的是返回字字符串的字符个数。如果这3个方法没有指定第二个参数,则以字符串长度作为结束位置。这3个方法都不会修改原字符串。
var a = "Hello world!";
console.log(a.slice(1,3)); // el
console.log(a.substr(1,3)); // ell
console.log(a.substring(1,3)); // el
再给这3个方法传递负值时,slice()方法会将传入的负值与字符串的长度想加,substr()方法将负的第一个参数加上字符串的长度,负的第二个参数直接转为0,substring()方法会把所有负值参数都转为0。
var a = "Hello world!";
console.log(a.slice(-5,-1)); // orld
console.log(a.substr(-5,3)); // orld
console.log(a.substring(-5,-1)); //
substring()方法会比较两个参数,会将较小数作为起始位置,较大数作为结束位置。
var a = "Hello world!";
// 相当于调用a.substring(0,3)
console.log(a.substring(3,-4)); // Hel
字符串位置方法:indexOf()和lastIndexOf()两个方法都是从一个字符串中搜索给定的子字符串,然后返回子字符串的位置,没有找到则返回-1。indexOf()从开头开始查找,lastIndexOf()从结尾开始查找。
var a = "Hello world!";
console.log(a.indexOf("o")); // 4
console.log(a.lastIndexOf("o")); // 7
两个方法都接收第二个参数,表示字符串从哪个位置开始查找,indexOf()会忽略参数之前的所有字符,lastIndexOf()会忽略参数之后的所有字符。
var a = "Hello world!";
console.log(a.indexOf("o",6)); // 7
console.log(a.lastIndexOf("o",6)); // 4
字符串去除空格方法:trim()方法用来去除字符串开头和结尾的空格,返回的是子字符串,不会改变原字符串。
var a = " Hello world! ";
console.log(a.trim()); // Hello world!
字符串大小写转换方法:toLowerCase()、toUpperCase()、toLocaleLowerCase()、toLocaleUpperCase()四个方法,toLowerCase()、toUpperCase()分别用来转化为小写和大写,toLocaleLowerCase()、toLocaleUpperCase()两个方法则是针对特定地区的大小写转换方法。大小写转换返回的都是子字符串,不会改变原字符串。
var a = "Hello world!";
console.log(a.toLowerCase()); // hello world!
console.log(a.toUpperCase()); // HELLO WORLD!
字符串匹配方法,match()方法接收一个正则表达式,返回一个匹配相关数组。全局匹配时返回所有匹配成功项组成的数组。
var a = "Hello world!";
var b = a.match(/o/);
console.log(b); // ["o", index: 4, input: "Hello world!"]
var c = a.match(/o/g);
console.log(c); // ["o", "o"]
search()方法接收一个正则表达式,返回字符串中第一个匹配项的索引,没有找到则返回-1。
var a = "Hello world!";
var b = a.search(/o/g);
console.log(b); // 4
字符串替换方法:replace(),可以接收两个参数,第一个参数可以是一个正则表达式或者一个字符串,第二个参数可以是一个字符串或者一个函数。如果第一个参数是一个字符串,则只会替换第一个匹配的子字符串,使用正则表达式并且带有g标识符,才能替换全部匹配的子字符串。
var a = "cat,fat,sat,bat";
var b = a.replace(/at/g,"xy");
console.log(b); // cxy,fxy,sxy,bxy
第二个参数是一个函数时,在只有一个匹配项的情况下,会向函数传递3个参数:模式的匹配项、模式匹配项在字符串中的位置,原始字符串。在定义了多个捕获组的情况下,传递给函数的参数依次是模式的匹配项、每个捕获组的匹配项,最后两个参数依然是模式匹配项在字符串中的位置和原始字符串。
var a = "Hello world";
var b = a.replace(/e/,function (match,pos,str) {
console.log(match,pos,str); // e 1 Hello world
});
split()方法可以基于指定的分隔符将一个字符串分割成多个子字符串,并将结果放在一个数组中。分隔符可以是一个字符串,也可以是一个正则表达式。这个方法还接收第二个可选的参数,用来限制分割后的数组长度。
var a = "cat,fat,sat,bat";
var b = a.split(",",3);
console.log(b); // ["cat", "fat", "sat"]
字符串的比较方法:localeCompare()方法用来比较两个字符串,根据字符串在字母表中的排序来返回,小于参数则返回-1,等于参数返回0,大于参数返回1
var a = "hello";
var b = a.localeCompare("hallo");
var c = a.localeCompare("hello");
var d = a.localeCompare("hfllo");
console.log(b); // 1
console.log(c); // 0
console.log(d); // -1
String构造函数本身还有一个fromCharCode()方法,接收一个或多个字符编码,将其转为字符串。
var a = String.fromCharCode(104,101,108,108,111);
console.log(a); // hello
5.7 单体内置对象
5.7.1 Global对象
在web浏览器中Global对象即window对象。
5.7.2 Math对象
Math对象用来保存数学公式和信息,所有属性和方法文档。
利用Math的求最大最小值方法来求数组中的最大最小值:
var a = [1,2,3,4,5];
var b = Math.min.apply(Math,a);
console.log(b); // 1
舍入方法:Math.ceil()执行向上舍入,Math.floor()执行向下舍入,Math.round()执行标准舍入,即四舍五入。
var a = 1.5;
var b = Math.ceil(a);
var c = Math.floor(a);
var d = Math.round(a);
console.log(b); // 2
console.log(c); // 1
console.log(d); // 2
利用Math的求随机值方法从某个范围中取一个随机值:
// 从1到10之间取一个随机整数
var a = Math.floor(Math.random()*10+1);