zoukankan      html  css  js  c++  java
  • js 对象中属性的来源

    通过对对象的创建,继承的理解,我们可以发现,在平时使用时,prototype和实例中的属性都可以直接通过this.para来调用。而且优先使用实例中的属性,然后在根据原型链一步步的向上寻找属性的位置,直到找到为止。在平时,这些机制对于我们使用对象有很大帮助,但是有时候会产生实例属性覆盖原型属性,使我们调用不到正确的值。这时候我们就首先要判断我们现在能得到的属性来自于哪个位置。

    首先是in操作符,in操作符可以判断某个属性在对象中能否被访问,不管是在实例中还是原型中。看以下这个例子:

     1 function Myobj(){
     2     this.name='Tom';
     3     this.age='20';
     4 }
     5 Myobj.prototype.getName = function(){
     6     console.log(this.name);
     7 }
     8 var obj = new Myobj();
     9 console.log('name' in obj);
    10 console.log('getName' in obj);

    最后两个console.log返回的都是true,这样就有了可以确定某个属性是否在这个对象中了。

    接下来就是hasOwnProperty了,它可以判断某个属性是来自实例中还是原型中。对于在实例中的属性会返回true,而在原型中的属性会返回false,看下面这个例子:

     1 function Myobj(){
     2 }
     3 Myobj.prototype.name = 'Peter';
     4 Myobj.prototype.getName = function(){
     5     console.log(this.name);
     6 }
     7 var obj = new Myobj();
     8 console.log(obj.hasOwnProperty('name'));        //false
     9 obj.name = 'Tom';
    10 console.log(obj.hasOwnProperty('name'));        //true
    11 delete obj.name;
    12 console.log(obj.hasOwnProperty('name'));        //false

    通过hasOwnProperty方法的使用,我们可以清楚的知道我们访问的到底是实例属性,还是来自原型或原型链中的属性。在调用obj.hasOwnProperty('name')时,只有重写name属性,才能使name成为一个实例属性,那么才会返回true。delete删除了这个name实例属性后,hasOwnProperty又会返回false了。

    根据以上的这些函数的特性,我们可以编写一个函数来检测属性是否来自于原型:

    1 function isParaFromProto(obj,para){
    2     if(para in obj){
    3         return (!obj.hasOwnProperty(para))?true:false;
    4     }else{
    5         throw new Error('para not in obj');
    6     }
    7 }

    函数的使用如下:

     1 function Myobj(){
     2 }
     3 Myobj.prototype.name = 'Peter';
     4 Myobj.prototype.getName = function(){
     5     console.log(this.name);
     6 }
     7 var obj = new Myobj();
     8 console.log(isParaFromProto(obj,'name'));        //true
     9 obj.name = 'Tom';
    10 console.log(isParaFromProto(obj,'name'));        //false
    11 delete obj.name;
    12 console.log(isParaFromProto(obj,'name'));        //true

    关于in操作符

    in操作符主要有两个用处,一个是以上介绍过的,另一个是用在for语句中。但是两处地方在一些设置更改以后还是有不同的地方。Object中定义有defineProperty方法,它可以设置对象中属性的特性(不能设置原型中的属性),通过将Enumerable属性设置为false,那么for in循环就无法遍历到这个属性了,就想object中原生的__proto__属性。但是这时用in操作符判断属性是否在对象中时,还是可以返回true的。

     1 function Myobj(){
     2     this.name = 'Tom';
     3 }
     4 var obj = new Myobj(),arr = [];
     5 for(var i in obj){
     6     arr.push(i);
     7 }
     8 console.log(arr);                  //['name']
     9 console.log('name' in obj);        //true
    10 arr=[];
    11 Object.defineProperty(obj,'name',{enumerable:false});
    12 for(var i in obj){
    13     arr.push(i);
    14 }
    15 console.log(arr);                  //[]
    16 console.log('name' in obj);        //true
  • 相关阅读:
    优雅的使用Python之软件管理
    优雅的使用python之环境管理
    SpriteSheet精灵动画引擎
    【译】AS3利用CPU缓存
    走在网页游戏开发的路上(十一)
    自定义路径创建Cocos2d-x项目
    C++静态库与动态库
    C++对象模型
    超时空英雄传说2复仇魔神完全攻略&秘技
    从头写个http client(java)
  • 原文地址:https://www.cnblogs.com/cyITtech/p/3564189.html
Copyright © 2011-2022 走看看