对象的属性,方法及序列化

对象的三个属性

每一个对象都有与之相关的原型(prototype)、类(class)和可扩展性(extensible attribute)。下面将会展开讲述这些属性有什么作用,以及如何查询和设置它们。

  • 原型属性

对象的原型属性是用来继承属性的,这个属性如此重要,以至于我们经常把“o的原型属性”直接叫做“o的原型”。

原型属性是在实例对象创建之初就设置好的,通过对象直接量创建的对象使用Object.prototype作为它们的原型。通过new创建的对象使用构造函数的prototype属性作为它们的原型。通过Object.create()创建的对象使用第一个参数(也可以是null)作为它们的原型。

在ECMAScript 5中,将对象作为参数传入Object.getPrototypeOf()可以查询它的原型,通过new表达式创建的对象,通常继承一个constructor属性,这个属性指代创建这个对象的构造函数。注意,通过对象直接量或Object.create()创建的对象包含一个名为constructor的属性,这个属性指代Object()构造函数。因此,constructor.prototype才是对象直接量的真正的原型,但对于通过Object.create()创建的对象则往往不是这样。

要想检测一个对象是否是另一个对象的原型(或处于原型链中),请使用isPrototypeOf()方法。例如,可以通过p.isPrototypeOf(o)来检测p是否是o的原型:
 

var p={x:1};//定义一个原型对象
var o=Object.create(p);//使用这个原型创建一个对象
p.isPrototypeOf(o)//=>true:o继承自p
Object.prototype.isPrototypeOf(o)//=>true:p继承自Object.prototype

需要注意的是,isPrototypeOf()函数实现的功能和instanceof运算符非常类似。 

  • 可扩展性

对象的可扩展性用以表示是否可以给对象添加新属性。所有内置对象和自定义对象都是显式可扩展的,宿主对象的可扩展性是由JavaScript引擎定义的。在ECMAScript 5中,所有的内置对象和自定义对象都是可扩展的,除非将它们转换为不可扩展的,同样,宿主对象的可扩展性也是由实现ECMAScript 5的JavaScript引擎定义的。

ECMAScript 5定义了用来查询和设置对象可扩展性的函数。通过将对象传入Object.esE xtensible(),来判断该对象是否是可扩展的。如果想将对象转换为不可扩展的,需要调用Object.preventExtensions(),将待转换的对象作为参数传进去。注意,一旦将对象转换为不可扩展的,就无法再将其转换回可扩展的了。同样需要注意的是,preventExtensions()只影响到对象本身的可扩展性。如果给一个不可扩展的对象的原型添加属性,这个不可扩展的对象同样会继承这些新属性。

可扩展属性的目的是将对象“锁定”,以避免外界的干扰。对象的可扩展性通常和属性的可配值性与可写性配合使用,ECMAScript 5定义的一些函数可以更方便地设置多种属性。

Object.seal()和Object.preventExtensions()类似,除了能够将对象设置为不可扩展的,还可以将对象的所有自有属性都设置为不可配置的。也就是说,不能给这个对象添加新属性,而且它已有的属性也不能删除或配置,不过它已有的可写属性依然可以设置。对于那些已经封闭(sealed)起来的对象是不能解封的。可以使用Object.isSealed()来检测对象是否封闭。

Object.freeze()将更严格地锁定对象——“冻结”(frozen)。除了将对象设置为不可扩展的和将其属性设置为不可配置的之外,还可以将它自有的所有数据属性设置为只读(如果对象的存取器属性具有setter方法,存取器属性将不受影响,仍可以通过给属性赋值调用它们)。使用Object.isFrozen()来检测对象是否冻结。

Object.preventExtensions()、Object.seal()和Object.freeze()都返回传入的对象,也就是说,可以通过函数嵌套的方式调用它们:

//创建一个封闭对象,包括一个冻结的原型和一个不可枚举的属性
var o=Object.seal(Object.create(Object.freeze({x:1}),
{y:{value:2,writable:true}}));

序列化对象

对象序列化(serialization)是指将对象的状态转换为字符串,也可将字符串还原为对象。ECMAScript 5提供了内置函数JSON.stringify()和JSON.parse()用来序列化和还原JavaScript对象。这些方法都使用JSON作为数据交换格式,JSON的全称是"JavaScript Object Notation"——JavaScript对象表示法,它的语法和JavaScript对象与数组直接量的语法非常相近:

o={x:1,y:{z:[false,null,""]}};//定义一个测试对象

s=JSON.stringify(o);//s是'{"x":1,"y":{"z":[false,null,""]}}'

p=JSON.parse(s);//p是o的深拷贝

JSON的语法是JavaScript语法的子集,它并不能表示JavaScript里的所有值。支持对象、数组、字符串、无穷大数字、true、false和null,并且它们可以序列化和还原。NaN、Infinity和-Infinity序列化的结果是null,日期对象序列化的结果是ISO格式的日期字符串(参照Date.toJSON()函数),但JSON.parse()依然保留它们的字符串形态,而不会将它们还原为原始日期对象。函数、RegExp、Error对象和undefined值不能序列化和还原。JSON.stringify()只能序列化对象可枚举的自有属性。对于一个不能序列化的属性来说,在序列化后的输出字符串中会将这个属性省略掉。JSON.stringify()和JSON.parse()都可以接收第二个可选参数,通过传入需要序列化或还原的属性列表来定制自定义的序列化或还原操作。

对象方法

所有的JavaScript对象都从Object.prototype继承属性(除了那些不通过原型显式创建的对象)。这些继承属性主要是方法,因为JavaScript程序员普遍对继承方法更感兴趣。下面将对定义在Object.prototype里的对象方法展开讲解,这些方法非常好用而且使用广泛,但一些特定的类会重写这些方法。

  • toString()方法

toString()方法没有参数,它将返回一个表示调用这个方法的对象值的字符串。在需要将对象转换为字符串的时候,JavaScript都会调用这个方法。比如,当使用“+”运算符连接一个字符串和一个对象时或者在希望使用字符串的方法中使用了对象时都会调用toString()。

默认的toString()方法的返回值带有的信息量很少(尽管它在检测对象的类型时非常有用),例如,下面这行代码的计算结果为字符串"[object Object]":

var s={x:1,y:1}.toString();

由于默认的toString()方法并不会输出很多有用的信息,因此很多类都带有自定义的toString()。例如,当数组转换为字符串的时候,结果是一个数组元素列表,只是每个元素都转换成了字符串,再比如,当函数转换为字符串的时候,得到函数的源代码。

  • toLocaleString()方法

除了基本的toString()方法之外,对象都包含toLocaleString()方法,这个方法返回一个表示这个对象的本地化字符串。Object中默认的toLocaleString()方法并不做任何本地化自身的操作,它仅调用toString()方法并返回对应值。Date和Number类对toLocaleString()方法做了定制,可以用它对数字、日期和时间做本地化的转换。Array类的toLocaleString()方法和toString()方法很像,唯一的不同是每个数组元素会调用toLocaleString()方法转换为字符串,而不是调用各自的toString()方法。

  • toJSON()方法

Object.prototype实际上没有定义toJSON()方法,但对于需要执行序列化的对象来说,JSON.stringify()方法会调用toJSON()方法。如果在待序列化的对象中存在这个方法,则调用它,返回值即是序列化的结果,而不是原始的对象。

  • valueOf()方法

valueOf()方法和toString()方法非常类似,但往往当JavaScript需要将对象转换为某种原始值而非字符串的时候才会调用它,尤其是转换为数字的时候。如果在需要使用原始值的上下文中使用了对象,JavaScript就会自动调用这个方法。默认的valueOf()方法不足为奇,但有些内置类自定义了valueOf()方法(比如Date.valueOf())。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值