聊聊原型对象

122 阅读3分钟

构造函数

说起原型对象不得不先说一说构造函数,什么是构造函数?使用new调用一个函数,构造函数是用来创造对象的函数。

  • 构造函数new的工作原理
  1. 创建空对象
  2. this指向这个对象
  3. 给对象赋值
  4. 返回这个对象
function Person(name,age,sex){
            //(1)创建空对象   {}
            //(2)this指向这个对象  this = {}
            //(3)对象赋值
            this.name = name
            this.age = age
            this.sex = sex
            this.eat = function(){
            console.log('eat');
            }
            //(4)返回这个对象 return this
        }

        let p1 = new Person('张三',20,'男')
        let p2 = new Person('李四',20'女')
        console.log(p1,p2)
  • 一些注意的点
  1. 构造函数首字母一般大写,为了提醒调用者不要忘记new关键字

  2. 如果在构造函数内部 手动return

    (1) return 值类型 : 无效,还是返回new创建对象

    (2) return 引用类型:有效,会覆盖new创建的对象

  • 构造函数内部的方法:会浪费内存资源

    让我们来思考这样一个问题:p1和p2都有eat方法,而是函数体相同。但是他们是同一个函数吗?答案当然是否定的,不是同一个,因为每次调用一次构造函数,内部都会执行一次function,就会在堆中开辟出一个新的空间。虽然里面的代码都是一样的,但是地址不同。所以每调用一次就会开辟一个新空间造成了内存资源的浪费。 console.log( p1.eat == p2.eat )//false

  • 使用全局函数解决内存的浪费

let eat = function() {
           console.log("吃东西")
         }

         let learn = function() {
           console.log("学习")
         }

         function Person(name, age) {
           this.name = name
           this.age = age
           this.eat = eat
           this.learn = learn
         }

         let p1 = new Person("张三", 18)
         let p2 = new Person("李四", 20)
         console.log(p1, p2)

将方法变成全局函数,现在p1里面的eat和p2里面的eat是不是同一个呢?没错,现在是的了,因为构造函数内部并没有重新创建一个函数,而是拷贝了eat的地址赋值。无论你调用构造函数多少次,都是直接拷贝的eat的地址。 console.log( p1.eat == p2.eat )//true但是这又导致了一个新的问题:全局变量污染。怎么解决呢?使用对象。

  • 使用对象解决内存浪费+全局变量污染
let obj = {
        eat: function() {
          console.log("吃东西")
        },
        learn: function() {
          console.log("学习")
        }
      }

      function Person(name, age) {
        this.name = name
        this.age = age
        this.eat = obj.eat
        this.learn = obj.learn
      }

      let p1 = new Person("张三", 18)
      let p2 = new Person("李四", 20)
      console.log(p1, p2)

这样看上貌似就解决了内存浪费和全局变量污染的问题,但是屠龙勇士终成恶龙,现在obj成了最大的变量污染。怎么解决呢?原型对象应运而生。

原型对象

当你创建一个构造函数的时候,JS就会自动给你创建一个原型对象来给你装这些方法。

  • 原型对象是什么? 任何函数在声明的时候,系统会自动帮你创建一个对象,称之为原型对象
  • 原型对象的作用? 解决 内存浪费+变量污染
  • 原型对象相关属性
  1. prototype: 属于构造函数,指向原型对象
  2. __proto__: 属于实例对象,指向构造函数
  3. constractor: 属于原型对象,指向构造函数

用图来表示三者之间的关系可能更直观一点,自己画的,比较丑,不过影响不大。

无标题.png

  • __proto__:这个属性不是web标准,很多浏览器都不会显示,在实际开发中都不会用,用于学习研究。

让我们来验证一下构造函数、原型对象、实例对象三者之间的关系。

 console.log( p1.__proto__.constructor )//Person
 console.log( Person.prototype === p1.__proto__ )//true

ok,今天的原型对象就聊到这里,下次进一步的聊一下原型链。

respect