JavaScript的原生引用类型

引用类型是一种数据结构,用于将数据和功能组织在一起,也常称做类。ECMAScript从技术上说是一门面向对象的语言,但它不具备传统的面向对象语言所支持的类和接口等基本结构。

 

Object类型

大多数引用类型的值都是Object类型的实例,创建object实例的方式有两种,第一种是使用new操作符,例如:

var myobj = new Object();

 

另一种方式是使用对象字面量表示法,例如:

var myobj = {

 name : "obj",

 weight : 20

};

 

如果留空其花括号,则可以定义只包含默认属性和方法的对象,例如:

var myobj = {};

 

一般来说,访问对象属性时使用的都是点表示法,也可以使用方括号一肤浅法来访问对象的属性,例如:

var myobj = {

 name = "obj"

}

alert(myobj["name"]);

 

Array类型

ECMAScript数组的每一项可以保存任何类型的数据,而且,数组的大小是可以动态调整的,即随着数据的添加自动增长以容纳新增数据。创建数组有两种形式,第一种是使用Array构造函数,例如:

var myarray = new Array();

 

也可以给Array构造函数传递数组要保存的项目数量,例如:

var myarray = new Array(20);

 

也可以向Array构造函数传递数组中应该包含的项,例如:

var myarray = new Array("a","b", "c");

 

使用Array构造函数时也可以省略new操作符,第二种创建数组的方式是使用数组字面量表示法,例如:

var myarray = ["a","b", "c"];

 

在读取数组的值时,要使用方括号并提供相应值的基于0的数字索引,例如:

alert(myarray[0]);

 

数组的项数保存在其length属性中,例如:

alert(myarray.length);

 

这个属性不是只读的,可以通过设置这个属性,从数组的末尾移除项或向数组中添加新项。

 

Array方法

所有对象都具有toLocaleString()、toString()和valueOf()方法,其中,调用数组的toString()和valueOf()方法会返回相同的值,即由数组中每个值的字符串形式拼接而成的一个以逗号分隔的字符串。实际上,它会调用数组每一项的toString()方法,而toLocaleString()方法则是调用数组每一项的toLocaleString()方法

ECMAScript数组也提供了一种让数组行为类似于其他数据结构的方法:push()和pop()。push()方法可以接收任意数量的参数,把它们逐个添加到数组末尾,并返回修改后数组的长度,而pop()方法则从数组末尾移除最后一项,然后返回移除的项,例如:

myarray.push("d");

myarray.pop();

 

此外,ECMAScript数组还提供了类似队列行为的方法:shift()和unshift()。shift()能够移除数组中的第一个项并返回该项,而unshift()相反,它能在数组前端添加任意个项并返回数组的长度,例如:

myarray.shift();

myarray.unshift("A","B");

 

数组中已经存在两个可以直接用来重排序的方法:reverse()和sort()。reverse()方法会反转数组项的顺序,而sort()方法按升序排列数组项,例如:

myarray.reverse();

myarray.sort();

 

最后,ECMAScript为操作已经包含在数组中的项提供了很多方法。其中,concat()方法也可基于当前数组中的所有项创建一个新数组,在没有传递参数的情况下,它只是复制当前数组并返回副本,如果传递给concat()方法的是一或多个数组,则该方法会将这些数组中的每一项都添加到结果数组中,如果传递的值不是数组,这些值就会被简单地添加到结果数组的末尾。

slice()方法能够基于当前数组中的一或多个项创建一个新数组,它可以接受一或两个参数,即要返回项的起始和结束位置,只有一个参数的情况下,slice()方法返回从该参数指定位置开始到当前数组末尾的所有项。

splice()方法的主要用途是向数组的中部插入项,它有很多种用法,如果提供两个参数(要删除的第一项的位置和要删除的项数),则会删除数组中的项,如果提供三个参数(起始位置,要删除项数,要插入的项),则可以实现在数组中插入元素。

 

Date类型

Date类型使用自UTC1970年1月1日午夜开始经过的毫秒数来保存日期,在使用这种存储格式的条件下,Date类型保存的日期能够精确到1970年1月1日之前或之后的285616年。

创建一个日期对象,使用new操作符和Date构造函数即可,例如:

var now = new Date();

 

在不传递参数的情况下,新创建的对象自动获得当前日期和时间,如果想根据特定的日期和时间创建日期对象,必须传入表示该日期的毫秒数。为了简化这一过程,ECMAScript提供了两个方法:Date.parse()和Date.UTC()。

Date.parse()方法接收一个表示日期的字符串参数,尝试根据这个字符串返回相应日期的毫秒数,如果传入Date.parse()方法的字符串不能表示日期,那么它会返回NaN,例如:

var mydate = new Date(Date.parse("May01, 2000"));

 

Date.UTC()方法同样也返回表示日期的毫秒数,但它与Date.parse()在构建值时使用不同的信息。Date.UTC()的参数分别是年份、基于0的月份(一月是0)、月中的哪一天(1到31)、小时数(0到23)、分钟、秒以及毫秒数,只有前两个参数是必须的,如果省略其他参数,则一律设为0,例如:

var mydate = new Date(Date.UTC(2000, 1, 1,8, 10, 10));

 

Date方法

Date类型也重写了toLocaleString()、toString()和valueOf()方法,但这些方法返回的值与其他类型中的方法不同。toLocaleString()方法会按照与浏览器设置的地区相适应的格式返回日期和时间。而toString()方法则通常返回带有时区信息的日期和时间。valueOf()方法根本不返回字符串,而是返回日期的毫秒表示。

 

RegExp类型

ECMAScript通过RegExp类型来支持正则表达式,语法如下:

var expression = /pattern/ flags;

 

其中模式(pattern)部分是正则表达式,每个正则表达式都可带有一或多个标志(flag)。正则表达式的匹配模式支持以下3个标志:

g: 表示全局模式,即模式将被用于所有字符串,而非在发现第一个匹配项时停止。

i: 表示不区分大小写模式。

m: 表示多行模式,即在到达一行文本末尾时还会继续查找下一行。

 

RegExp方法

RegExp对象的主要方法是exec(),它接受一个参数,即要应用模式的应符串,然后返回包含第一个匹配项信息的数组,没有匹配项的情况下返回null。返回的数组是Array()的实例,但包含两个额外属性index和input,index表示匹配项在字符串中的位置,input表示应用正则表达式的字符串,例如:

var input = "this is a test";

var pattern = /test/gi;

var matches = pattern.exec(text);

alert(matches.index);

alert(matches.input);

alert(matches[0]);

 

对于exec()方法,即使设置了模式g,每次也只返回一个匹配项,但每次调用都会在字符串中继续查找新匹配项。

另一个方法是test(),它接受一个字符串参数,在模式与参数匹配的情况下返回true,否则返回false,例如:

var input = "this is a test";

var pattern = /test/gi;

alert(pattern.test());

RegExp继承的toLocaleString()和toString()方法都会返回正则表达式的字面量。

 

RegExp属性

RegExp构造函数包含一些属性,这些属性可以通过两种方式访问它们,一个长属性名,一个短属性名(Opera不支持短属性名)。

RegExp构造函数属性

长属性名         短属性名       说明

Input         $_  最近一次要匹配的字符串(Opera不支持)。

lastMath $& 最近一次的匹配项(Opera不支持)。

lastParen $+  最近一次匹配的捕获组(Opera不支持)。

lastContext      $`   input字符串中lastMatch之前的文本。

multiline  $*  是否所有表达式都使用多行模式(IE和Opera不支持)。

rightContext    $‘    input字符串中lastMatch之后的文本。

 

Function类型

函数实际上是对象,每个函数都是Function对象的实例,而且都与其他引用类型一样具有属性和方法。函数名实际上也是一个指向函数的指针,不会与某个函数绑定。函数通常使用函数声明语法定义,例如:

function myfunc(myvar) {

 return myvar;

}

 

也可以使用如下方式:

var myfunc = function(myvar) {returnmyvar;};

 

第二种方式是使用Function构造函数,它可以接收任意数量的参数,但最后一个参数始终都被看成是函数体,例如:

var myfunc = newFunction("myvar", "return myvar;");

 

但是不推荐使用这种方式,因为这种语法会导致解析两次代码,从而影响性能,但这种语法有助于理解函数是对象的概念。

如果声明两个同名函数,结果就是后面的函数覆盖了前面的函数,因为函数名相当于指针。

解析器在执行环境中加载数据时,会率先读取函数声明,并使其在执行任何代码前可用,但函数表达式则必须等到解析器执行到它所在的代码行,才会被真正解析执行,例如:

alert(myfunc1(1)); //正确

function myfunc1(myvar) {

 return myvar;

}

alert(myfunc2(1)); //错误

var myfunc2 = function(myvar) {

 return myvar;

}

 

因为ECMAScript中函数名本身就是变量,所以函数也可以作为值来使用,比如可以将一个函数作为另一个函数的结果返回,例如:

function myfunc() {

 return function() {

   return 1;

  }

}

 

Function方法

每个函数都包含两个非继承而来的方法:apply()和call()。这两个方法的用途都是在特定的作用域中调用函数。

apply()方法接受两个参数,一个是在其中运行函数的作用域,另一个是参数数组,第二个参数可以是Array的实例,也可以是arguments对象,例如:

function myfunc1() {

}

function myfunc2() {

 return myfunc1.apply(this, arguments);

}

 

call()方法与apply()方法的作用相同,只是在于接收参数的方式不同,对于call()方法而言,第一个参数是作用域,其余参数都是直接传递给函数的,例如:

function myfunc1() {

}

function myfunc2(myvar) {

 return myfunc1.call(this, myvar);

}

 

Function属性

ECMAScript中的函数是对象,所有也有属性和方法,每个函数都包含两个属性:length和prototype。其中length属性表示函数希望接收的命名参数的个数。

对于ECMAScript中的引用类型而言,prototype是保存它们所有实例方法的真正所在,例如toString()和valueOf()等方法实际都保存在prototype名下,只不是通过各自对象的实例访问,在创建自定义引用类型及实现继承时,prototype属性极为重要。

在函数内部,有两个特殊的对象:arguments和this.arguments包含传入函数中的所有参数,这个对象还有一个callee属性,该属性是一个指针,指向拥有这个agruments对象的函数。this与Java和C#中的this大致类似,引用的是函数据以执行操作的对象,或者说this是函数在执行时所处的作用域。

 

本文为Anyforweb技术分享博客,需要了解网站建设及更多web应用相关信息,请访问anyforweb.com。

JavaScript的原生引用类型,布布扣,bubuko.com

JavaScript的原生引用类型

上一篇:java实战应用:MyBatis实现单表的增删改


下一篇:【python】UnboundLocalError: local variable 'counter' referenced before assignment