JavaScript关于原型链的总结

JavaScript关于原型链的总结

一、原型属性

  1. 函数的prototype属性
  • 每个函数都有一个prototype属性, 它默认指向一个Object空对象(即称为: 原型对象)
  • 原型对象中有一个属性constructor, 它指向函数对象

  1. 给原型对象添加属性(一般都是方法)
  • 作用: 函数的所有实例对象自动拥有原型中的属性(方法)

当在创建每一个函数时,解析器会向函数添加一个属性prototype(这就是所谓的原型对象)


  1. 显示原型与隐式原型

函数=>构造函数

对象=>实例对象

1)每个函数function都有一个prototype,即显式原型

Fn.prototype

2)每个实例对象都有一个__proto__,可称为隐式原型

let fn =new Fn()
fn.__proto__

3)对象的隐式原型的值对应构造函数的显式原型的值

fn.__proto__ = Fn.prototype
fn.__proto__ === Fn.prototype

4)在定义函数的时候,会自动添加一个prototype属性,默认值是一个空Object对象

function Fn() {}
this.prototype = {}

5)当创建实例对象的时候,会自动添加__proto__属性,默认值是=>prototype属性值

function Fn() {}
// 创建一个实例对象
var fn = new Fn()
fn.__proto__ = Fn.prototype	// 默认值是=> prototype的值

6)程序员能直接操作显式原型, 但不能直接操作隐式原型(ES6之前)

	// 定义构造函数
	function Fn() {
    // 内部语句:this.prototype = {}
	}
  var fn = new Fn()	// 内部语句:fn.__proto__ = Fn.prototype
	// 给prototype添加test方法
  Fn.prototype.test = function () {
    console.log('test()')
  }
	// 通过实例调用原型的方法
  fn.test()

请添加图片描述


二、原型链

  1. 原型链(图解)
  • 访问一个对象的属性时,

  • 先在自身属性**(实例对象属性)**中查找,找到返回

  • 如果没有, 再沿着__proto__这条链向上查找, 找到返回

  • 如果最终没找到, 返回undefined

  • 别名: 隐式原型链

  • 作用: 查找对象的属性(方法)

	function Fn() {// 内部语句:this.prototype = {}
		this.test1 = function () {
      console.log('test1()')
    }
  }
  Fn.prototype.test2 = function () {
    console.log('test2()')
  }
  var fn = new Fn()	// 内部语句:fn.__proto__ = Fn.prototype
	// 通过实例调用原型的方法
  fn.test1()
  fn.test2()
  fn.test3()

请添加图片描述
总结:

  • Object空对象里同样也有一个隐式原型,在找下去就会找到Object原型对象,而Object原型对象同样也有一个隐式原型,只不过他的值为null

  1. 构造函数/原型/实体对象的关系(图解)
  • o1,o1:有一个隐式原型属性(__ proto __)他指向Object的原型对象(Object.prototype
var o1 = new Object();
var o2 = {};

请添加图片描述


  1. 构造函数/原型/实体对象的关系2(图解)
  • 1)首先创建一个函数,他有一个显示原型属性(Foo.prototype),默认是空的Object对象

    • 此时是构造函数
    • function Foo(){ }
    • 请添加图片描述
  • 2)为什么Foo构造函数的隐式原型指向Function的显示原型?

    • let Foo = new Function()
    • Foo函数是Function()的实例对象,因此Foo__proto__指向Function的显示原型属性。
    • 根据定义=>当创建实例对象时,实例对象的隐式原型对应构造函数的显示原型
  • **TIP:所有函数都有一个隐式原型属性(__ proto __指向大写Funcion的显示原型属性(Funcion.prototype)**具体为什么?看下面。

  • 3)为什么Function的隐式原型指向自身的显示原型?

    • Function = new Function()
    • 因为FunctionFunction()的实例对象,那么隐式原型必定指向显示原型
    • 请添加图片描述
  • 4)我们继续看图:

    • let Object = new Function()
    • 我创建了一个新的函数名为Object,他的隐式原型同样也会指向Function的显示原型,因为他也是New Function产生的
    • 请添加图片描述

最关键是要掌握一点:

构造函数隐式原型指向Function的显示原型(也可以说指向Function的构造函数的显示原型)

而构造函数实例化后:实例对象隐式原型=>构造函数的显示原型

实例对象的隐式原型=构造函数的显示原型

  • 5)总结:

    • 所有构造函数都是通过new Function产生

    • 所有函数的构造函数__proto__都是指向Function的显示原型,因为都是由new Function产生

    • 这里做个小总结:所有的函数对象都是Function函数的实例对象,因此函数的隐性原型属性都是一样的。然后这些函数都有各自自己的显性原型属性,他们自己创建的实例对象,与其隐性原型属性地址值相等。

function Foo(){  }
let Foo = new Function()
Function = new Function()

请添加图片描述


4)函数的显示原型指向的对象默认是空Object实例对象(但Object不满足)

console.log(Fn.prototype instanceof Object) // true
console.log(Object.prototype instanceof Object) // false
console.log(Function.prototype instanceof Object) // true

5)所有函数都是Function的实例(包含Function)

console.log(Function.__proto__===Function.prototype)

6)Object的原型对象是原型链尽头

console.log(Object.prototype.__proto__) // null

三、instanceof

表达式:A instanceof B

判断B函数的显示原型对象是否在A对象的原型链上(A原型链是否存在B的显示原型)

A是一个实例对象

B是一个构造函数对象

  1. 例一
  • function Foo() {  }
    var f1 = new Foo();
    console.log(f1 instanceof Foo);// true
    console.log(f1 instanceof Object); // true
    
  • f1是实例对象,而Foo是构造函数对象

  • 函数的实例对象默认是一个空的Object对象,然后又因为(实例对象的隐式原型=构造函数的显示原型),所以:如图
    请添加图片描述
    请添加图片描述


  1. 例二
console.log(Object instanceof Function);// true
console.log(Object instanceof Object);// true
console.log(Function instanceof Function);// true
console.log(Function instanceof Object);// true

function Foo() {}
console.log(Object instanceof  Foo);// false

1)Function作为构造函数看显示原型,Object作为实例对象看隐式原型,其他就没什么好说了,自行看图。

请添加图片描述

function Foo() {  }
var f1 = new Foo();
let o1 = new Object()
console.log(f1 instanceof Foo);// true
console.log(f1 instanceof Object); // true

请添加图片描述

原型链的总结

  • 显示原型与隐式原型

    • 显示原型:prototype
    • 隐式原型:__proto__
    • 构造函数有:显示原型
      • 构造函数隐式原型永远指向Function显示原型
    • 实例对象有:隐式原型
  • 访问属性

    • 访问一个属性的时候,是先在自身属性找,找不到就沿着隐式原型向上找,最终找不到会返回undefined
    • 小提示:我们是在沿着实例对象上找。
  • 定理1:Object的原型对象是原型链的尽头

  • 定理2:实例对象的隐式原型永远等于构造函数显示原型。

    • 红线是显示原型显示原型指向显示原型属性。
    • 紫线是隐式原型,而显示原型指向哪里,隐式原型就会跟着指向哪里。
    • 请添加图片描述
  • 定理3:构造函数的显示原型属性默认是空的Object实例对象。(除了Object)

  • 定理4:所有函数对象都是Function实例对象。(包括Function)

  • 定理4:所有构造函数的隐式原型必定指向Function的显示原型。

  • 定理5Object隐式原型指向Function的显示原型。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值