乐趣区

JS基础——引用类型

引用类型的值(对象)是引用类型的一个实例,引用类型是一种数据结构,用于将数据和功能组织在一起。引用类型有时候也被称为对象定义,因为他们描述的是一类对象所具有的属性和方法。对象是某个特定引用类型的实例,新对象是使用 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); //35、通过设置数组的 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()方法相同的值,但也不总是如此。数组继承的 toLocaleString()、toString()和 valueOf()方法,在默认情况下都会以逗号分隔的字符串的形式返回数组项,而如果使用 join()方法,则可以使用不同的分隔符来构建这个字符串(将数组转化为字符串)。join()方法只接收一个参数,即用作分隔符的字符串,然后返回包含所有数组项的字符串. 如果不给 join()方法传入任何值,或者给它传入 undefined,则使用逗号作为分隔符。var colors = [“red”, “green”, “blue”];alert(colors.join(“,”)); //red,green,bluealert(colors.join(“||”)); //red||green||blue3. 栈方法 栈是一种 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”alter(colors.length); //14. 队列方法 队列数据结构的访问规则是 FIFO(First-In-First-Out,先进先出)。队列在列表的末端添加项,从列表的前端移除项;(1)shift()方法,它能够移除数组中的第一项并返回该项,同时将数组长度减 1(删除第一项);(2)unshift()方法,它能在数组前端添加任意个项并返回新数组的长度。(3)结合使用 shift()和 push()方法,可以像使用队列一样使用数组;(末端添加项,前端移除项)var colors = new Array(); // 创建一个数组 var count = colors.push(“red”, “green”); // 推入两项 alter(count); //2
count = colors.push(“black”); // 末端推入另一项
var item = colors.shift(); // 取得第一项 alter(item); //”red” alter(colors.length); //2(4)同时使用 unshift()和 pop()方法,可以从相反的方向来模拟队列;(前端添加项,末端移除项)var colors = new Array(); // 创建一个数组 var count = colors.push(“red”, “green”); // 推入两项 alter(count); //2
count = colors.unshift(“black”); // 前端推入另一项
var item = colors.pop(); // 取得最后一项 alter(item); //”green” alter(colors.length); //2
5. 重排序方法(1)数组中已经存在的两个可以直接用重排序的方法:reverse()和 sort()方法 reverse()方法会反转数组项的顺序;在默认情况下,sort()方法按升序排列数组项,sort()方法会调用每个数组项的 toString()转型方法,然后比较得到字符串,已确定如何排序,即使数组中的每一项都是数值,sort()方法比较的也是字符串。(2)比较函数(P93)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);
alter(colors2); //green,blue,yellow,purplealter(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) // 删除第一项 alter(colors); //green,bluealter(removed); //red,返回的数组中只包含一项
removed = colors.splice(1,0,”yellow”,”orange”); // 从位置 1 开始插入两项 alter(colors); //green,yellow,orange,bluealter(removed); // 返回的是一个空数组
removed = colors.splice(1,1,”red”,”purple”); // 插入两项,删除一项 alter(colors); //green,red,purple,orange,bluealter(removed); //yellow,返回的数组中只包含一项 7. 位置方法 indexOf()和 lastIndexOf(), 这两个方法都接收两个参数:要查找的项和(可选的)表示查找起点位置的索引。其中,indexOf()方法从数组的开头(位置 0)开始向后查找。LastIndexOf()方法则从数组的末尾向前查找。这两个方法都返回要查找的项在数组中的位置,或者在没有找到的情况下返回 -1.var numbers = [1,2,3,4,5,4,3,2,1];alter(numbers.indexOf(4)); //3alter(numbers.lastIndexOf(4)); //5
alter(numbers.indexOf(4,4)); //5alter(numbers.lastIndexOf(4,4)); //38. 迭代方法 每个方法都接收两个参数:要在每一项运行的函数和(可选的)运行该函数的作用域对象。传入这些方法中的函数会接收三个参数:数组项的值、该项在数组中的位置和数组对象本身。

every():对数组中的每一项运行给定函数,如果该函数对每一项都返回 true,则返回 true;

filter():对数组中的每一项运行给定函数, 返回该函数会返回 true 的项组成的数组;

forEach():对数组中的每一项运行给定函数, 该方法没有返回值;

map():对数组中的每一项运行给定函数, 返回每次函数调用的结果组成的数组;

some():对数组中的每一项运行给定函数,如果该函数对任一项返回 true,则返回 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;});alter(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 构造函数的模式参数是字符串,所以在某些情况下要对字符串进行双重转义。1. RegExp 实例属性

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

2. RegExp 实例方法正则表达式的第一个方法是 exec()链接描述:接收一个参数,即要应用模式的字符串,然后返回包含第一个匹配信息的数组;或者在没有匹配项的情况下返回 null。exec() 方法还返回两个属性。index 属性声明的是匹配文本的第一个字符的位置(匹配项在字符串中的位置)。input 属性则存放的是被检索的字符串 string(表示应用正则表达式的字符串)。对于 exec()方法而言,即使在模式中设置了全局标志(g),他每次也只会返回一个匹配项。在不设置全局标志的情况下,在同一个字符串上多次调用 exec()将始终返回第一个匹配项的信息,而在设置全局变量的情况下,每次调用 exec()则都会在字符串中继续查找新匹配项。正则表达式的第二个方法是 test()链接描述:它接受一个字符串参数,如果字符串 string 中含有与 RegExpObject 匹配的文本,则返回 true,否则返回 false3. 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)){alter(RegExp.input); //this has been a short summeralter(RegExp.leftContext); //this has beenalter(RegExp.rightContext); //summeralter(RegExp.lastMatch); //shortalter(RegExp.lastParen); //aalter(RegExp.multiline); //false}注意:以上使用的长属性名都可以用相应的短属性名来代替,不过短属性名不是有效的 ECMAScript 标识符,因此必须通过方括号语法来访问它们。var text = “this has been a short summer”;var pattern = /(.)hort/g;
if(pattern.test(text)){alter(RegExp.$_); //this has been a short summeralter(RegExp[“$”]); //this has been`alter(RegExp[“$'”]); //summeralter(RegExp[“$&”]); //shortalter(RegExp[“$+”]); //aalter(RegExp[“$*”]); //false}4. 模式的局限性 (P109)
5.5 Function 类型
1. 没有重载(深入理解)2. 函数声明与函数表达式 3. 作为值的函数 4. 函数的内部属性 在函数内部,有两个特殊的对象:arguments 和 this(1)arguments 是一个类数组对象,包含着传入函数中的所有参数,它的主要用途是保存函数参数。这个对象还有一个名叫 callee 的属性,该属性是一个指针,指向拥有这个 arguments 对象的函数。function factorial(num) {if (num<=1) {return 1;} else {rerurn num*factorial(num-1);}}转变为 function factorial(num) {if (num<=1) {return 1;} else {rerurn num*arguements.callee(num-1);}}在这个重写后的 factorial()函数的函数体内,没有再引用函数名 factorial。这样,无论引用函数时使用的是什么名字,都可以保证正常完成递归调用。(2)函数内部的另一个特殊对象是 this。this 引用的是函数执行的环境对象(当在网页的全局作用域中调用函数时,this 对象引用的就是 window)!函数的名字仅仅是一个包含指针的变量而已 EMAScript 也规范了另一个函数对象的属性:caller 这个属性保存着 调用当前函数的函数的引用 5. 函数属性和方法每个函数都包含两个属性:length 和 prototype(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); // 其余参数都直接传递给函数}
alter(callSum1(10,10)); //20alter(callSum2(10,10)); //20alter(callSum3(10,10)); //20
apply()和 call()真正的用武之地在——能够扩充函数赖以运行的作用域 windows.color = “red”;var o = {color : “blue”};
function sayColor() {alter(this.color);}sayColor(); //red
sayColor.call(this); //redsayColor.call(window); //redsayColor.call(o); //blue 使用 apply()或 call()来扩充作用于的最大好处就是,对象不需要与方法有任何耦合关系。(4)bind()方法。这个方法会创建一个函数的实例,其 this 值会被绑定到传给 bind()函数的值。windows.color = “red”;var o = {color : “blue”};
function sayColor() {alter(this.color);}var objectSayColor= sayColor.bind(o);objectSayColor(); //blue
5.6 基本包装类型
1. Boolean 类型 2. Number 类型 3. String 类型
5.7 单体内置对象
1. Global 对象 2. Math 对象
5.8 小结

退出移动版