pwindy  
在完成任务的同时,还需要不断“复盘”,不论你多么的忙,都需要留下时间思考,可以思考哪些地方做的好,哪些地方我们可以改进,应该如何改进,注重总结才是王道

首先来了解几个常见的名称(以下解释依据本文实力代码场景)

Object:对象(对象的值可以为任意类型,array,object,function......)

prototype:原型对象

constructor:构造函数

__proto__:指向Person.prototype的原型对象

 

一、函数的prototype属性

JavaScript规定,每一个构造函数都有一个特别的属性prototype,该属性的值是一个对象,这个对象就是我们常说的“原型对象”。这个原型对象的所有属性和方法,都会被构造函数的实例对象继承。

1.现,有如下函数Person

     function Person(name){
         this.name = name
     }

2.Person函数的prototype属性(即,原型对象),如下

根据打印出来的结果显示:

2.1.Person.prototype的属性包含两项constructor(构造函数)和__proto__

2.2.其中Person.prototype的构造函数constructor为Person函数本身,即

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

 2.3.Person.prototype的__proto__属性指向对象的原型对象,即

      函数是Object的实例。

          Person.prototype.__proto__ == Object.prototype

 二、通过prototype和__proto__来实现继承

通过将对象A的__proto__属性赋值为对象B

即,A.__proto__ = B

此时使用A.__proto__便可以访问B的属性和方法

通过以上可以得出结论:

JavaScript可以在两个对象之间创建一个关联,使得一个对象可以访问另一个对象的属性和方法,从而实现了继承。

 三、构造函数和实例对象

     function Person(name){
         this.name = name
     }
     var lily = new Person('Lily')

              其中:lily.__proto__ = Person.prototype

结论:

  1. 每个函数的原型对象(Person.prototype)都拥有constructor属性,指向该原型对象的构造函数(Person)
  2. 使用构造函数(Person)可以创建对象( new Person() ),创建的对象称为实例对象(lily)
  3. 实例对象通过将__proto__属性指向构造函数的原型对象(Person.prototype),实现了该原型对象的继承(lily.__proto__=Person.prototype)

四、prototype和__proto__的关系

  1. 每个对象都有__proto__属性来标识自己所继承的原型对象,但只有函数才有prototype属性。
  2. 对于函数来说,每个函数都有一个prototype属性,该属性为该函数的原型对象。
  3. 通过将实例对象的__proto__属性赋值为其构造函数的原型对象prototype,JavaScript可以使用构造函数创建对象的方式来实现继承。

 五、通过原型链访问对象的方法和属性

1.首先会优先在该对象上搜寻

2.如果找不到,还会一次层层向上搜索该对象的原型对象、该对象的原型对象的原型对象等(套娃告警)

    lily.__proto__ = Person.prototype
    Person.prototype.__proto__ = Object.prototype
    Object.prototype.__proto__ = null

3.JavaScript中的所有对象都是来自Object

4.Object.prototype.__proto__ ===  null

5.null没有原型,并作为这个原型链中的最后一个环节

6.JavaScript会遍历访问对象的整个原型链

7.如果最后依然找不到,此时会认为该对象的属性值为undefined

   8.示例解释,基于原型链的对象属性的访问过程,如下

 六、通过原型链访问属性的性能特点

function Person(name){
   this.name = name  
}

var lily = new Person('Lily');
lily.__proto__ = Person.prototype
Person.prototype.__proto__ = Object.prototype
Object.prototype.__proto__ = null

当试图访问不存在的属性时,会遍历整个原型链,在原型链上查找属性比较耗时,对性能有副作用,这在性能要求苛刻的情况下很重要。

七、JavaScript中实现继承的方式

1.经典继承(盗用构造函数)

可以实现实例属性私有,但要求类型只能通过构造函数来定义

function Person(name){
  // 私有属性,不共享
  this.name = name    
}

2.组合继承(JavaScript中常见的继承模式)

通过将需要复用、共享的方法定义在父类原型上,结合构造函数和原型式继承的优点

function Person(name){
  // 私有属性,不共享
  this.name = name    
}

Parent.prototype.speak = function(){
  console.log("hello")  
}

3.原型式继承

引用类型的属性被所有实例共享,无法做到实例私有

4.寄生式继承

 

posted on 2022-08-05 14:39  pwindy  阅读(92)  评论(0)    收藏  举报