欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

更简单的原型语法和原型语法的动态性

程序员文章站 2022-05-08 16:37:56
...

更简单的原型语法 为减少不必要的输出,也从视觉上更好的封装原型的功能,用一个包含所有属性和方法的对象字面量来重写整个原型对象:

  function Person() {
   }

   Person.prototype = {
       name : "Hongbin",
       age : 21,
       sex : true,
       sayHello : function () {
           console.log("Hello "+this.name);
       }
   };

存在问题:上面相当于重写了默认的Person.prototype,prototype中的constructor属性也随之改变,不在指向Person。此时instanceof操作符还能返回正确的结果,但通过constructor已经无法确定对象的类型了:

    var person1 = new Person();

    console.log(person1 instanceof Person);//true
    console.log(person1.constructor == Person);//false
    console.log(person1.constructor == Object);//true

如果constructor指向整的很重要,可以手动设置值

    Person.prototype = {
        constructor : Person,
        name : "Hongbin",
        age : 21,
        sex : true,
        sayHello : function () {
            console.log("Hello "+this.name);
        }
    };

    var person2 = new Person();
    console.log(person2.constructor == Person);//true

但以这种方式设置constructor的属性,导致constructor的[[Enumerable]]值变成了true,默认情况下值为false,如果使用的兼容ECMAScript5的JavaScript引擎,可以用Object.defineProperty()方法设置constructor属性

    Object.defineProperty(Person.prototype,'constructor',{
        value:Person,
        enumerable:false
    });
    // console.log(Object.getOwnPropertyDescriptors(Person.prototype));//constructor: {writable: true, enumerable: false, configurable: true, value: ƒ}

到此解决constructor指向因重置prototype属性而产生变化问题

原型链的动态性:原型查找是一次搜索行为,因此我们对原型对象做的任何操作都能立刻反映到实例上–即使先创建了实例后修改原型也是如此:
在设置prototype.name为一个新的值之前打印的实例属性也发生变化
更简单的原型语法和原型语法的动态性
下图中,我们可以看到在constructor没有设置的时候创建的person1并没有任何改变,甚至constructor依旧没有指向Person,是因为它定义在constructor指向Person之前,
更简单的原型语法和原型语法的动态性
我们将person2也放到constructor指向Person之前定义发现
更简单的原型语法和原型语法的动态性
person2也出现了和person1一样的抓概况,对比一下
更简单的原型语法和原型语法的动态性
person2又恢复正常,
通过person1和person2对比我们发现:

重写的原型对象切断了现有原型与任何之前已经存在的对象实例之间的联系;它们引用的仍是最初的原型

//更简单的原型语法 为减少不必要的输出,也从视觉上更好的封装原型的功能,用一个包含所有属性和方法的对象字面量来重写整个原型对象:
    function Person() {
    }

    Person.prototype = {
        name : "Hongbin",
        age : 21,
        sex : true,
        sayHello : function () {
            console.log("Hello "+this.name);
        }
    };
    //问题:上面相当于重写了默认的Person.prototype,prototype中的constructor属性也随之改变,不在指向Person。此时instanceof操作符还能返回正确的结果,但通过constructor已经无法确定对象的类型了:
    var person1 = new Person();

    console.log(person1 instanceof Person);//true
    console.log(person1.constructor == Person);//false
    console.log(person1.constructor == Object);//true
    //如果constructor指向整的很重要,可以手动设置值
    Person.prototype = {
        constructor : Person,
        name : "Hongbin",
        age : 21,
        sex : true,
        sayHello : function () {
            console.log("Hello "+this.name);
        }
    };

    var person2 = new Person();
    console.log(person2.constructor == Person);//true
    //但以这种方式设置constructor的属性,导致constructor的[[Enumerable]]值变成了true,默认情况下值为false,如果使用的兼容ECMAScript5的JavaScript引擎,可以用Object.defineProperty()方法设置constructor属性
    Object.defineProperty(Person.prototype,'constructor',{
        value:Person,
        enumerable:false
    });
    // console.log(Object.getOwnPropertyDescriptors(Person.prototype));//constructor: {writable: true, enumerable: false, configurable: true, value: ƒ}
    //到此解决constructor指向因重置prototype属性而产生变化问题

    //原型链的动态性:原型查找是一次搜索行为,因此我们对原型对象做的任何操作都能立刻反映到实例上--即使先创建了实例后修改原型也是如此:
    console.log(person2);
    Person.prototype.name = "new name!";
    console.log(person2);//new name!

    console.log(person1);//Hongbin
    console.log(person1.constructor == Person);//false
    //person1并没有改变,constructor也是如此,是因为它定义在constructor指向Person之前