欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

js 原型 与 原型链

程序员文章站 2022-04-24 23:07:09
...

title: js 原型 与 原型链
time: 2019-11-26
author: wsm
mail: aaa@qq.com
github: https://github.com/Geronimomiao/advance

基础


每个构造函数(constructor)都有一个原型对象(prototype),原型对象都包含一个指向构造函数的指针,而实例(instance)都包含一个指向原型对象的内部指针
如果试图引用对象(实例instance)的某个属性,会首先在对象内部寻找该属性,直至找不到,然后才在该对象的原型(instance.prototype)里去找这个属性

  • 一切皆对象,对象又可以分为两类
    • 普通对象
      • 除了函数对象之外的对象都是,包括new函数对象()产生的实例,普通对象没有prototype,也就没有继承和原型链一说
    • 函数对象
      • 系统内置的函数对象:Function、Object、Array、String、Number ,Function其实充当了函数对象的构造器,比如Object对象的构造源码其实是Function Object() {[native code]}的形式,这一点对于理解原型链很重要
      • 由function创造出来的函数
      function f1() {
     
      } 
      var f2 = function() {
      
      }
      var f3 = new Function('x','console.log(x)');
      // 以上都是函数对象

讲解用到的代码

function Foo(){
    //属性和方法
}
var f1 = new Foo();
var f2 = new Foo(); 
var o1 = new Object();
var o2 = new Object();

js 原型 与 原型链

js 原型 与 原型链

  • js 中一切皆对象

  • 每个对象都有__proto__属性,用于储存继承得来的方法和属性

  • 每个函数对象都有prototype属性,用于继承,将其中定义的属性和方法传递给‘后代’(比如实例化)

    • f1为何有Foo、Object的原型方法,其实就是通过原型链继承
    • 继承的过程可以表示为f1._proto_ = Foo.prototype,即对象._proto_ = 构造器.prototype
  • 在js中 并不能说对象有原型 而应该说对象的构造器有原型 对象把请求委托给自己构造器的原型

  • js 提供了__proto__的隐藏属性 某个对象的__proto__属性会默认指向{constructor}.prototype

Object 和 Function 的关系

一切对象都最终继承自Object对象,Object对象直接继承自根源对象null

  • 一切对象都包含有Object的原型方法,Object的原型方法包括了toString、valueOf、hasOwnProperty等等,在js中不管是普通对象,还是函数对象都拥有这些方法
  • 一切对象的原型链最终都是… → Object.prototype → null
    • 定义一个num变量var num = 1,则num的原型链为x → Number.prototype → Object.prototype → null
    • 定义一个函数对象fn function fn() {},则fn的原型链为fn → Function.prototype → Object.prototype → null

一切函数对象(包括Object对象)都直接继承自Function对象

  • js 原型 与 原型链

Function的原型链为 Function → Function.prototype → Object.prototype → null
Object的原型链为 Object → Function.prototype → Object.prototype → null

Question:
一切对象继承自Object,Object又继承自Function,那一切对象是不是都有Function的原型方法?
Answer:
不对,普通对象都没有Function的原型方法。从我们所写原型链中可以看出,Object是继承自Function,而Object也有Function的原型方法(比如bind),但Object继承得到的方法储存于__proto__属性中,普通对象从Object继承到的原型方法却在于prototype属性中,因而不对

总结


  • 一切对象都继承自Object.prototype,而一切函数对象都继承自Function.prototype(且Function.prototype会最终继承自Object.prototype)
  • 普通对象和函数对象的区别是:普通对象直接继承了Object.prototype,而函数对象在中间还继承了Function.prototype

原型同样也可以通过 _proto_ 访问到原型的原型,比方说这里有个构造函数 Person 然后“继承”前者的有一个构造函数 People,然后 new People 得到实例 p
当访问 p 中的一个非自有属性的时候,就会通过 _proto_ 作为桥梁连接起来的一系列原型、原型的原型、原型的原型的原型直到 Object 构造函数为止

js 原型 与 原型链

推荐链接1
推荐链接2