【又见JavaScript】原型prototype、constructor、__proto__相关知识点

相关概念:

  • 原型prototype其实是function对象的一个属性
  • 打印出结果来看,会发现它也是一个对象
function Handphone() { }
console.log(Handphone.prototype); // {constructor:f}

  • prototype是定义构造函数构造出的每个对象公共祖先

    所有被该构造函数构造出的对象都可以继承原型上的属性和方法

    构造函数中有的属性对象也会有,所以不会再去原型上找

    在代码中理解:

    function Handphone(color,brand) {
      this.color = color;
      this.brand = brand;
      this.screem = '18:9';
      this.system = 'Android';
    }
    
    Handphone.prototype.rom = '64G';
    Handphone.prototype.ram = '6g';
    Handphone.prototype.screem = '16:9'
    
    var hp1 = new Handphone('red','小米');
    var hp2 = new Handphone('black','华为');
    
    console.log(hp1.rom); // 64G
    console.log(hp1.ram); // 6g
    console.log(hp1.screem); // 16:9'
    
  • 往往不需要修改的属性和方法,一般会写在原型上,需要配置的写在构造函数内部

  • 通过实例化出来的对象,对其继承的原型进行“增删改查”测试:

    • 查(对象访问其内部属性):
      若是构造函数中没有同时设置一样的属性名和值,其构造函数实例化的对象可以访问其继承的原型上的属性和方法

      function Test(){}
      Test.prototype.name = 'prototype';
      var test = new Test();
      console.log(test.name); // prototype
      
    • 增:
      实例化的对象是无法增加其继承的原型上的属性

      function Test(){}
      Test.prototype.name = 'prototype';
      var test = new Test();
      test.num = 1;
      console.log(Test.prototype,test); // 前者中没有num属性,后者中有
      

    • 改:
      实例化的对象是无法修改其继承的原型上的属性 ,最后只会在其自身中增加一个属性
      只可以对它重新赋值

      function Test(){}
      Test.prototype.name = 'prototype';
      var test = new Test();
      test.name = 'proto';
      console.log(Test.prototype,test);
      

    • 删:

      实例化的对象是无法删除其继承的原型上的属性

      function Test(){}
      Test.prototype.name = 'prototype';
      var test = new Test();
      delete test.name;
      console.log(Test.prototype,test);
      

constructor 构造器,存在于prototype下

  • constructor (默认) -> 构造函数本身,即,存的是实例化前的东西

    function Handphone(color) {
      this.color = color;
    }
    console.log(Handphone.prototype);
    

  • constructor 可以被修改

    function Telephone() {}
    function Handphone(color) {
      this.color = color;
    }
    Handphone.prototype = {
      constructor: Telephone,
    }
    console.log(Handphone.prototype);
    

__proto__属性

  • __proto__ 是new,实例化对象之后产生的! 是属于每个实例化对象的

  • 实质上就是一个装载每个实例化对象的原型的容器

  • 系统内置的属性,所以写法是__xxx__,目的是提醒不要乱改

    function Car(){}
    Car.prototype.name = 'Benz';
    var car = new Car();
    console.log(car);
    
  • 因为在实例化之前,构造函数里是没有它的,但是构造函数本身也有一个prototype属性

    相当于:实例化后(new)一个对象后,系统在其对象中隐式声明了一个this对象,并且默认在里面存了一个__proto__ 对象,最后return this ===> 由此可得,__proto__其实是属于实例化对象的

  • 那么,__proto__ 里面存的是什么?🤷‍♀️

    以上面的例子为例,存的是实例化后的对象继承的原型Car.prototype,所以原型与构造函数其实是无关的

    上面的代码中,实例化后的car可以得到name属性值的原因为:this中没有的属性,系统会自动访问其__proto__属性下的原型去寻找,所以它与构造函数无关;再次印证,实质上就是一个装载每个实例化对象的原型的容器

  • 这个实例化对象的原型中,Car.prototype 中存着constructor,它指向构造函数Car()本身 ,意义之一,在于实例化后告诉你它的构造函数是谁;

  • __proto__ 是否能被修改?

    答案是:可以的。 可以试试以下代码:

    function Person(){}
    Person.prototype.name = '张三';
    var p1 = {
      name: '李四'
    }
    var person = new Person();
    console.log(person.__proto__);
    

    // 此时故意将__proto__修改为p1
    function Person(){}
    Person.prototype.name = '张三';
    var p1 = {
      name: '李四'
    }
    var person = new Person();
    console.log(person.name);  // 张三
    person.__proto__ = p1;
    console.log(person.name);  // 李四
    
  • 在实例化后将prototype重写的情况:

    上面的情况,是在实例化后重写的原型prototype,所以和实例化对象的prototype没有关系,这一点是可以印证,prototype是实例化对象的!

    如果在实例化前重写的原型prototype,所以后续实例化对象的原型也会改变!

    Car.prototype.name = 'Benz';
    function Car(){}
    
    var car = new Car();
    
    Car.prototype = {
      name : 'Mazda'
    }
    console.log(car.name);  // Benz
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值