WithCoderWithCoderWithCoder

Javascript原型对象之原型有关的几个属性和方法

    前面的文章介绍了Javascript原型的一些基本概念,“Javascript原型对象之概念简介”。本文介绍与原型有关的几个属性和方法。

    1. prototype属性

    在创建一个函数后,每个函数会自动创建一个 prototype 属性(任意函数中都有,但我们通常只关注构造函数的 prototype 属性) ,它指向了这个函数的原型对象。

    具体可以参考前面的文章。           

    2. constructor属性

    当我们查看 prototype 对象的属性时,可以看到一个 constructor 属性存在于原型对象中。实际上,它指向了前面创建的函数(构造函数)。

    看下面的代码:   

    <script>
        function A() {
        }

        // 函数A的prototype属性对象中,constructor属性指向函数A
        console.log(A.prototype.constructor === A); // true
    </script>

    根据需要,我们可以将函数的 prototype 属性指向新的对象。但是这个时候有个问题,新的 prototype 对象的constructor属性就不再指向此函数了。

    看下面的代码:

    <script>

        function A() {
        }

        function B() {
        }

        // 将函数A的prototype指向B的prototype
        A.prototype = B.prototype;
        // 函数A的prototype属性发生变化,其中的constructor也同样发生了变化,指向了函数B
        console.log(A.prototype);
        console.log(A.prototype.constructor === A); // false
    </script>

    不过,如果 constructor 对你很重要,可以将函数赋值给 prototype 的 constructor 属性,如下:   

    // 将 prototype 属性对象的 constructor 重新指向 函数A
    A.prototype.constructor = A;

    3. __proto__ 属性(注意:左右各是2个下划线)

    在把函数用作构造函数时,实例化一个新的对象之后,这个对象中默认会有一个不可访问的属性 [[prototype]] , 这个属性就指向了构造方法的原型对象。但是在个别浏览器中,也提供了对这个属性[[prototype]]的访问(chrome浏览器和火狐浏览器,ie浏览器不支持)。访问方式:obj.__proto__。但是开发者尽量不要用这种方式去访问,因为操作不慎会改变这个对象的继承原型链。

    查看下面的代码:

    <script>
        function A() {
        }

        //直接给A的原型指定对象字面量。则这个对象的constructor属性不再指向A函数
        A.prototype = {
            constructor: A// 将 prototype 属性对象的 constructor 重新指向 函数A
            name: "neil"
        };

        // 实例化对象
        var a = new A();

        // 实例对象的__proto__和构造函数的prototype指向同一个对象
        console.log(a.__proto__ === A.prototype);   // true
    </script>

    4. hasOwnProperty() 方法

    当我们访问一个实例对象的属性的时候,这个属性既有可能来自实例对象本身,也有可能来自这个实例对象的[[prototype]]属性指向的原型。

    那么如何判断这个对象的来源呢?使用 hasOwnProperty() 方法,可以判断一个属性是否来自对象本身。    

    <script type="text/javascript">
        function A() {
        }

        A.prototype.name = "neil"// 原型对象添加属性name

        // 实例化对象
        var a = new A();
        a.age = 100// 实例对象添加属性age

        // age属性是直接在a属性中添加,所以是true
        console.log("age属性是对象本身的:" + a.hasOwnProperty("age"));

        // name属性是在原型中添加的,所以是false
        console.log("name属性是对象本身的:" + a.hasOwnProperty("name"));

        // sex属性不存在,所以也是false
        console.log("sex属性是存在于对象本身:" + a.hasOwnProperty("sex"));
    </script>

    因此,通过 hasOwnProperty() 方法可以判断一个属性对象是否是实例对象本身添加的。但是此方法不能判断属性是否存在于原型对象中,因为这个属性有可能不存在。也即是说,对于在原型中的属性和不存在的属性此方法都会返回fasle。

    如何判断一个属性是否存在于原型中呢?

    5. in 操作符

    in操作符用来判断一个属性是否存在于实例对象中。但是在查找这个属性时候,先在实例对象本身中找,如果找不到再去原型中找。换句话说,只要对象和原型中有一个地方存在这个属性,就返回true。

    <script type="text/javascript">
        function A() {
        }

        // 原型中添加属性name
        A.prototype.name = "neil";

        // 实例化对象
        var a = new A();
        // 实例对象添加属性age
        a.age = 100

        console.log("age" in a);    // age属性是实例对象本身添加的,所以true

        console.log("name" in a);   // name属性在原型中存在,所以true

        console.log("sex" in a); // sex属性对象和原型中都不存在,所以false
    </script>

    回到前面的问题,如何判断一个属性是否存在于原型中

    如果一个属性存在,但是没有在对象本身中,则一定存在于原型中。

欢迎分享交流,转载请注明出处:WithCoder » Javascript原型对象之原型有关的几个属性和方法