Web 技术研究所

我一直坚信着,Web 将会成为未来应用程序的主流

hasOwnProperty与对象的可复制性

  复制一个对象,就是把所有属于这个对象的属性都复制一遍。但是,“属于这个对象的属性”这个概念有些模糊。如果把JavaScript的普通对象都看做简单的哈希对象,那就会出现很多无法解释的问题,毕竟JavaScript也是有继承概念的。所以要搞清楚什么才是对象拥有的属性。
  即使只是一个字符串或一个数字,他们也会有很多继承而来的属性。比如toString和valueOf。虽然可以在对象上使用但是他们在定义时使用的局部变量和对象没有关系,而是与对象所继承的构造器有关。所以,这样继承而来的属性不属于对象本身的东西。判断属性是否是对象本身拥有的可以使用hasOwnProperty方法。
var X=function(){
  this.a=0;
};
X.prototype.b=0;
X.prototype.c=0;
var x=new X;
x.d=0;
x.c++;
console.log(x.hasOwnProperty("a")); //true
console.log(x.hasOwnProperty("b")); //false
console.log(x.hasOwnProperty("c")); //true
console.log(x.hasOwnProperty("d")); //true
  只有从构造器对象的原型中继承而来,并且没有经过任何赋值的属性才不属于那个实例对象。即使是默认属性,经过任何赋值以后也会变成实例对象所拥有的属性。 var x={};
console.log(x.hasOwnProperty("toString")); //false
x.toString=x.toString;
console.log(x.hasOwnProperty("toString")); //true
  拥有属性的概念大概就是这样了,然后是对象的可复制性问题。上一篇文章其实就有遇到这个问题,什么样的对象才是可复制的呢?其实可复制的对象,就是可序列化的对象。所谓序列化,就是把内存对象转换成某种格式存储到硬盘上。有些对象会使用到在调用堆栈中创建的数据句柄,由于调用堆栈的临时性,使得调用堆栈中的数据句柄会在一个作用域运行结束时被释放。而JavaScript的内存回收机制就会回收这些没有句柄指向的数据,这样对象引用的数据就不可用了。看到这里,你也许会有疑问。复制数据不是按值复制吗?为什么句柄释放了数据会不可用?确实,复制数据是按值复制的,但是这“复制数据”的概念仅仅是“复制对象拥有的属性”而已,在对象拥有的属性之外的东西就无法被复制,比如函数中使用函数外的变量时。看下面的例子 var f;
(function(){
  var a=2;
  f=function(){
    alert(a);
  };
})();
f(); //2
  由于匿名函数中定义的函数被放入全局变量f,而这个函数中需要使用到了匿名函数内的局部变量。所以匿名函数执行完毕之后对于这个局部变量的引用依然存在,它暂时不会被释放。只有等到f都被释放时它才会被回收。这样f这个函数就变得不可序列化,因为它对正变量的引用是一个内存地址,也许除了这个f还有其它对象也在共用它。于是我们就认为这个f是无法复制的。
  但是如果对象只是拥有某个方法,而这个方法是从构造器继承而来。也就是说,对象本身不具有那个函数,这时复制对象时就不会遍历到那个函数,对象就变得可复制。
var A=function(){};
A.prototype.test=function(){};
var a=new A;
console.log(a.hasOwnProperty("test")); //false
//a可复制

var B=function(){
  this.test=function(){};
};
var b=new B;
b.test=b.test;
console.log(b.hasOwnProperty("test")); //true
//b不复制
  最后要注意一点,虽然a是可以复制的,但是由于它是某个构造器的实例,而复制是把它作为普通对象来复制而已,因此复制以后和构造器关联的属性都会丢失。上面的这个a,复制之后得到的对象就丢失了constructor,继承的属性也会一并消失。因为构造器也只是内存中的一个数据而已,并不能保证序列化后不被释放。真正能完美序列化的数据只有基本类型的对象(数组)组合,这其实就是JSON,这也是为什么JSON这么受欢迎的原因。
  好了,貌似乱七八糟的又说了一大堆,不想看的直接无视吧,咱吃饭去啦 \(^_^)/
网名:
34.203.213.*
电子邮箱:
仅用于接收通知
提交 悄悄的告诉你,Ctrl+Enter 可以提交哦
神奇海螺
[查看全部主题]
各类Web技术问题讨论区
发起新主题
本模块采用即时聊天邮件通知的模式
让钛合金F5成为历史吧!
次碳酸钴的技术博客,文章原创,转载请保留原文链接 ^_^