引用类型的值(对象)是引用类型的一个实例。在ECMAScript中,引用类型是一种数据结构,用于将数据和功能组织在一起,它通常被称为类,但这种称乎并不妥当。从传统意义上来说,ECMAScript 并不真正具有类。事实上,除了说明不存在类,在 ECMA-262 中根本没有出现“类”这个词,它不具备传统的面向对象语言支持的类和接口等基本结构。引用类型有时候也被称为对象定义。
对象是某个特定引用类型的实例,新对象是由 new 运算符加上要实例化的对象的名字创建的,如:
var person = new Object();
这行代码创建了Object引用类型的一个新实例,然后把该实例保存在了变量person。使用的构造函数是Object,它只为新对象定义了默认的属性和方法。
1、Object类型
Object是ECMAScript中使用最多的一个类型,虽然Object的实例不具备多少功能,但对于在应用程序中存储和传输数据而言,确实是非常理想的选择。
创建Object实例的方式有两种,第一种是使用new操作符后跟Ojbect构造函数,如:
var person = new Object(); person.name = "wuyan"; person.age = 20;另一种方式是使用对象字面量表示法,如:
var person = { name : "wuyan", age : "20" };在使用对象字面量语法时,属性名也可以使用字符串,如:
var person = { "name" : "wuyan", "age" : "20", 6 : true //这里的数值属性名会自动转换为字符串 };一般来说,访问对象属性时使用的都是点表示法,不过在JavaScrip中也可以使用方括号表示法来访问对象的属性,在使用方括号语法时,应该将要访问的属性以字符串的形式放在方括号中,如:
alert(person["name"]); //wuyan alert(person.name); //wuyan从功能上看,这两种访问对象属性没有任务区别,但方括号语法的主要优点是可以通过变量来访问属性。如果属性名中包含会导致语法错误,或者属性名是关键字或者保留字时,可以用方括号表示法。
2、Array类型
2.1数组创建
ECMAScript数组的每一项可以保存任何类型的数据,并且数组的大小是可以动态调整的,即可以随着数据的添加自动增长以容纳新增数据。创建数组有两种方式,一种是使用Array构造函数,如:
var colors = new Array();如果预先知道数组的项目数据,也可以给构造函数传递数量,该数量会自动变成length的属性值,如:
var colors = new Array(20);也可以向Array构造函数传递数组中应该包含的项,如:
var colors = new Array("red","green","blue");另外,在使用Array构造函数时也可以省略new操作符,如:
var colors = Array(3); //创建一个包含3项的数组 var colors = Array("red"); //创建一个包含1项数组另外一种创建数组的方式是使用 数组字面量表示法,如:
var colors = ["red","green","blue"]; //创建一个包含3字符串的数组 var names = []; //创建一个空数组 var values = [1,2,]; //不要这样,这样会创建一个包含2项或者3项的数组,在IE浏览器会成为 //一个包含3个项,且每项的值分别为1,2和undefined的数组,在其他浏览器中,会成为一个包含2项且值 //分别为1和2的数组 var options = [ , , , , ,]; //这样会创建一个包含5或6项的数组在读取和设置数组的值时,要使用方括号并提供相应值的基于0的数字索引,如:
var colors = new Array("red","green","blue"); alert(colors[0]); //显示第一项 colors[2] = "black"; //修改第三项 colors[3] = "gray"; //新增第四项,数组会自动增加到该索引值加1的长度,因此数组长度就是4如果利用length属性设置为大于数组项数的值,访问它们都将返回undefined.
2.2检测数组
对于一个网页或者一个全局作用域而言,使用instanceof操作符,如果网页中包含多个框架,实际上就存在两个以上不同的全局执行环境,从而存在两个以上不同版本的Array构造函数,ECMAScript5新增了Array.isArray()方法。这个方法最终确定某个值到底是不是数组,而不管它是在哪个全局执行环境中创建的。
2.3转换方法
所有对象都具有toLocaleString()、toString()和valueOf()方法。其中toString返回由数组中每个值的字符串形式拼接而成的一个以逗号分隔的字符串,valueOf()返回的还是数组。
toLocaleString()、toString()和valueOf()方法默认情况下都会以逗号分隔的字符串形式返回数组项,使用join()方法,可以使用不同的分隔符来构建这个字符串。
2.4栈方法
栈是一种后进先出的数据结构,ECMAScript为数组专门提供了push()和pop()方法,实现类似栈的行为。
push()方法可以接收任意数量的参数,把它们逐个添加到数组末尾,并返回修改后数组的长度,pop()方法则从数组末尾移除最后一项,减少数组的length值,然后返回移除的项,如:
var colors = new Array(); //创建一个数组 var result = colors.push("red","blue"); //推入两项 alert(result); //2 result = colors.push("black",); //推入另一项 alert(result); //3 var item = colors.pop(); alert(item); //black alert(colors.length); //2
2.5队列方法
队列是一种先进先出的数据结构,实现这一操作的数组方法就是shift(),它能够移除数组中的第一个项并返回该项,同时数组的长度减1.结合使用shift()和push()方法,可以像使用队列一样使用数组。如:
var colors = new Array(); //创建一个数组 var result = colors.push("red","blue"); //推入两项 alert(result); //2 result = colors.push("black",); //推入另一项 alert(result); //3 var item = colors.shift(); //取得第一项 alert(item); //"red" alert(colors.length); //2ECMAScript还为数组提供了一个unshift()方法。顾名思义,unshift()与shift()的用途相反,它能在数组前端添加任意个项并返回新数组的长度。因此,同时使用unshift()和pop()方法,可以从相反的方向来模拟队列。
2.6重排序方法
数组中已经存在两个可以直接用来排序的方法:reverse()和sort()方法。reverse()方法会反转数组项的顺序,sort()方法按升序排列数组项,并且会调用每个数组项的toString()方法,然后比较得到的字符串,以确定如何排序。即使数组中的每一项都是数值,sort()方法比较的也是字符串。如:
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 > values2) { return 1; } else { return 0; }**/ //对于数值类型或者其valuesOf()方法返回数值类型的对象类型,可以使用第二个值减第一个即可 return values2 - value1; } var values = [0, 1, 5, 10, 15]; values.sort(compare); alert(values); //0,1, 5 , 10,15
2.7操作方法
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():
它能够基于当前数组中的一或者多个项创建一个新数组。它可接收1个或者两个参数,即要返回项的起始和结束位置,但不包含结束位置的项。只有一个参数的情况下,返回从该参数指定位置开始到当前数组末尾的所有项。如:
var colors = ["red","green","blue","black","brown"]; var colors2 = colors.slice(1); var colors3 = colors.slice(1,4); alert(colors2); //green,blue,yellow,brown alert(colors3); //green,blue,yellow如果slice()方法的参数中一个负数,则用数组长度加上该数来确定相应的位置。
splice():
可以向数组中删除,插入,替换等操作
删除:可以删除任意数量的项,只需要指定2个参数:要删除的第一项的位置和要删除的项数。
插入:可以向指定位置插入任意数量的项,只需要提供3个参数:起始位置、0(要删除的项数)和要插入的项,如果要插入多个项,可以传入任意多个项。
替换:可以向指定位置插入任意数量的项,且同时删除任意数量的项,只需要指定3个参数:起始位置、要的项数和要插入的任意数量的项数。插入的项数不必与删除的项数相等。如:
var colors = ["red","green","blue"]; var remove = colors.splice(0,1); //删除第一项 alert(colors ); //green,blue alert(remove ); //red remove = colors.splice(1,0, "yellow","orange"); //从位置1开始插入2项 alert(colors ); //green,yellow,orange,blue alert(remove ); //返回的是一个空数组 remove = colors.splice(1,1, "red","purple"); //插入两项,删除一项 alert(colors ); //green,red,purple,orange,blue alert(remove ); //yellow
2.8位置方法
ECMAScript5为数组实例添加了两个位置方法:indexOf()和lastIndexOf().都接收两个参数:要查找的项和(可选的)查找起始位置的索引。其中indexOf()方法从数组的开头开始向后查找,lastIndexOf()方法则从数组的末尾开始向前查找。
2.9迭代方法
ECMAScript5为数组定义了5个迭代方法每个方法都接收两个参数:要在每一项上运行的函数和(可选的)运行该函数的作用域对象。传入这些方法中的函数会接收3个参数:数组项的值,该项在数组中的位置和数组对象本身。以下是5个迭代方法及作用:
every():对数组中的每一项运行给定函数,如果该函数对每一项都返回true,由返回true
filter():对数组中的每一项运行给定函数,返回该函数会返回true的项组成的数组
forEach():对数组中的每一项运行给函数。这个方法没有返回值
map():对数组中的每一项运行给定函数,返回每次函数调用的结果组成的数组
some():对数组中的第一项运行给定函数,如果该函数对作一项返回true,则返回true
如:
var numbers = [1,2,3,4,5,4,3,2,1]; var everyResult = number.every(function(item,index,array){ return (item > 2); }); alert(everyResult ); //false var filterResult = number.filter(function(item,index,array){ return (item > 2); }); alert(filterResult ); //[3,4,5,4,3] var someResult = number.some(function(item,index,array){ return (item > 2); }); alert(someResult ); //true var mapResult = number.map(function(item,index,array){ return item * 2; }); alert(someResult ); //[2,4,6,8,10,8,6,4,2] number.forEach(function(item,index,array){ //todo });
2.10归并方法
ECMAScript5还新增了两个归并数组的方法:reduce()笔reduceRight(),这两个方法都会迭代数组的所有项,然后构建一个最终返回的值。其中reduce()方法从数组的第一项开始,逐个遍历到最后。而reduceRight()方法则数组的最后一项开始,向前遍历到第一项。
如:
var values = [1,2,3,4,5]; var sum = values.reduce(function(prev, cur, index, array){ return prev + cur; //第一次prev是1,cur是2。第二次prev是3(1+2的结果), //cur是3(数组的第3项) }); alert(sum); //15 var sum = values.reduceRight(function(prev, cur, index, array){ return prev + cur;//第一次prev是5,cur是4 }); alert(sum); //15
3.日期类型
ECMAScript中的Date类型是在早期java的java.util.Date类基础上构建的。要创建一个日期对象,使用new操作符和Date构造函数即可,如:
var now = new Date();
ECMAScript5添加了Date.now()方法,返回表示调用这个方法时的日期和时间的毫秒数,支持Date.now()的浏览器包括IE9+、firefox3+、safari3+、opera10.5和chrome,在不支持它的浏览器中,使用+操作符把Date对象转换成字符串,也可以达到同样的目的.如:
var start = +new Date();
日期/时间方法:
getTime(): 返回表示日期的毫秒数
getFullYear(): 取得4位数的年份
getMonth(): 返回日期中的月份,其中0表示一月,11表示十二月
getDate(): 返回日期月份中的天数(1-31)
getDay(): 返回日期中星期的星期几(其中0表示星期日,6表示星期六)
getHours(): 返回日期中的小时数(0-23)
getMinutes(): 返回日期中的分钟数(0-59)
getSeconds(): 返回日期中的分秒数(0-59)
getMiliseconds(): 返回日期中的毫秒数
其余更多内容不再详细列出。
4.RegExp类型
ECMAScript通过RegExp类型来支持正则表达式。
var expression = /pattern/flags;
其中的模式(pattern)部分可以是任何简单或者复杂的正则表达式,每个正则表达式都可以带有一个或者多个标志(flags).正则表达式支持下列3个标志:
g:表示全局(global)模式,即模式将被应用于所有字符串,而非在发现第一个匹配项时立即停止
i: 表示不区分大小写模式,即在确定匹配项时忽略模式与字符串的大小写
m: 表示多行模式,即在达到一行文本末尾时还会继续查找下一行中是否存在与模式匹配的项。
正则表达式更多内容不再详细列出。
5.Function类型
5.1、函数其实是对象,每个函数都是Function类型的实例,而且都与其他引用类型一样具有属性和方法,因此,函数名实际上也是一个指向函数对象的指针,不会与某个函数绑定。函数的声明如下:
function sum(num1, num2) { return num1 + num2; }或
var sum = function(num1, num2) { return num1 + num2; }或
var sum = new Function("num1", "num2", "return num1 + num2");//不推荐,这种语法会导致 解析两次代码,从而影响性能注:使用不带圆括号的函数名是访问函数指针,而非调用函数。
5.2、javascript函数没有重载
function add(num) { return num + 100; } function add(num) { return num + 200; } var rs = add(100); alert(rs); //300
5.3、函数声明与函数表达式
解析器在向执行环境中添加数据时,解析器会先率先读取函数声明,并使其在执行任何代码之前可用(可以访问),函数表达式,则必须等到解析器执行到它所在的代码行,才会真正被解释执行。如:
alert(sum(10,10));//可以正常运行 function sum(num1, num2) { return num1 + num2; } alert(sum(10,10)); //会在运行期产生错误 var sum = function(num1, num2) { return num1 + num2; }
5.4、作为值的函数
因为JavaScript中的函数名本身就是变量,所以函数也可以当作值来使用。也就是说,不仅可以想传递参数一样把一个函数传递给另一个函数,而且可以将一个函数作为另一个函数的结果返回
5.5、函数的内部属性
5.5.1在函数内部,有两个特殊的对象:arguments和this。其中,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 * arguments.callee(num-1);//这样无论用什么名字都能完成递归调用 } } var trueFactorial = factorial; function factorial(num) { return 0; } alert(trueFactorial(5)); //120 alert(factorial(5)); //0
5.5.2 this指的是函数执行时所处的作用域。
5.5.3 每个函数都有一个非标准的caller属性,caller这个属性中保存着调用当前函数的函数的引用。如果在全局作用域中调用当前函数,它的值为null。如
function outer() { inner(); } function inner() { alert(inner.caller); //显示outer()函数的源代码 } outer(); 以上代码也可以通过arguments.callee.caller来访问,如: function outer() { inner(); } function inner() { alert(argument.callee.caller); //显示outer()函数的源代码 } outer()
5.6、函数属性和方法
每个函数都包含:length和prototype两个属性。length属性表示函数希望接收的参数个数,prototype是保存它们所有实例方法的真正所在。
每个函数都包含两个非继承而来的方法:apply()和call()。这两个方法的用途都是在特定的作用域中调用函数,实际上等于设置函数体内this对象的值。
apply()方法接收两个参数:一个是在其中运行函数的作用域,另一个是参数数组。其中第二个参数可以是Array的实例,也可以是arguments对象。如:
function sum(num1,num2){ return num1+num2; } function callSum(num1,num2){ return sum.apply(this,arguments); //传入aguments对象 } function callSum2(num1,num2){ return sum.apply(this,[num1,num2]); //传入数组 } alert(callSum(10,10)); //20 alert(callSum2(10,10)); //20call()方法与apply()的作用相同,区别仅在于接收参数的方式不同。call()方法的第一个参数是作用域没有变化,变化的是其余的参数必须直接传递给函数。如:
function sum(num1,num2){ return num1+num2; } function callSum(num1,num2){ return sum.call(this,num1,num2); } alert(callSum(10,10)); apply()和call()最强大的地方是能够扩充函数赖以运行的作用域,如: window.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
5.7、基本包装类型
5.7.1为了便于操作基本类型值,Javascript还提供了三个特殊的引用类型:Boolean、Number和String。这些类型与其他引用类型相似,同时也具有与各自的基本包装类型相应的特殊行为。
var s1 = "some text";
var s2 = s1.substring(2);
看上面代码,字符串是基本类型,但基本类型类型不是对象,逻辑上讲它们是没有方法的,可是这其中又发生着什么呢?
其实,当第二行代码访问是时,访问过程处于一种读取模式,也就是要从内存中读取这个字符串的值。而在读取模式中访问字符串,后台会自动完成下列处理:
(1)创建String类型的一个实例。
(2)在实例上调用指定的方法。
(3)销毁这个实例
代码如下:
var s1 = new String("some text"); var s2 = s1.substring(2); s1 = null;这样,基本的字符串值就变得和对象一样了。Boolean、Number也是如此。
5.7.2 引用类型与基本包装类型的主要区别就是对象的生命周期。使用new操作符创建的引用类型的实例,在执行流离开当前作用域之前都一直保存在内存中。而自动创 建的基本包装类型的对象,只存在于这一行代码的执行期(瞬间),然后立即销毁。这就意味着我们不能在运行时为属性添加属性和方法。
var s1 = "some text"; s1.color = "red"; alert(s1.color); //undifned我们是可以显示的调用Boolean、Number和String来创建基本包装类型,但不推荐这么做
相关推荐
JavaScript中的引用类型主要涉及到Object、Array、Date、RegExp和Function等类型。...以上内容概括了JavaScript引用类型的核心知识点,这些是深入理解JavaScript语言的重要基础,并广泛应用于各种Web开发场景中。
总结一下,我们从文件中提供的小例子中分析了JavaScript引用类型的工作方式,特别是引用类型变量赋值的过程和机制。通过这个例子,我们可以更好地理解JavaScript中对象的引用机制,以及在不同对象间进行赋值时可能...
本文实例讲述了JavaScript引用类型Object常见用法。分享给大家供大家参考,具体如下: 1、JavaScript数据类型 (1)基本类型 5种基本类型:Undefined、Null、Boolean、Number、String (2)引用类型 5种引用类型:Object...
本文实例讲述了JavaScript引用类型Array。分享给大家供大家参考,具体如下: 1、ECMAScript数组的特点 (1)ECMAScript数组的每一项可以保存任何类型的数据。 (2)ECMAScript数组的大小是可以动态调整的。 2、创建...
本文实例讲述了JavaScript引用类型Function。分享给大家供大家参考,具体如下: Function类型 函数是对象,函数名是指针:每个函数都是Function类型的实例。由于函数是对象,因此函数名是一个指向函数对象的指针,...
本文实例讲述了JavaScript引用类型Date常见用法。分享给大家供大家参考,具体如下: Date类型使用自UTC1970年1月1日午夜(零时)开始经过的毫秒数来保存日期。 创建日期对象的方法: (1)获得当前日期和时间 var ...
本文实例讲述了JavaScript引用类型RegExp基本用法。分享给大家供大家参考,具体如下: 1、正则表达式定义 三个标志:全局模式g,不区分大小写模式i,多行模式m。 1) 字面量定义 var pattern = /[fe]at/gim; 2) ...
主要介绍了JavaScript引用类型和基本类型详解的相关资料,需要的朋友可以参考下
在JavaScript编程中,理解基本类型和引用类型的区别非常重要,因为这关系到变量的存储、操作以及内存管理等核心概念。在给定的内容中,首先介绍了JavaScript中的基本数据类型和引用数据类型的定义、区别和联系,并...
JavaScript中的引用类型是编程语言中的一种数据结构,它允许我们将数据和相关操作组合在一起,使得代码更加灵活且易于管理。JavaScript中的引用类型主要包括Object、Array、Date、RegExp等,它们都是基于引用而不是...
总结来说,JavaScript的基本数据类型和引用类型在处理和存储上有显著区别,理解这两种类型对于编写高效且无错误的JavaScript代码至关重要。基本类型是不可变的,按值访问,而引用类型则是可变的,按引用访问,这决定...
在JavaScript中,引用类型是一种特殊的数据类型,它们代表了对象。与基本类型不同,基本类型(如String、Number、Boolean等)的值是直接存储在栈内存中的,而引用类型的值则存储在堆内存中,变量仅存储对这些对象的...
3. **JavaScript 引用类型的变量声明和赋值** 当声明一个引用类型的变量并赋值时,如`let myObject = {key: 'value'}`,myObject在栈中存储的是指向堆中对象的引用。如果将一个引用类型的变量赋值给另一个变量,如`...