关于构造函数和原型prototype对象的理解

Posted wjmm

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于构造函数和原型prototype对象的理解相关的知识,希望对你有一定的参考价值。

构造函数

    1.什么是构造函数

      构造函数,主要用于对象创建的初始化,和new运算符一起用于创建对象,一个类可以有多个构造函数,因为函数名相同,所以只能通过参数的个数和类型不同进行区分,即构造函数的重构, 如果没有定义构造函数,那么该类会自动生成一个空参数的构造函数。   

       在javascript中,对象创建有二种方式:对象字面量和使用new表达式。

       对象字面量,每创建一个对象都要重新定义一次语句,不便于创建大量相同类型的对象

        技术分享图片

        new表达式,配合构造函数使用,例如var person1 = new Person("wmm",30);

   new操作符调用构造函数执行了以下几步:

   a.首先创建一个空的person1对象  ------   var person1 = {};

   b.将空对象person1的__proto__属性(其原型)指向构造函数的prototype对象,  ------  person1.__proto__ = Person.prototype;

   c.将构造函数的作用域赋值给person1对象,Person内的this指向实例化对象person1,  --------   Person.call(person1);

   d.返回新对象person1。 ------  return person1

    技术分享图片

    2.构造函数和普通函数的区别

   a.函数名称格式,构造函数一般首字母大写,而普通函数是一般首字母小写,使用驼峰式命名;

   b.是否需要new调用, 构造函数需要new操作符调用,普通函数不需要;

   c.this的指向,构造函数里this指向实例化对象,普通函数中this指向调用函数的对象,没对象调用时,默认指向window

   d.返回值,构造函数默认返回值为实例化对象,不用return返回值,而普通函数通过return语句返回值。

prototype对象

  每一个函数都有一个prototype属性,它指向一个对象的引用,每个实例化对象会从prototype指向的对象上继承属性。一旦原型对象上的属性发生了改变,实例化对象也会随之发生变化。

    每一个对象都会在内部初始化一个属性(__prototype__),属性__proto__所指向的对象是它的原型对象,即person1.__proto__  ===  Person.prototype。

    当我们访问一个对象的属性时,如果对象内部找不到该属性,就会去实例化对象的属性__proto__指向的对象里面去找这个属性,__proto__里面有它自己的__proto__ 属性,然后一直找下去,直到找到为止。如果直到最顶层的Object.prototype还是找不到,则返回undefined.

       所有一切对象的原型顶端,都是Object.prototype,Object.prototype的原型对象为null ,null对象没有自己的原型

function Person(name){
      this.name  =  name;
      this.eat = function(){
            console.log("food")
      }
}
Person.prototype.age = "20";
Person.prototype.height = function(){
  this.h = "160";
   console.log(this.h);
}
var person1 = new Person("吴默默"); var person2 = new Person("wumomo");

  每个实例化对象会继承构造函数的原型对象,实例化对象的属性__proto__指向的是原型对象,所以person1.__proto__  === person2.__proto__ === Person.prototype

  prototype对象除了自定义属性和__proto__属性外,还有一个constructor属性,constructor属性指向的是它所在的构造函数,如下图:

  技术分享图片

  实例化对象本身其实没有constructor属性,当找不到constructor属性时,就会根据person1.__proto__ 在其原型对象上查找。所以 person1.constructor  ===  person1.__proto__.constructor     ===  Person.prototype.constructor  ===  Person

  技术分享图片

  当重新定义prototype对象时,prototype对象原有的constructor属性会丢失,其constuctor属性会默认为Object(Person.prototype.constructor === Object)

   技术分享图片

构造函数和原型prototype的区别

   每创建一个实例化对象,都要调用一次构造函数,当创建多个实例化方法时,就要调用多次构造函数,这可能会导致内存溢出,性能较差,而实例化对象会继承prototype对象上的属性,使用原型prototype定义时,不管实例化多少个对象,都只调用一次,所以最好的解决方式是公共的方法和属性可以放在prototype原型中,其他的放在构造函数内。

扩展:

  isPrototypeOf() ----- 用于测试一个对象是否存在于另一个对象的原型链上     

    Person.prototype.isPrototypeOf(person1)     // ture

  instanceof -----  一个对象是否是这个特定类或者是它的子类的一个实例,形式为 object instanceOf constructor

    person1   instanceof   Person    // true

    person3   instanceof  Person   // false

  in运算符和hasOwnProperty()  ------  都是用来检测对象中是否存在某属性

    in运算符 :只要通过对象能访问到属性就返回true,否则返回false

    hasOwnProperty() : 只能检测到对象本身的属性,无法检查其原型链中是否具有该属性。

    技术分享图片






以上是关于关于构造函数和原型prototype对象的理解的主要内容,如果未能解决你的问题,请参考以下文章

关于原型原型链和原型继承的理解

原型链、constructor和prototype图文详解

javascript的构造函数和实例对象prototype和__proto__的区别,原型对象及构造器的理解

关于js中原型链的理解

关于prototype属性的理解

原型原型对象构造函数原型链理解