JavaScript高级-原型和原型链

1.函数的prototype

1.函数的prototype属性

  • 每个函数都有一个prototype属性,它默认指向一个Object空对象(原型对象)

  • 原型对象中有一个属性constructor,它指向函数对象(如下图)

在这里插入图片描述

2.给原型对象添加属性(一般为方法)

  • 作用:函数的所有实例对象都会拥有原型中的属性(方法)

     	function Fun(){
            
        }
        const fun  = new Fun()
    	console.log(fun.__proto__===Fun.prototype);//true
    

2.显式原型与隐式原型

  1. 每个函数function都有一个protorype,即显示原型

  2. 每个构造函数的实例对象都有一个__ proto __,即隐式原型

  3. 对象的隐式原型的值为其对应构造函数的显式原型的值

  4. 内存结构

在这里插入图片描述

  1. 总结

    1. 函数的prototype属性:在定义函数时js内部自动添加,默认值是一个空Object对象
    2. 对象的__ proto __属性:在创建对象时js内部自动添加,默认值是构造函数的prototype属性值
    3. 程序员能直接操作显示原型,但不能直接操作隐式原型(ES6之前)

3.原型链

1.定义

​ 解释:原型链就是根据对象的__ proto __指向,一层一层连接起来的具有关联性的对象集合

  • 访问一个对象的属性时

    • 先在自身属性中查找,找到返回
    • 如果没有找到,再沿着__ proto __这条链返回
    • 如果最终没找到,返回indefined
  • 别名:隐式原型链

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

2.分析

原型链就是根据对象的__ proto __指向,一层一层连接起来的具有关联性的对象集合

当我们调用一个对象的方法时,js内部会根据原型链进行查找,如果当前层没有此方法,则往它的__ proto __指向的对象查找,直到找到这个方法

Object原型对象是原型链的尽头,它的__ proto __指向为空,如果在Object的原型对象中仍然没有找到此方法,则说明对象中不包含这个方法

function Fun{}
const fun = new Fun()
const Object = new Object()

在这里插入图片描述

如上图所示,假设我现在想在fun函数中查找toString()方法,那么查询的顺序是这样的:

fun—>fun. __ proto __ (没找到,往下层寻找)—>fun. __ proto __ . __ proto __ (没找到,往下层寻找)—>

fun. __ proto __ . __ proto __ . __ proto __(到达Object的原型对象,找到了toString()方法)

如果查找一个不存在的方法,会返回undefined

4.构造函数-原型-实例对象之间的关系

1.定义
  1. 每个构造函数都有一个原型对象,这个原型对象又是另一个原型对象的实例
  2. 每个构造函数的实例也有一个原型对象,这个原型对象也是另一个原型对象的实例
  3. 构造函数的显式原型等于这个构造函数的实例的隐式原型
  4. 构造函数以及他的实例最终都指向Object的原型对象
2.解释

我们画图来描述
在这里插入图片描述

如上图

fun是Fun的实例,即 const fun = new Fun()

Fun又是Function的实例,即const Fun = new Function()

注意:Function是引用属性,一切函数都是Function的实例对象

我们先来分析fun函数:

​ fun是Fun实例对象,它只有隐式原型属性 __ proto __,它的隐式原型指向它的构造函数Fun的原型对象,

​ 这也印证了我们之前说的一句话:构造函数的显式原型等于这个构造函数的实例的隐式原型,

​ 然后Fun的原型对象又指向Object的原型对象

​ 故而我们可以知道,Fun的原型对象实际上是Object的实例对象

​ Object的原型对象是原型链的终点,它的原型属性指向null

我们来分析Fun函数:

​ Fun本身是一个构造函数,同时他也是Function的实例对象,故而Fun既有隐式原型也有显式原型

​ 它的显式原型等于fun的隐式原型,指向的是Fun的原型对象,Fun的原型对象又是Object的实例对象,他最终指向Object的原型对象

​ 它的隐式原型等Function的显式原型,指向的是Function的原型对象,而Function的原型对象实际上也是Object的实例对象,它的原型指向Object的原型对象

我们可以得出结论:一切函数的原型都指向Object的原型对象


需要特别注意的一点是Function的原型关系:Function的隐式原型等于它的显式原型

这怎么解释呢?

实际上可以理解为 Function的构造函数就是它本身,即 const Function = new Function()

通俗一点就是:所有的鸡(函数)都是由鸡妈妈(Function)生的,而鸡妈妈(Function)也是鸡,所以鸡妈妈(Function)也是鸡妈妈(Function)生的


5.探索instanceof属性

1.定义

instanceof:判断对象的具体类型,返回值是布尔值

instanceof是如何进行判断的?

  • 表达式:A instanceof B:如果B的显式原型对象在A的原型链上,返回true,否则返回false
2.解释

我们来探讨instanceof判断对象的具体过程

还是这个示例图,我们判断以下表达式

const obj = {}
function Fun(){}
const fun = new Fun()
console.log(obj instanceof Fun)//false

在这里插入图片描述

obj instanceof Fun的过程:

对于Fun,我们要查找它的显式原型对象:

Fun—>Fun.prototype(Object的实例对象)

对于obj,我们要沿着它的原型链查找:

obj—>obj.__ proto __(Object的原型对象)

从以上查找路径我们可知,Fun的显式原型对象在obj的原型链中并没有出现,故而返回false

6.面试题

1.题目
  //第一题 判断输出的结果
	function A(){

    }
    A.prototype.n = 1
    const b = new A()
    A.prototype = {
        n:2,
        m:3
    }
    const c = new A()
    console.log(b.n,b.m,c.n,c.m);//1 undefined 2 3

    // 第二题 判断输出的结果
    const F = function(){}
    Object.prototype.a = function(){
        console.log('a()');
    }
    Function.prototype.b = function(){
        console.log('b()');
    }
    const f = new F()
    f.a() // a()
    f.b() // undefined
    F.a() // a()
    F.b() // b()
2.题解

先抛图

在这里插入图片描述

​ 我们定义构造函数A,并给A.prototype(A的原型对象)定义变量n为1

​ 创建构造函数A的实例b,此时b的原型链为:

​ b–>b.__ proto __ (b的隐式原型对象,与A.prototype相等,故而b. __ proto __ .n = 1)–>b. __ proto __ . __ proto __(Object的原型对象)

​ 在定义完b之后,我们修改了A的原型对象,此时A的原型对象中的数据已经被替换,此时n的值为2

​ 创建构造函数A的实例c,此时c的原型链为:

c–>c.__ proto __ (c的隐式原型对象,与A.prototype相等,故而c. __ proto __ .n = 2,c. __ proto __ .m = 3)–>c.__ proto __ . __ proto __(Object的原型对象)

​ 由上可得

我们输出的结果为 1 indefined 2 3

​ 我们给object的原型对象赋值a方法,再给Function的原型对象赋值b方法

​ 此时object的原型链为:

​ object–>object.prototype(Object的原型对象,并且拥有方法a)

​ 此时Function的原型链为:

​ Function–>Function.prototype(Function的原型对象,它拥有方法b)–>Function.prototype.__ proto __ (Object的原型对象,它拥有方法a)

​ 我们创建构造函数F的实例f,此时F和f的原型链分别为

F: F–>F. __ proto __ (F的原型对象)–>F. __ proto __ . __ proto __ (Function的原型对象,它拥有方法b)–>F.prototype.prototype.__ proto __(Object的原型对象,它拥有方法a)

f: f–>f.__ proto __ (f的隐式原型对象)–>f. __ proto __ . __ proto __ (Object的原型对新昂,它拥有方法a)

由上可得

我们输出的结果为 a() indefined a() b()

注意:构造函数的实例对象的原型链不会指向Function原型对象,而构造函数的原型链指向Function原型对象

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值