引用类型的值(对象)是引用类型的一个实例,引用类型是一种数据结构,用于将数据和功能组织在一起。引用类型有时候也被称为对象定义,因为他们描述的是一类对象所具有的属性和方法。对象是某个特定引用类型的实例,新对象是使用new操作符后跟一个构造函数来创建。

var  person = new Object();

5.1 Object类型

1. 创建Object实例
创建Object实例的方式有两种:
(1)使用new操作符后跟Object构造函数

var person = new Object();
person.name = "Chris";
person.age = 22;

(2)使用对象字面量表示法

var person = {
name : "Chris",
age : 22
};

注意:
1) 在对象字面量中,使用逗号来分隔不同的属性,但在最后一个属性后面不能添加逗号。否则在一些早 版本浏览器中导致错误。
2)在使用对象字面量语法时,属性名也可以使用字符串;
3)使用对象字面量语法时,如果留空其花括号,则可以定义只包含默认属性和方法的对象,如下:

var person = {};
person.name = "Chris";
person.age = 22;

2. 访问对象属性
(1)点表示法

 alert(person.name);  //"Chris"

(2)方括号表示法

alert(person["name"]);  //"Chris"

注意:1)方括号表示法的主要优点是可以通过变量来访问属性;

 var propertyName = "name";
 alert(person[propertyName]);  //"Chris"

2)如果属性名中包含会导致语法错误的字符,或者属性名使用的是关键字或者保留字,也可以使用方括号表示法;

person["first name"] = "Chris";  

因为"first name"中包含一个空格,所以不能让使用点表示法来访问它们,然而,属性名中是可以包含非字母非数字的,这时候就可以使用方括号表示法来访问它们;
3)通常,除非必须使用变量来访问属性,否则建议使用点表示法。

5.2 Array类型

1、与其他语言不同的是:
(1)ECMScript数组的每一项可以保存任何类型的数据;
(2)ECMScript数组的大小是可以动态调整的,即可以随着数据的添加自动增长以容纳新增数据;
2、创建数组的基本方式有两种:
(1)使用Array构造函数;

var colors = new Array();

(2)使用数组字面量表示法,数组字面量由一对包含数组项的方括号表示,多个数组之间以逗号隔开;

var colors = ["red", "blue", "yellow"];

3、在读取和设置数组的值时,要使用方括号并提供相应值的基于0的数字索引;

var colors = ["red", "blue", "green"] //定义一个字符串数组`
alert(colors[0]); //显示第一项
colors[2] = "black";  //修改第三项
colors[3] = "brown";  //新增第四项

4、数组的项数保存在其length属性中,这个属性始终会返回0或更大的值;

var colors = ["red", "blue", "green"]; //定义一个字符串数组
alert(colors.length);  //3

5、通过设置数组的length属性,可以从数组的末尾移除项或者向数组中添加新项;

var colors = ["red", "blue", "green"] //定义一个字符串数组
colors.length = 2;
alert(colors[2]);  //undefined(移除项)

该例中的数组colors一开始有3个值,将其length属性设置为2会移除最后一项(位置为2的那一项),结果再访问colors[2]就会显示undefined。如果将其length属性设置为大于数组项数的值,则新增的每一项都回去的undefined值;

var colors = ["red", "blue", "green"] //定义一个字符串数组
colors.length = 4;
alert(colors[3]);  //undefined(新增项)

利用length属性也可以方便地在数组末尾添加新项;

var colors = ["red", "blue", "green"] //定义一个字符串数组
colors[colors.length] = "black";  //(在位置3)添加一种颜色
colors[colors.length] = "brown";  //(在位置4)再添加一种颜色

当把一个值放在超出当前数组大小的位置上时,数组就会重新计算其长度值,即长度值等于最后一项的索引加1。
1. 检测数组
(1)对于一个网页或者有个全局作用域而言,使用instanceof操作符就能确定某个对象是不是数组;

if (value instanceof Array) {
   //对数组执行某些操作
}

(2)Array.isArray()方法的目的是最终确定某个值到底是不是数组,而不管它是在哪个全局执行环境中创建的。

if (Array.isArray(value)) {
  //对数组执行某些操作
}

2. 转换方法
所有对象都具有toLocaleString()toString()valueOf()方法。其中,调用valueOf()返回的还是数组本身,而调用数组的toString()方法会返回有数组中每个值的字符串形式拼接而成的一个以逗号分隔的字符串;
toLocalString()方法经常会返回与toString()和valueOf()方法相同的值,但也不总是如此。

  • (1)当调用数组的toLocaleString()方法时,调用的是每一项的toLocaleString()方法。
  • (2)采用alert()输出时,由于alert()要接收字符串参数,所以它会在后台调用toString()方法,由此会得到与直接调用toString()方法相同的结果。

数组继承的toLocaleString()、toString()和valueOf()方法,在默认情况下都会以逗号分隔的字符串的形式返回数组项,而如果使用join()方法,则可以使用不同的分隔符来构建这个字符串(将数组转化为字符串)。join()方法只接收一个参数,即用作分隔符的字符串,然后返回包含所有数组项的字符串.如果不给join()方法传入任何值,或者给它传入undefined,则使用逗号作为分隔符。split()将字符喜转换为数组。

var colors = ["red", "green", "blue"];
alert(colors.join(","));  //red,green,blue
alert(colors.join("||"));  //red||green||blue

var color1 = "2:3:4:5";
color1.split(":");    //["2","3","4","5"]

3. 栈方法
栈是一种LIFO(Last-In-First-Out,先进后出)的数据结构,也就是最新添加的项最早被移除。而栈中项的插入(叫做推入)和移除(叫做弹出),只发生在一个位置——栈的顶部。
push()方法可以接收任意数量的参数,把它们逐个添加到数组末尾,并返回修改后数组的长度;
pop()方法从数组末尾移除最后一项,减少数组的length值,然后返回移除的项;

var colors = new Array();  //创建一个数组
var count = colors.push("red", "green");  //推入两项
alert(count);  //2

var item = colors.pop(); //取得最后一项
alter(item);  //"green"
alert(colors.length); //1

4. 队列方法
队列数据结构的访问规则是FIFO(First-In-First-Out,先进先出)。队列在列表的末端添加项,从列表的前端移除项;
(1)shift()方法,它能够移除数组中的第一项并返回该项,同时将数组长度减1(删除第一项);
(2)unshift()方法,它能在数组前端添加任意个项并返回新数组的长度。
(3)结合使用shift()和push()方法,可以像使用队列一样使用数组;(末端添加项,前端移除项)

var colors = new Array(); //创建一个数组
var count = colors.push("red", "green"); //推入两项
alert(count);  //2

count = colors.push("black");  //末端推入另一项

var item = colors.shift();  //取得第一项
alert(item); //"red" 
alert(colors.length);  //2
(4)同时使用unshift()和pop()方法,可以从相反的方向来模拟队列;(前端添加项,末端移除项)
var colors = new Array(); //创建一个数组`
var count = colors.push("red", "green"); //推入两项
alert(count);  //2

count = colors.unshift("black");  //前端推入另一项

var item = colors.pop();  //取得最后一项
alert(item); //"green" 
alert(colors.length);  //2

5. 重排序方法
(1)数组中已经存在的两个可以直接用重排序的方法:reverse()sort()方法
reverse()方法会反转数组项的顺序;
在默认情况下,sort()方法按升序排列数组项,sort()方法会调用每个数组项的toString()转型方法,然后比较得到字符串,已确定如何排序,即使数组中的每一项都是数值,sort()方法比较的也是字符串。
(2)比较函数(P93)

function compare(value1,value2) {
    if(value1 < value2) {
        return -1;
    }else if(value1 > value2){
        return 1;
    }else{
        return 0;
    }
}

6. 操作方法
(1)concat()方法可以基于当前数组中的所有项创建一个新的数组
(2)slice()方法能够基于当前数组中的一个多个项创建一个新的数组。slice()方法可以接收一个或者两个参数,即要返回项的起始和结束位置。在只有一个参数的情况下,slice()方法返回从该参数指定位置开始到当前数组末尾的所有项;如果有两个参数,该方法返回起始和结束位置之间的项——但不包括结束位子的项。注意,slice()方法不会影响原始数组。

var colors = ["red", "green", "blue", "yellow","purple"];
var colors2 = colors.silce(1);
var colors3 = colors.slice(1,4);

alert(colors2); //green,blue,yellow,purple
alert(colors3); //green,blue,yellow

注意:
1)如果slice方法的参数中有一个附属,则用数组长度加上该数来确定相应的位置;
2)如果结束位置小于起始位置,则返回空数组
(3)splice()方法的主要用途是向数组的中部插入项
1)删除:可以删除任意数量的项,只需指定2个参数:splice(要删除的第一项的位置,要删除的项数)
2)插入:可以向指定位置插入任意数量的项,只需提供3个参数splice(起始位置,要删除的项数,要插入的项)
3)替换:可以向指定位置插入任意数量的项,且同时删除任意数量的项,只需指定3个参数
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,返回的数组中只包含一项

7. 位置方法
indexOf()lastIndexOf(),这两个方法都接收两个参数:要查找的项和(可选的)表示查找起点位置的索引。其中,indexOf()方法从数组的开头(位置0 )开始向后查找。LastIndexOf()方法则从数组的末尾向前查找。这两个方法都返回要查找的项在数组中的位置,或者在没有找到的情况下返回-1.

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

8. 迭代方法
每个方法都接收两个参数:要在每一项运行的函数和(可选的)运行该函数的作用域对象。传入这些方法中的函数会接收三个参数:数组项的值、该项在数组中的位置和数组对象本身

  • every():对数组中的每一项运行给定函数,如果该函数对每一项都返回true,则返回true;
  • filter():对数组中的每一项运行给定函数,返回该函数会返回true的项组成的数组;
  • forEach():对数组中的每一项运行给定函数,该方法没有返回值;
  • map():对数组中的每一项运行给定函数,返回每次函数调用的结果组成的数组;
  • some():对数组中的每一项运行给定函数,如果该函数对任一项返回true,则返回true。
var numbers = [1,2,3,4,5,4,3,2,1];
  var everyResult = numbers.every(function(item,index,array){
      return (itrem>2);
  });
  alert(everyResult);   //false
  
  var someResult = numbers.every(function(item,index,array){
    return (itrem>2);
});
  alert(someResult);  //true

注意:对every()来说,传入的函数必须对每一项都返回true,这个方法才返回true;而some()方法则是只要传入的函数对数组中的某一项返回true,就会返回true。

9. 归并方法
ECMAScript5新增了两个归并数组的方法:reduce()和reduceRight()。这两个方法都会迭代数组的所有项,然后构建一个最终返回值。其中reduce()方法从数组的第一项开始,逐个遍历到最后。而reduceRight()则从数组的最后一项开始,向前遍历到第一项。
以上两种方法都接收两个参数:在每一项调用的函数、作为归并基础的初始值
传给reduce()和reduceRight()的函数接收四个参数:前一个值、当前值、项的索引和数组对象。这个函数返回的任何值都会作为第一个参数自动传给下一项。以第一次迭代发生在数组的第二项上,因此第一个参数是数组的第一项,第二个参数就是数组的第二项。

var values = [1,2,3,4,5];
var sum = values.reduce(function(prev, cur, index, array){
return prev + cur;
});
alert(sum); //15

5.3 Date类型

要创建一个日期对象,使用new操作符和Date构造函数即可
var now = new Date();
//在调用Date构造函数而不传递参数的情况下,新创建的对象自动获得当前日期和时间
如果想根据特定的日期和时间创建日期对象,必须传入该日期的毫秒数。或者使用Date.parse()Date.UTC();
Date.parse()方法接收一个表示日期的字符串参数,然后尝试根据这个字符串返回相应日期的毫秒数;如果传入Date.parse()方法的字符串不能表示日期,那么它会返回NaN;如果直接将表示日期的字符串传递给Date构造函数,也会在后台调用Date.parse()。
Date.UTC()方法同样也返回表示日期的毫秒数,Date.UTC()的参数分别是年份、基于0的月份,月中的哪一天(1到31)、小时数(0到23)、分钟、秒以及毫秒数。在这些参数中,只有年和月是必需的
Date.now()方法,返回表示调用这个方法时的日期和时间的毫秒数。
1. 继承的方法
Date类型也重写了toLocaleString()、toString()和valueOf()方法。

  • Date类型的toLocaleString()方法会按照与浏览器设置的时区相适应的格式返回日期和时间。(大致意味时间格式中会包含AM或PM,但不会包含时区信息);
  • Date类型的toString()方法则通常返回带有时区信息的日期和时间,其中时间一般以军用时间表示;
  • Date类型的valueOf()方法则根本不返回字符串,而是返回日期的毫秒表示。因此,可以方便使用比较操作符(小于或大于)来比较日期值。

2. 日期格式化方法

  • toDateString()——以特定于实现的格式显示星期几、月、日和年;
  • toTimeString()——以特定于实现的格式显示时、分、秒和时区;
  • toLocaleDateString()——以特定于地区的格式显示星期几、月、日和年;
  • toLocaleTimeString()——以特定于实现的格式显示时、分、秒和时区;
  • toUTCString()——以特定于实现的格式完整的UTC日期;

3. 日期/时间组件方法 (P102)

5.4 RegExp类型

RegExp类型是用来支持正则表达式:
(1)第一种创建正则表达式的方法如下:
var expression = / pattern / flags;
其中的模式(pattern)部分可以是任何简单或复杂的正则表达式,可以包含字符类、限定符、分组、向前查找以及反向引用。
每个正则表达式都可以带有一个或者多个标志(flags),用以标明正则表达式的行为。正则表达式的匹配模式支持下列3个标志:

  • g:表示全局(global)模式,即模式将被应用于所有字符串,而非在发现第一个匹配项时立即停止;
  • i:表示不区分大小写(case-insensitive)模式,即在确定匹配项时忽略模式与字符串的大小写;
  • m:表示多行(multiline)模式,即在到达一行文本末尾时还会继续查找下一行是否存在与模式匹配的项

模式中使用的所有元字符都必须转义。正则表达式中的元字符包括:( [ { ^ $ | ) ? * + . ] }
(2)另一种创建正则表达式的方式是使用RegExp函数,它接收两个参数:一个是要匹配的字符串模式,另一个是可选的标志字符串。
//匹配第一个"bat"或"cat",不区分大小写
var pattern1 = /[bc]at/i; //使用第一种方法创建
var pattern2 = new RegExp("[bc]at","i"); //使用RegExp函数实现
由于RegExp构造函数的模式参数是字符串,所以在某些情况下要对字符串进行双重转义。

正则表达式字面量始终会共享同一个RegExp实例,而使用构造函数创建的每一个新RegExp实例都是一个新实例。
1. RegExp实例属性

  • global:布尔值,表示是否设置了g标志;
  • ignoreCase:布尔值,表示是否设置了i标志;
  • lastIndex:整数,表示开始搜索下一个匹配项的字符位置,从0算起。
  • multiline:布尔值,表示是否设置了m标志;
  • source:正则表达式的字符串表示,按照字面量形式而非传入构造函数的字符串模式返回。
  • source属性保存的是规范形式的字符串,即字面量形式所用的字符串。

2. RegExp实例方法
正则表达式的第一个方法是exec()链接描述: 接收一个参数,即要应用模式的字符串,然后返回包含第一个匹配信息的数组;或者在没有匹配项的情况下返回null。exec() 方法还返回两个属性。index 属性声明的是匹配文本的第一个字符的位置(匹配项在字符串中的位置)。input 属性则存放的是被检索的字符串 string(表示应用正则表达式的字符串)。

  • 在数组中,第一项是与整个模式匹配的字符串,其他项是与模式中的捕获组匹配的字符串(如果模式中没有捕获组,则该数组只包含一项)
  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()方法而言,即使在模式中设置了全局标志(g),他每次也只会返回一个匹配项。在不设置全局标志的情况下,在同一个字符串上多次调用exec()将始终返回第一个匹配项的信息,而在设置全局变量的情况下,每次调用exec()则都会在字符串中继续查找新匹配项。

正则表达式的第二个方法是test()链接描述:它接受一个字符串参数,如果字符串 string 中含有与RegExpObject 匹配的文本,则返回true,否则返回false
3. RegExp构造函数属性

  • input:最近一次要匹配的字符串["$_"]
  • lastMatch:最近一次与整个正则表达式匹配的字符串["$&"]
  • lastParen:最近一次匹配的捕获组["$+"]
  • leftContext:input字符串中lastMatch之前的文本["$`"]
  • rightContext:input字符串中lastMatch之后的文本["$'"]
  • multiline:布尔值,表示是否所有表达式都使用多行模式["$*"]
    var text = "this has been a short summer";
    var pattern = /(.)hort/g;
    
    if(pattern.test(text)){
    alert(RegExp.input);  //this has been a short summer
    alert(RegExp.leftContext);  //this has been
    alert(RegExp.rightContext);  //summer
    alert(RegExp.lastMatch);  //short
    alert(RegExp.lastParen);  //a
    alert(RegExp.multiline);  //false
    }

注意:以上使用的长属性名都可以用相应的短属性名来代替,不过短属性名不是有效的ECMAScript标识符,因此必须通过方括号语法来访问它们。

var text = "this has been a short summer";
var pattern = /(.)hort/g;

if(pattern.test(text)){
alert(RegExp.$_);  //this has been a short summer
alert(RegExp["`$`"]);  
//this has been
alert(RegExp["$'"]);  //summer
alert(RegExp["$&"]);  //short
alert(RegExp["$+"]);  //a
alert(RegExp["$*"]);  //false
}

4. 模式的局限性 (P109)

5.5 Function类型

1. 没有重载(深入理解)
2. 函数声明与函数表达式
3. 作为值的函数
4. 函数的内部属性
在函数内部,有两个特殊的对象:argumentsthis
(1)arguments是一个类数组对象,包含着传入函数中的所有参数,它的主要用途是保存函数参数。这个对象还有一个名叫callee的属性,该属性是一个指针,指向拥有这个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*arguements.callee(num-1);
}
}

在这个重写后的factorial()函数的函数体内,没有再引用函数名factorial。这样,无论引用函数时使用的是什么名字,都可以保证正常完成递归调用。
(2)函数内部的另一个特殊对象是this。this引用的是函数执行的环境对象(当在网页的全局作用域中调用函数时,this对象引用的就是window)
!函数的名字仅仅是一个包含指针的变量而已
EMAScript也规范了另一个函数对象的属性:caller这个属性保存着 调用当前函数的函数的引用
5. 函数属性和方法
每个函数都包含两个属性:lengthprototype
(1)length属性表示函数希望接收的命名参数的个数
(2)prototype属性是保存他们所有实例方法的真正所在
(3)每个函数都包含两个非继承而来的方法:apply()call(),这两个方法的用途都是在特定的作用域中调用函数,实际上等于设置函数体内this对象的值。
apply()方法接收两个参数:在其中运行的函数的作用域 和 参数数组
call()方法:第一个参数是this值没有变化,变化的是其余参数都直接传递给函数。换句话说,在使用call()方法时,传递给函数的参数必须逐个列举出来。

function sum(num1,num2) {
return num1+num2; 
}
function callSum1(num1,num2) {
return sum.apply(this,arguments); //传入arguments对象
}

function callSum2(num1,num2) {
return sum.apply(this,[num1,num2]); //传入数组
}

function callSum3(num1,num2) {
return sum.call(this,num1,num2); //其余参数都直接传递给函数`
}

alert(callSum1(10,10));  //20
alert(callSum2(10,10));  //20
alert(callSum3(10,10));  //20

apply()和call()真正的用武之地在——能够扩充函数赖以运行的作用域

windows.color = "red";
var o = {color : "blue"};

function sayColor() {
alert(this.color);
}
sayColor();  //red

sayColor.call(this);  //red
sayColor.call(window); //red
sayColor.call(o); //blue

使用apply()或call()来扩充作用于的最大好处就是,对象不需要与方法有任何耦合关系。
(4)bind()方法。这个方法会创建一个函数的实例,其this值会被绑定到传给bind()函数的值。

windows.color = "red";
var o = {color : "blue"};

function sayColor() {
alert(this.color);
}
var objectSayColor= sayColor.bind(o);
objectSayColor();   //blue

5.6 基本包装类型

ECMAScript提供了3种特殊的引用类型:Boolean、Number和String
引用类型与基本包装类型的主要区别就是对象的生存周期。使用new操作符创建的引用类型的实例,在执行流离开当前作用域之前都一直保存在内存中。而自动创建的基本包装类型的对象,则只存在于一行代码的执行瞬间,然后立即被销毁。这意味着我们不能在运行时为基本类型值添加属性和方法。

var s1 = "some text";
s1.color = "red";
alert(s1.color); //undefined

!注意:使用new调用基本包装类型的构造函数,与直接调用同名的转型函数是不一样的

var value = "25";
var number = Number(value); //转型函数
alert(typeof number); //"number"

var obj = new Number(value); //构造函数
alert(type of obj);  //"object"

1. Boolean类型
(1)Boolean类型是与布尔值对应的引用类型。要创建Boolean对象,可以像下面这样调用Boolean构造函数并传入true或者false值。

var BooleanObject= newBoolean(true);

Boolean类型的实例重写了valueOf()方法,返回基本类型值true或false;重写了toString()方法,返回字符串"true"和"flase"。

var falseObject = new Boolean(false);
var result = falseObject && true;   
alert(result);  //true 
(布尔表达式中的所有对象都会被转化为true,因此falseObject对象在布尔表达式中代表的是true,结果true&&true就等于true) 

(2)基本类型与引用类型的布尔值还有两个区别:
1)typeof操作符对基本类型返回"boolean",而对引用类型返回"object";
2)由于Boolean对象是Boolean类型的实例,所以使用instanceof操作符测试Boolean对象会返回true,而测试基本类型的布尔值则返回false。

var falseObject = new Boolean(false);
var falseValue = false;
alert(typeof falseObject); //Object
alert(typeof falseValue); //boolean
alert(falseObject instanceof Boolean); //true
alert(falseValue instanceof Boolean); //false

2. Number类型
(1)要创建Number对象,可以在调用Number构造函数时向其中传递相应的数值。

var numberObject = new Number(10);

(2)Number类型也重写了valueOf()、toLocaleString()和toString()方法。重写后的valueOf()方法返回对象表示的基本类型的值,另外两个方法则返回字符串形式的数值。
(3)toFixed()方法会按照指定的小数位返回数值的字符串表示。

var num = 10;
alert(num.toFixed(2)); //"10.00"

如果数值本身包含的小数位比指定的还多,那么接近指定的最大小数位的值就会被舍入。

var num = 10.005;
alert(num.toFixed(2)); //"10.01"

(4)toExponential()可用于格式化数值,该方法返回以指数表示法表示的数值的字符串形式。toExponential()也接收一个参数,而且该参数同样也是指定输出结果的小数位数。

var num = 10;
alert(num.toExponential(1)); //"1.0e+1"

(5)toPrecision()方法可能会返回固定大小(fixed)格式,也可能返回指数(exponential)格式。这个方法接收一个参数,即表示数值的所有数字的位数(不包括指数部分)。

var num = 99;
alert(num.toPrecision(1)); //"1e+2"
alert(num.toPrecision(2)); //"99"
alert(num.toPrecision(3)); //"99.0"

3. String类型
链接描述

5.7 单体内置对象

1. Global对象
2. Math对象

5.8 小结


皮卡丘丘丘
50 声望12 粉丝

不忘初心方得始终,念念不忘必有回响