JavaScript之面向对象学习二(原型属性对象与in操作符)获取对象中所有属性的方法

1、原型属性对象于in操作符之in单独使用

有两种方式使用in操作符:单独使用和在for-in循环中使用。在单独使用中,代码如下:

   function Person(){
    }
        Person.prototype.name="张三";
        Person.prototype.age=22;
        Person.prototype.job="coder";
        Person.prototype.sayName=function(){
        alert(this.name);
    }

    var person1=new Person();
    var person2=new Person();
    alert(person1.hasOwnProperty("name"));  //输出:false,因为person1并没有自己的实例属性!
    alert("name" in person1);  //输出:true,因为person1含有[[Prototype]]属性,该属性是一个指针,指向Person构造函数的原型属性对象。
    // person1所指向的原型属性对象里面含有name属性,所以person1实例能够访问"name"属性。

    person1.name="李四";
    alert(person1.name); //输出"李四", 因为person1.name="李四";给person1实例定义了一个name属性,该属性将原型属性对象中的name属性屏蔽了
    //屏蔽的原因是当执行person1.name代码时,JS会先到person1实例中寻找name属性,如果实例中没有该属性,则会去原型属性对象中寻找name属性
    //所以这里在person1实例中找到了name属性,则JS就不会再去原型属性对象那个中寻找该属性,原型对象中的同名属性就会被忽略

    alert(person1.hasOwnProperty("name"));//输出:true   因为person1.name="李四"给person1实例定义了一个实例属性
    alert("name" in person1);//输出:true  person1实例对象里面含有name属性,所以"name"属性可以访问

    alert(person2.name);
    alert(person2.hasOwnProperty("name"));  //输出:false  person2实例没有自己的实例属性
    alert("name" in person2); //输出:true  person2所指向的原型属性对象里面含有name属性,所以person1实例能够访问"name"属性。

    delete person1.name;
    alert(person1.hasOwnProperty("name"));  //输出:false  因为delete person1.name;person1的实例被删除,所以此时person1没有实例属性
    alert("name" in person1);  ////输出:true  person1所指向的原型属性对象里面含有name属性,所以person1实例能够访问"name"属性。

观察上面的代码我们发现,当in操作符单独使用的时候有一个规律如下:

属性    in   对象的实例

他的用法就是:判断这个属性能否被对象的实例所访问到,如果对象实例能访问到属性返回true,如果不能返回false;

注意:这里的属性可以是对象实例的属性,也可以是对象实例的[[Prototype]]属性指针,所指向的原型对象;

下面是结合Object.hasOwnProperty()和in判断一个属性到底是实例属性,还是实例对应原型对象的额属性,代码如下:

function Person(){
    }
        Person.prototype.name="张三";
        Person.prototype.age=22;
        Person.prototype.job="coder";
        Person.prototype.sayName=function(){
        alert(this.name);
    }
    var person1=new Person();
    var person2=new Person();
    /*
     @param object    ---对象的实例名
     @param name      ---需要判断的对象属性
     功能:判断name是实例的原型属性对象的属性还是实例的实例属性
     */
    function hasPrototypePrototype(object,name){
        return !object.hasOwnProperty(name) && (name in object);
    }
    alert(hasPrototypePrototype(person1,"name"));  //输出:true  说明person1能访问"name"属性,person1的实例属性中没有"name"属性,说明"name"属性是原型对象中属性
    person1.name="李四";
    alert(hasPrototypePrototype(person1,"name"));  //输出:false 有两种情况 1、"name"属性既不是实例属性,也不是原型对象属性  2、person1能访问"name"属性,person1有"name"属性

2、原型属性对象与与in操作符之for-in结合使用

在使用for-in循环时,返回的是所有能够通过对象访问的、可枚举的属性,既包括实例中的属性又包括原型对象中的属性;

注意:屏蔽了原型中不可枚举属性(即将[[Enumerable]]设置为false的属性)也会在for-in循环中返回,因为根据规定,所有开发人员定义的属性都是可枚举的---只有IE8即更早版本中例外

代码如下:

  var o={
        toString:function(){
            return "My Object";
        }
    }
    for(var property in o){
        if(property=="toString"){
            alert("Found toString");  //在IE8 中不显示
        }
    }

输出:Found toString,

注意:在IE中存在一个bug,因为其实现认为原型的toString()方法被打上了值为false的[[Enumerable]]标记(所以该属性无法被循环),因此应该跳过该属性,所以我们就看不到警告框,所以该bug会影响默认不可枚举的所有属性和方法,包括:hasOwnProperty()、propertyIsEnumerable()、toLocaleString、toString、valueOf()。

ECMAScript 5也将constructor和prototype属性的[[Enumerable]]特性设置为false,但并不是所有的浏览器都照此实现。

3、使用Object.keys()方法获取指定对象中所有可枚举的实例属性

ECMAScript 5中提供了Object.keys()方法。这个方法接收一个对象作为参数,返回一个包含所有可枚举属性的字符串数组,代码如下:

    function Person(){
    }
    Person.prototype.name="张三";
    Person.prototype.age=22;
    Person.prototype.job="coder";
    Person.prototype.sayName=function(){
        alert(this.name);
    }
   var keys=Object.keys(Person.prototype);   //Person.prototype =》获取Person构造函数的原型属性对象 ;
    //Object.keys(Person.prototype)=》获取原型属性对象的所有属性名,是键不是值
    alert(keys); //输出name、age、job、sayName

    var person=new Person();
    person.name="李四";
    person.age=22;
    var personkeys=Object.keys(person);  //获取person实例的属性不包含其原型对象的属性。
    alert(personkeys); //输出:name、age

    var allkeys=Object.getOwnPropertyNames(Person.prototype); //获取Person构造函数原型对象的所有属性(包括不可枚举的属性([[Enumerable]]设为false的属性))
    alert(allkeys);//输出:constructor,name,age,job,sayName   注意:在ECMAScript 5中constructor属性是不可枚举的

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏LanceToBigData

JavaSE(十)之反射

开始接触的时候可能大家都会很模糊到底什么是反射,大家都以为这个东西不重要,其实很重要的,几乎所有的框架都要用到反射,增加灵活度。到了后面几乎动不动就要用到反射。...

214100
来自专栏GreenLeaves

JavaScript之面向对象学习七(动态原型模式、寄生构造函数模式、稳妥构造函数模式创建自定义类型)

一、动态原型模式 在面向对象学习六中的随笔中,了解到组合构造函数模式和原型模式创建的自定义类型可能最完善的!但是人无完人,代码亦是如此! 有其他oo语言经验的开...

242100
来自专栏nummy

JS遍历属性

对象属性可枚举,表示该属性的值不可修改,可认为该属性是常量。 如何定义不可枚举的属性?

18520
来自专栏五毛程序员

java反射机制入门3

28370
来自专栏python3

python 迭代器

一类是generator,包括生成器和带yield的generator function。

10110
来自专栏coding for love

JS原生引用类型解析3-Function类型

(注1:如果有问题欢迎留言探讨,一起学习!转载请注明出处,喜欢可以点个赞哦!) (注2:更多内容请查看我的目录。)

9910
来自专栏Micro_awake web

JavaScript OOP(三):prototype原型对象(即构造函数的prototype属性)

通过构造函数生成的实例化对象,无法共享属性或方法(即每个实例化对象上都有构造函数中的属性和方法);造成了一定的资源浪费 1 function Obj(name...

22270
来自专栏大闲人柴毛毛

稳扎稳打JS——“继承”

JS使用原型链实现“继承” JS是“基于对象”的语言,因此没有继承。但可以使用JS的特性实现“继承”——原型链。 JS使用_proto_属性构造原型链,如 ...

42040
来自专栏ios 技术积累

swift 函数

下面定义名称 sayHello 的函数,只有一个 String 类型的 name 参数,函数返回值为 String 类型。

13130
来自专栏GreenLeaves

JavaScript之面向对象学习一

1、通过Object构造函数和对象字面量来创建对象缺点:使用同一个接口创建很多的对象,会产生大量的重复代码。比如我需要创建人的对象,并且需要三类人,医生、工程师...

19460

扫码关注云+社区

领取腾讯云代金券