Loading

原型与原型链

  • 为什么要有原型的出现?
    •  

       

       

       

       

       

       

       

  • 所有函数都有一个特别的属性:

    • prototype : 显式原型属性

  • 所有实例对象都有一个特别的属性:

    • __proto__ : 隐式原型属性

  • 讲原型的时候,我们应该先要记住以下几个要点,这几个要点是理解原型的关键:

    1、所有的引用类型(数组、函数、对象)可以自由扩展属性(除null以外)。

    2、所有的引用类型都有一个’_ _ proto_ _'属性(也叫隐式原型,它是一个普通的对象)。

    3、所有的函数都有一个’prototype’属性(这也叫显式原型,它也是一个普通的对象)。

    4、所有引用类型,它的实例化的对象的’_ _ proto_ _'属性指向它的构造函数的’prototype’属性。

    5、当试图得到一个对象的属性时,如果这个对象本身不存在这个属性,那么就会去它的’_ _ proto_ _'属性(也就是它的构造函数的’prototype’属性)中去寻找。

  • 显式原型与隐式原型的关系

    • 函数的prototype: 定义函数时被自动赋值, 值默认为{}, 即用为原型对象

    • 实例对象的__proto__: 在创建实例对象时被自动添加, 并赋值为构造函数的prototype值

    • 原型对象即为当前实例对象的父对象

  • 原型链

    • 所有的实例对象都有__proto__属性, 它指向的就是原型对象

    • 这样通过__proto__属性就形成了一个链的结构---->原型链

    • 当查找对象内部的属性/方法时, js引擎自动沿着这个原型链查找

    • 当给对象属性赋值时不会使用原型链, 而只是在当前对象中进行操作

 

 

 

 上面可以看出实例化对象ldh.__proto__指向star的原型对象,

而star的原型对象.__proto__指向Object的原型对象,

而object的原型对象.__proto__指向null

------------------------------------------------------------------------------------------------------------------------------------------------------------

原型:
1. 函数的prototype属性
  * 每个函数都有一个prototype属性, 它默认指向一个Object空对象(即称为: 原型对象)
  * 原型对象中有一个属性constructor, 它指向函数对象
2. 给原型对象添加属性(一般都是方法)
  * 作用: 函数的所有实例对象自动拥有原型中的属性(方法)
//定义构造函数
  function Fn() {   // 内部语句: var Fn = new Function() this.prototype = {}

  }
 // 1. 每个函数function都有一个prototype,即显式原型属性, 默认指向一个空的Object对象
  console.log(Fn.prototype)
  // 2. 每个实例对象都有一个__proto__,可称为隐式原型
  //创建实例对象
  var fn = new Fn()  // 内部语句: this.__proto__ = Fn.prototype
  console.log(fn.__proto__)
  // 3. 对象的隐式原型的值为其对应构造函数的显式原型的值
  console.log(Fn.prototype===fn.__proto__) // true

 

 

 原型链(所有函数的隐式原型都指向同一原型,都一样)

1. 原型链(图解)
  * 访问一个对象的属性时,
    * 先在自身属性中查找,找到返回
    * 如果没有, 再沿着__proto__这条链向上查找, 找到返回
    * 如果最终没找到, 返回undefined
  * 别名: 隐式原型链
  * 作用: 查找对象的属性(方法)
2. 构造函数/原型/实体对象的关系(图解)
3. 构造函数/原型/实体对象的关系2(图解)

 

Function、Object、普通构造函数的原型链关系

 

 

图中有几个难点:

1.Function构造函数可以用Function.__proto__来访问Function.prototype. 这是因为Function构造函数的构造函数是他本身,作为实例化对象的角色来访问,可行。

2.任何函数都是函数,他都继承Function的所有属性和方法,而Function是内置的构造函数,也是对象,都是继承Object的所有属性和方法。

/*
  1. 函数的显示原型指向的对象默认是空Object实例对象
   */
  console.log(Fn.prototype instanceof Object) // true
  console.log(Object.prototype instanceof Object) // false
  console.log(Function.prototype instanceof Object) // true
  /*
  2. 所有函数都是Function的实例(包含Function)
  */
  console.log(Function.__proto__===Function.prototype)
  /*
  3. Object的原型对象的隐式原型是原型链尽头
   */
  console.log(Object.prototype.__proto__) // null

读取属性:

1. 读取对象的属性值时: 会自动到原型链中查找
2. 设置对象的属性值时: 不会查找原型链, 如果当前对象中没有此属性, 直接添加此属性并设置其值
3. 方法一般定义在原型中, 属性一般通过构造函数定义在对象本身上
function Fn() {

}
Fn.prototype.a = 'xxx'
var fn1 = new Fn()
console.log(fn1.a, fn1)

var fn2 = new Fn()
fn2.a = 'yyy'
console.log(fn1.a, fn2.a, fn2)

运行:

 

 

posted @ 2021-02-22 15:47  兜里还剩五块出头  阅读(32)  评论(0编辑  收藏  举报