ECMAScript 专题
专题目录
您的位置:ECMAScript > ECMAScript 专题 > ECMAScript 引用类型
ECMAScript 引用类型
作者:--    发布时间:2019-11-20

引用类型通常叫做类(class)。

本教程会讨论大量的 ecmascript 预定义引用类型。

引用类型通常叫做类(class),也就是说,遇到引用值,所处理的就是对象。

本教程会讨论大量的ecmascript预定义引用类型。

从现在起,将重点讨论与已经讨论过的原始类型紧密相关的引用类型。

注意:从传统意义上来说,ecmascript并不真正具有类。事实上,除了说明不存在类,在ecma-262中根本没有出现“类”这个词。ecmascript定义了“对象定义”,逻辑上等价于其他程序设计语言中的类。

提示:本教程将使用术语“对象”。

对象是由 new 运算符加上要实例化的对象的名字创建的。例如,下面的代码创建object对象的实例:

var o = new object();

这种语法与java语言的相似,不过当有不止一个参数时,ecmascript要求使用括号。如果没有参数,如以下代码所示,括号可以省略:

var o = new object;

注意:尽管括号不是必需的,但是为了避免混乱,最好使用括号。

提示:我们会在对象基础这一章中更深入地探讨对象及其行为。

这一节的重点是具有等价的原始类型的引用类型。

object 对象

object对象自身用处不大,不过在了解其他类之前,还是应该了解它。因为ecmascript中的object对象与java中的java.lang.object相似,ecmascript中的所有对象都由这个对象继承而来,object对象中的所有属性和方法都会出现在其他对象中,所以理解了object对象,就可以更好地理解其他对象。

object 对象具有下列属性:

constructor
对创建对象的函数的引用(指针)。对于object对象,该指针指向原始的object()函数。
prototype
对该对象的对象原型的引用。对于所有的对象,它默认返回object对象的一个实例。

object 对象还具有几个方法:

hasownproperty(property)
判断对象是否有某个特定的属性。必须用字符串指定该属性。(例如,o.hasownproperty("name"))
isprototypeof(object)
判断该对象是否为另一个对象的原型。
propertyisenumerable
判断给定的属性是否可以用for...in语句进行枚举。
tostring()
返回对象的原始字符串表示。对于object对象,ecma-262没有定义这个值,所以不同的ecmascript实现具有不同的值。
valueof()
返回最适合该对象的原始值。对于许多对象,该方法返回的值都与tostring()的返回值相同。

注释:上面列出的每种属性和方法都会被其他对象覆盖。

boolean 对象

boolean对象是boolean原始类型的引用类型。

要创建boolean对象,只需要传递boolean值作为参数:

var obooleanobject = new boolean(true);

boolean对象将覆盖object对象的valueof()方法,返回原始值,即true和false。tostring()方法也会被覆盖,返回字符串"true"或"false"。

遗憾的是,在ecmascript中很少使用boolean对象,即使使用,也不易理解。

问题通常出现在boolean表达式中使用boolean对象时。例如:

var ofalseobject = new boolean(false);
var bresult = ofalseobject && true;	//输出 true

在这段代码中,用false值创建boolean对象。然后用这个值与原始值true进行and操作。在boolean运算中,false和true进行and操作的结果是false。不过,在这行代码中,计算的是ofalseobject,而不是它的值false。

正如前面讨论过的,在boolean表达式中,所有对象都会被自动转换为true,所以ofalseobject的值是true。然后true再与true进行and操作,结果为true。

注意:虽然你应该了解boolean对象的可用性,不过最好还是使用boolean原始值,避免发生这一节提到的问题。

参阅

如需更多有关boolean对象的信息,请访问javascript boolean对象参考手册

number 对象

正如你可能想到的,number对象是number原始类型的引用类型。要创建number对象,采用下列代码:

var onumberobject = new number(68);

您应该已认出本章前面小节中讨论特殊值(如number.max_value)时提到的number对象。所有特殊值都是number对象的静态属性。

要得到数字对象的number原始值,只需要使用valueof()方法:

var inumber = onumberobject.valueof();

当然,number类也有tostring()方法,在讨论类型转换的小节中已经详细讨论过该方法。

除了从object对象继承的标准方法外,number对象还有几个处理数值的专用方法。

tofixed() 方法

tofixed()方法返回的是具有指定位数小数的数字的字符串表示。例如:

var onumberobject = new number(68);
alert(onumberobject.tofixed(2));  //输出 "68.00"

在这里,tofixed()方法的参数是2,说明应该显示两位小数。该方法返回"68.00",空的字符串位由0来补充。对于处理货币的应用程序,该方法非常有用。tofixed() 方法能表示具有0到20位小数的数字,超过这个范围的值会引发错误。

toexponential() 方法

与格式化数字相关的另一个方法是toexponential(),它返回的是用科学计数法表示的数字的字符串形式。

与tofixed()方法相似,toexponential()方法也有一个参数,指定要输出的小数的位数。例如:

var onumberobject = new number(68);
alert(onumberobject.toexponential(1));  //输出 "6.8e+1"

这段代码的结果是"6.8e+1",前面解释过,它表示6.8x101。问题是,如果不知道要用哪种形式(预定形式或指数形式)表示数字怎么办?可以用toprecision()方法。

toprecision() 方法

toprecision()方法根据最有意义的形式来返回数字的预定形式或指数形式。它有一个参数,即用于表示数的数字总数(不包括指数)。例如,

var onumberobject = new number(68);
alert(onumberobject.toprecision(1));  //输出 "7e+1"

这段代码的任务是用一位数字表示数字68,结果为"7e+1",以另外的形式表示即70。的确,toprecision()方法会对数进行舍入。不过,如果用2位数字表示68,就容易多了:

var onumberobject = new number(68);
alert(onumberobject.toprecision(2));  //输出 "68"

当然,输出的是"68",因为这正是该数的准确表示。不过,如果指定的位数多于需要的位数又如何呢?

var onumberobject = new number(68);
alert(onumberobject.toprecision(3));  //输出 "68.0"

在这种情况下,toprecision(3)等价于tofixed(1),输出的是"68.0"。

tofixed()、toexponential()和toprecision()方法都会进行舍入操作,以便用正确的小数位数正确地表示一个数。

提示:与boolean对象相似,number对象也很重要,不过应该少用这种对象,以避免潜在的问题。只要可能,都使用数字的原始表示法。

参阅

如需更多有关number对象的信息,请访问javascript number对象参考手册

string 对象

string对象是string原始类型的对象表示法,它是以下方式创建的:

var ostringobject = new string("hello world");

string对象的valueof()方法和tostring()方法都会返回string类型的原始值:

alert(ostringobject.valueof() == ostringobject.tostring());	//输出 "true"

如果运行这段代码,输出是"true",说明这些值真的相等。

注释:string对象是ecmascript中比较复杂的引用类型之一。同样,本节的重点只是string类的基本功能。更多的高级功能请阅读本教程相关的章节,或参阅javascript string对象参考手册

length 属性

string对象具有属性length,它是字符串中的字符个数:

var ostringobject = new string("hello world");
alert(ostringobject.length);	//输出 "11"

这个例子输出的是"11",即"hello world"中的字符个数。注意,即使字符串包含双字节的字符(与ascii字符相对,ascii字符只占用一个字节),每个字符也只算一个字符。

charat() 和 charcodeat() 方法

string对象还拥有大量的方法。

首先,两个方法charat()和charcodeat()访问的是字符串中的单个字符。这两个方法都有一个参数,即要操作的字符的位置。

charat()方法返回的是包含指定位置处的字符的字符串:

var ostringobject = new string("hello world");
alert(ostringobject.charat(1));	//输出 "e"

在字符串"hello world"中,位置1处的字符是"e"。在“ecmascript原始类型”这一节中我们讲过,第一个字符的位置是0,第二个字符的位置是1,依此类推。因此,调用charat(1)返回的是"e"。

如果想得到的不是字符,而是字符代码,那么可以调用charcodeat()方法:

var ostringobject = new string("hello world");
alert(ostringobject.charcodeat(1));	//输出 "101"

这个例子输出"101",即小写字母"e"的字符代码。

concat() 方法

接下来是concat()方法,用于把一个或多个字符串连接到string对象的原始值上。该方法返回的是string原始值,保持原始的string对象不变:

var ostringobject = new string("hello ");
var sresult = ostringobject.concat("world");
alert(sresult);		//输出 "hello world"
alert(ostringobject);	//输出 "hello "

在上面这段代码中,调用concat()方法返回的是"hello world",而string对象存放的仍然是"hello "。出于这种原因,较常见的是用加号(+)连接字符串,因为这种形式从逻辑上表明了真正的行为:

var ostringobject = new string("hello ");
var sresult = ostringobject + "world";
alert(sresult);		//输出 "hello world"
alert(ostringobject);	//输出 "hello "

indexof() 和 lastindexof() 方法

迄今为止,已讨论过连接字符串的方法,访问字符串中的单个字符的方法。不过如果无法确定在某个字符串中是否确实存在一个字符,应该调用什么方法呢?这时,可调用indexof()和lastindexof()方法。

indexof()和lastindexof()方法返回的都是指定的子串在另一个字符串中的位置,如果没有找不到子串,则返回-1。

这两个方法的不同之处在于,indexof()方法是从字符串的开头(位置0)开始检索字符串,而lastindexof()方法则是从字符串的结尾开始检索子串。例如:

var ostringobject = new string("hello world!");
alert(ostringobject.indexof("o"));		输出 "4"
alert(ostringobject.lastindexof("o"));	输出 "7"

在这里,第一个"o"字符串出现在位置4,即"hello"中的"o";最后一个"o"出现在位置7,即"world"中的"o"。如果该字符串中只有一个"o"字符串,那么indexof()和lastindexof()方法返回的位置相同。

localecompare() 方法

下一个方法是localecompare(),对字符串进行排序。该方法有一个参数 - 要进行比较的字符串,返回的是下列三个值之一:

  • 如果string对象按照字母顺序排在参数中的字符串之前,返回负数。
  • 如果string对象等于参数中的字符串,返回0
  • 如果string对象按照字母顺序排在参数中的字符串之后,返回正数。

注释:如果返回负数,那么最常见的是-1,不过真正返回的是由实现决定的。如果返回正数,那么同样的,最常见的是1,不过真正返回的是由实现决定的。

示例如下:

var ostringobject = new string("yellow");
alert(ostringobject.localecompare("brick"));		//输出 "1"
alert(ostringobject.localecompare("yellow"));		//输出 "0"
alert(ostringobject.localecompare("zoo"));		//输出 "-1"

在这段代码中,字符串"yellow" 与3个值进行了对比,即"brick"、"yellow"和"zoo"。由于按照字母顺序排列,"yellow"位于"brick"之后,所以localecompare()返回 1;"yellow"等于"yellow",所以localecompare()返回0;"zoo"位于"yellow"之后,localecompare()返回 -1。再强调一次,由于返回的值是由实现决定的,所以最好以下面的方式调用localecompare()方法:

var ostringobject1 = new string("yellow");
var ostringobject2 = new string("brick");

var iresult = ostringobject1.localecompare(ostringobject2);

if(iresult < 0) {
  alert(ostringobject1 + " comes before " + ostringobject2);
} else if (iresult > 0) {
  alert(ostringobject1 + " comes after " + ostringobject2);
} else {
  alert("the two strings are equal");
}

采用这种结构,可以确保这段代码在所有实现中都能正确运行。

localecompare()方法的独特之处在于,实现所处的区域(locale,兼指国家/地区和语言)确切说明了这种方法运行的方式。在美国,英语是ecmascript实现的标准语言,localecompare()是区分大小写的,大写字母在字母顺序上排在小写字母之后。不过,在其他区域,情况可能并非如此。

slice() 和 substring()

ecmascript提供了两种方法从子串创建字符串值,即slice()和substring()。这两种方法返回的都是要处理的字符串的子串,都接受一个或两个参数。第一个参数是要获取的子串的起始位置,第二个参数(如果使用的话)是要获取子串终止前的位置(也就是说,获取终止位置处的字符不包括在返回的值内)。如果省略第二个参数,终止位就默认为字符串的长度。

与concat()方法一样,slice()和substring()方法都不改变string对象自身的值。它们只返回原始的string值,保持string对象不变。

var ostringobject = new string("hello world");
alert(ostringobject.slice("3"));		//输出 "lo world"
alert(ostringobject.substring("3"));		//输出 "lo world"
alert(ostringobject.slice("3", "7"));		//输出 "lo w"
alert(ostringobject.substring("3", "7"));	//输出 "lo w"

在这个例子中,slice()和substring()的用法相同,返回值也一样。当只有参数3时,两个方法返回的都是"lo world",因为"hello"中的第二个"l"位于位置3上。当有两个参数"3"和"7"时,两个方法返回的值都是"lo w"("world" 中的字母"o"位于位置7上,所以它不包括在结果中)。

为什么有两个功能完全相同的方法呢?事实上,这两个方法并不完全相同,不过只在参数为负数时,它们处理参数的方式才稍有不同。

对于负数参数,slice()方法会用字符串的长度加上参数,substring()方法则将其作为0处理(也就是说将忽略它)。例如:

var ostringobject = new string("hello world");
alert(ostringobject.slice("-3"));		//输出 "rld"
alert(ostringobject.substring("-3"));	//输出 "hello world"
alert(ostringobject.slice("3, -4"));		//输出 "lo w"
alert(ostringobject.substring("3, -4"));	//输出 "hel"

这样即可看出slice()和substring()方法的主要不同。

当只有参数-3时,slice()返回"rld",substring()则返回"hello world"。这是因为对于字符串"hello world",slice("-3")将被转换成slice("8"),而substring("-3")将被转换成substring("0")。

同样,使用参数3和-4时,差别也很明显。slice()将被转换成slice(3, 7),与前面的例子相同,返回"lo w"。而substring()方法则将两个参数解释为substring(3, 0),实际上即substring(0, 3),因为substring()总把较小的数字作为起始位,较大的数字作为终止位。因此,substring("3, -4")返回的是"hel"。这里的最后一行代码用来说明如何使用这些方法。

tolowercase()、tolocalelowercase()、touppercase() 和 tolocaleuppercase()

最后一套要讨论的方法涉及大小写转换。有4种方法用于执行大小写转换,即

  • tolowercase()
  • tolocalelowercase()
  • touppercase()
  • tolocaleuppercase()

从名字上可以看出它们的用途,前两种方法用于把字符串转换成全小写的,后两种方法用于把字符串转换成全大写的。

tolowercase()和touppercase()方法是原始的,是以java.lang.string中相同方法为原型实现的。

tolocalelowercase()和tolocaleuppercase()方法是基于特定的区域实现的(与localecompare()方法相同)。在许多区域中,区域特定的方法都与通用的方法完全相同。不过,有几种语言对unicode大小写转换应用了特定的规则(例如土耳其语),因此必须使用区域特定的方法才能进行正确的转换。

var ostringobject = new string("hello world");
alert(ostringobject.tolocaleuppercase());	//输出 "hello world"
alert(ostringobject.touppercase());		//输出 "hello world"
alert(ostringobject.tolocalelowercase());	//输出 "hello world"
alert(ostringobject.tolowercase());		//输出 "hello world"

这段代码中,touppercase()和tolocaleuppercase()输出的都是"hello world",tolowercase()和tolocalelowercase()输出的都是"hello world"。一般来说,如果不知道在以哪种编码运行一种语言,则使用区域特定的方法比较安全。

提示:记住,string对象的所有属性和方法都可应用于string原始值上,因为它们是伪对象。

instanceof 运算符

在使用typeof运算符时采用引用类型存储值会出现一个问题,无论引用的是什么类型的对象,它都返回"object"。ecmascript引入了另一个java运算符instanceof来解决这个问题。

instanceof运算符与typeof运算符相似,用于识别正在处理的对象的类型。与typeof方法不同的是,instanceof方法要求开发者明确地确认对象为某特定类型。例如:

var ostringobject = new string("hello world");
alert(ostringobject instanceof string);	//输出 "true"

这段代码问的是“变量 ostringobject是否为string对象的实例?”ostringobject的确是string对象的实例,因此结果是"true"。尽管不像typeof方法那样灵活,但是在typeof方法返回"object"的情况下,instanceof方法还是很有用的。

网站声明:
本站部分内容来自网络,如您发现本站内容
侵害到您的利益,请联系本站管理员处理。
联系站长
373515719@qq.com
关于本站:
编程参考手册