原型对象,扩展原型对象

构造函数

构造函数就是为了创建出很多具有相同属性和方法的实例对象

  function Person(name) {
            this.mName = name;
            this.sayName = function() {
                return this.mName;
            }
        };
        // 使用构造函数创建实例化对象
        var p1 = new Person('张三');
        var p2 = new Person('李四');

每一个实例对象都有sayName方法。但是这样每次创建一个对象都会产生一个一样的sayName方法,这很占用空间,而且也不符合代码书写规范(减少重复性)。

当我们这样写时

 // 创建构造函数
      function Person(name) {
            this.mName = name;
            // this.sayName = function() {
            //     return this.mName;
            // }
        };
      Person.prototype.sayName = function () {
        return this.mName;
      }
        // 使用构造函数创建实例化对象
        var p1 = new Person('张三');
        var p2 = new Person('李四');
        p1.sayName();

发现p1.sayName()依然能够执行。
检测p1中是否有sayName这个属性

 console.log(p1.hasOwnProperty('sayName'));// false

返回为false,说明p1中确实没有sayName属性。

这是因为p1作为构造函数Person的实例化对象,它继承了来自Person的prototype属性里面的方法。

这里就要看一下实例对象的__proto__属性,
先打印一下

        console.log(p1.__proto__);
        console.log(Person.prototype);

在这里插入图片描述
两个属性一摸一样。

再进行一下对比

 console.log(Person.prototype === p1.__proto__);

结果是true。
说明两个属性是完全相等的。

获取对象的__proto__属性指向的构造函数的prototype属性。也就是原型对象

**使用Object.getPrototypeOf()获取对象的原型对象

  console.log(Object.getPrototypeOf(p1));

在这里插入图片描述
就是Person的prototype属性。
这个对象里sayName是我们自己添加的,constructor构造函数的意思,里面的构造函数指向自身,__proto__这个属性指向另一个原型对象。
总结:

  • 每一个实例化成员都有一个__proto__属性,这个属性里面指向向其构造函数的prototype属性。
  • 而每一个构造函数都有一个prototype属性,属性值是一个对象,称为原型对象。

当调用某种方法或者查找某种属性时,首先会先在自身查找,如果自身没有这个属性或者方法,就会去对象的__proto__属性中去查找,也就是构造函数的prototype中调用查找。

原型链

任何对象都有原型对象,也就是prototype属性,任何原型对象也是一个对象,该对象就有__proto__属性,这样一层一层往上找,就形成了一条链,我们称此为原型链;
每一个实例对象都有一个__proto__属性,指向的构造函数的原型对象,构造函数的原型对象也是一个对象,也有__proto__属性,这样一层一层往上找就形成了原型链。

原型的修改或改变

可以通过给构造函数的prototype属性添加属性和方法来让创建的实例对象继承。
1、普通的暴力方法

        Person.prototype = {
          sayName:function(){
          return this.mName;
            
          }

直接用一个新的对象替换掉原来的原型对象,但是这样不建议使用,因为原型对象中还保存这其他的信息,这样就会将其他的属性给抹除掉了。

2、使用 . 添加属性和方法

Person.prototype.sayName = function () {
        return this.mName;
      }

这种添加方式可以使用,但是还是不够完美,因为这样添加上去的属性是可以被实例对象使用for in遍历时遍历到的,正常的属于继承的属性是不应该被子元素遍历到的。

3、使用Object.defineProperty()方法,可以添加属性时,定义属性内部的特性。

        Object.defineProperty(Person.prototype,'sayName',{
          configurable:false,
          enumerable:false,
          writable:false,
          value:function(){
            return this.mName;
          }
        })
        //定义多个
     Object.defineProperties(Person.prototype, {
      sayName: {
        configurable: false,
        enumerable: false,
        writable: false,
        value: function () {
          return this.mName;
        },
        fullNmae: {
          configurable: false,
          enumerable: false,
          writable: false,
          value: '尼古拉丝儿'
        }
      }
    })

这样添加的属性就不会被遍历出来。

4、Object.create()方法创建一个新对象,使用现有的对象来提供新创建的对象的__proto__。
语法:Object.create(proto, [propertiesObject])
proto:新创建对象的原型对象。
propertiesObject:可选。若没有指定为 undefined,则是要添加到新创建对象的可枚举属性(即其自身定义的属性,而不是其原型链上的枚举属性)对象的属性描述符以及相应的属性名称。这些属性对应Object.defineProperties()的第二个参数
返回值:一个新对象,带着指定的原型对象和属性。
例外:如果propertiesObject参数不是 null 或一个对象,则抛出一个 TypeError 异常。

 var p2 = Object.create(p1,{
      fullNmae: {
          configurable: false,
          enumerable: false,
          writable: false,
          value: '尼古拉丝儿'
          //这些属性不写默认是false
        }
    });

还可以利用这个创建一个空的对象。

var obj3 = Object.create({});

创建的空对象的原型也是一个空对象。

Object的原型对象给我们提供的方法

1.hasOwnProperty() 方法会返回一个布尔值,指示对象自身属性中是否具有指定的属性

 console.log(p1.getOwnProper('mName'));// true

与他相似的还有in操作符,但是in会算上原型链中可以访问的属性

2.propertyIsEnumerable() 方法返回一个布尔值,表示指定的属性是否可枚举。

  console.log(p1.propertyIsEnumerable('mName'));//true

3、 isPrototypeOf() 方法用于在person的原型链上搜寻是否有object原型

  console.log(Person.prototype.isPrototypeOf(p1));//true

4、 toString:把对象用字符串的形式表示出来

 console.log(p1.toString());//[object Object]

5、 valueOf() 方法返回指定对象的原始值。一般只有js内置的对象才会有原始值。没有原始值的对象会返回自身。

 console.log(p1.valueOf());// 自身
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值