【JS】中的原型与原型链。

JS三座金山

JS三座金山之——原型与原型链


目录

JS三座金山

前言

一、Function与Object

Function

定义函数

构造函数

Object

创建对象

Function与Object之间的关系

二、prototype、__proto__与constructor

prototype、__proto__二者的关系

constructor

 三、原型链

原型链 

原型链终点

四、原型继承

五、例子

六、 总结

1.一般来说,构造函数中的prototype与其实例对象中的__proto__是指向同一个地方,这个地方就叫做原型对象。

2.

函数是Function构造函数的实例

对象是Object构造函数的实例

3.

function Object()其实也是个函数,所以他是Function构造函数的实例

function Function()其实也是个函数,所以他也是Function构造函数的实例

4.原型链的终点是null!!

5.两张图片​


前言

相信大家都听过前端的三座大山:闭包,原型链,作用域,今天我们来说一下第一座金山——原型与原型链。


一、Function与Object

在此之前先铺垫一些函数与对象的内容。

Function

定义函数

一般来说我们平时定义函数无非以下几种:

    const fn1 = function (name, age) {
        console.log(`fn1中的name:${name},fn1中的age${age}`);
    }
    fn1('JAVIS_L', 18)//fn1中的name: JAVIS_L, fn1中的age18


    function fn2(name, age) {
        console.log(`fn2中的name:${name},fn2中的age${age}`);
    }
    fn2('JAVIS_L', 18)//fn2中的name: JAVIS_L, fn2中的age18


    const fn3 = (name, age) => {
        console.log(`fn3中的name:${name},fn3中的age${age}`);
    }
    fn3('JAVIS_L', 18)//fn3中的name: JAVIS_L, fn3中的age18

说到底,他们的本质都是一样的(只考虑函数声明),都可以使用 new Function来声明

     const fn1 = new Function('name', 'age', 'console.log(`我是fn1中的name:${name},age:${age}`)')
    fn1('JAVIS_L', 18)//我是fn1中的name: JAVIS_L, fn1中的age18

    const fn2 = new Function('name', 'age', 'console.log(`我是fn2中的name:${name},age:${age}`)')
    fn2('JAVIS_L', 18)//我是fn2中的name: JAVIS_L, fn2中的age18

    const fn3 = new Function('name', 'age', 'console.log(`我是fn3中的name:${name},age:${age}`)')
    fn3('JAVIS_L', 18) //我是fn3中的name: JAVIS_L, fn3中的age18

构造函数

那什么是构造函数呢?俗话说就是,可以用来new的函数就叫构造函数,箭头函数不能用来当做构造函数。

    function Person(name, age) {//这个就是构造函数
            this.name = name
        this.age = age
    }
    const p1 = new Person('JAVIS_L',18)//构造函数Person的实例
    const p2 = new Person('JARVIS_L',20)//构造函数Person的实例

Object

创建对象

咱们平常开发中,创建一个对象,通常会用以下几种方法。

  • 构造函数创建对象,他创建出来的对象都是此Function构造函数的实例,所以这里不讨论它
  • 字面量创建对象
  • new Object创建对象
  • Object.create创建对象,创建出来的是一个空原型的对象,这里不讨论它
 // 第一种:构造函数创建对象
    function Person(name, age) {
        this.name = name
        this.age = age
    }
    const person1 = new Person('JAVIS_l', 18)
    console.log(person1) // Person { name: 'JAVIS_l', age: 18 }

    // 第二种:字面量创建对象
    const person2 = { name: 'JAVIS_l', age: 18 }
    console.log(person2) // { name: 'JAVIS_l', age: 18 }

    // 第三种:new Object创建对象
    const person3 = new Object()
    person3.name = 'JAVIS_l'
    person3.age = 18
    console.log(person3) // { name: 'JAVIS_l', age: 18 }

    // 第四种:Object.create创建对象
    const person4 = Object.create({})
    person4.name = 'JAVIS_l'
    person4.age = 18
    console.log(person4) // { name: 'JAVIS_l', age: 18 }

事实上,字面量创建对象本质上就是new Object创建对象,所以

// 字面量创建对象
    const person3 = { name: 'JAVIS_l', age: 18 }
    console.log(person3) // { name: 'JAVIS_l', age: 18 }

    本质上是


    // new Object创建对象
    const person3 = new Object()
    person3.name = 'JAVIS_l'
    person3.age = 18
    console.log(person3) // { name: 'JAVIS_l', age: 18 }

Function与Object之间的关系

上面已经说过了构造函数,所以我们常说

  • 函数Function构造函数的实例
  • 对象Object构造函数的实例

Function构造函数Object构造函数他们两个又是谁的实例呢?

  • function Object()其实也是个函数,所以他是Function构造函数的实例
  • function Function()其实也是个函数,所以他也是Function构造函数的实例,没错,他是他自己本身的实例(在下面原型中验证)

二、prototype、__proto__与constructor

  • prototype:显式原型(存在于构造函数中)
  • __proto__:隐式原型(存在于实例对象中)

prototype、__proto__二者的关系

首先它们两个都叫做原型。一般来说,构造函数中的prototype与其实例对象中的__proto__是指向同一个地方,这个地方就叫做原型对象。

可以验证一下

function Person(name, age) {//构造函数Person
        this.name = name
        this.age = age
    }

    // 为构造函数Person的原型对象上添加一个sayName方法
    Person.prototype.sayName = function () {
        console.log(this.name);
    }
    console.log(Person.prototype);//{sayName: ƒ, constructor: ƒ}

    const person1 = new Person('JAVIS_L', 18)//构造函数Person的一个实例对象person1
    console.log(person1.__proto__);//{sayName: ƒ, constructor: ƒ}

    console.log(Person.prototype === person1.__proto__);//true

重点来啦!!构造函数中的prototype与其实例对象中的__proto__是指向同一个地方,这个地方就叫做原型对象。

刚刚有两句话大家还记得吗?

  • 函数Function构造函数的实例
  • 对象Object构造函数的实例

下面我们就来分别验证一下。

函数Function构造函数的实例。还是那句话,构造函数中的prototype与其实例对象中的__proto__是指向同一个地方,这个地方就叫做原型对象。所以这里的fn1、fn2、fn3其实也都是Function构造函数的实例对象。

    const fn1 = function (name, age) {
        console.log(`fn1中的name:${name},fn1中的age${age}`);
    }
    fn1('JAVIS_L', 18)//fn1中的name: JAVIS_L, fn1中的age18


    function fn2(name, age) {
        console.log(`fn2中的name:${name},fn2中的age${age}`);
    }
    fn2('JAVIS_L', 18)//fn2中的name: JAVIS_L, fn2中的age18


    const fn3 = (name, age) => {
        console.log(`fn3中的name:${name},fn3中的age${age}`);
    }
    fn3('JAVIS_L', 18)//fn3中的name: JAVIS_L, fn3中的age18


    console.log(Function.prototype === fn1.__proto__);//true
    console.log(Function.prototype === fn2.__proto__);//true
    console.log(Function.prototype === fn3.__proto__);//true

对象Object构造函数的实例。还是那句话,构造函数中的prototype与其实例对象中的__proto__是指向同一个地方,这个地方就叫做原型对象。所以这里的person1、person2其实也都是Object构造函数的实例对象。

    const person1 = { name: 'JAVIS_L', age: 18 }

    const person2 = new Object()
    person2.name = 'JAVIS_L'
    person2.age = 18

    console.log(Object.prototype === person1.__proto__) // true
    console.log(Object.prototype === person2.__proto__) // true

 下面我们来验证这两句话

  • function Object()其实也是个函数,所以他是Function构造函数的实例
  • function Function()其实也是个函数,所以他也是Function构造函数的实例,没错,他是他自己本身的实例(在下面原型中验证)
 console.log(Object.__proto__ === Function.prototype) // true
 console.log(Function.__proto__ === Function.prototype) // true

constructor

constructor和prototype是成对的,相互指向。

    function fn() { }

    console.log(fn.prototype) // {constructor: fn}
    console.log(fn.prototype.constructor === fn) // true

 三、原型链

         在此之前我们先验证一个东西:“构造函数Function的原型对象是构造函数Object的实例对象。”对不对呢?我们可以先来验证下

console.log(Function.prototype.__proto__ === Object.prototype) // true

结果是true。为什么呢?????

首先Function.prototype是构造函数Function的原型对象,既然是“对象”,那本质上都是通过new Object()创建的,因此Function.prototype就是Object的一个实例对象,所以Function.prototype的__proto__指向Object.prototype(Person.prototype同理)

原型链 

什么是原型链呢?其实俗话说就是:__proto__的路径就是原型链

原型链终点

虽然说三条原型链都指向了Object.prototype,那么原型链的终点就是Object.prototype了么??其实不是的,Object.prototype也有一个__proto__属性,最终指向null!!

至此原型与原型链就讲完了!

 

四、原型继承

说到原型,就不得不说下原型继承了,原型继承说的就是实例对象可以使用构造函数上prototype中的方法。

    function Person(name, age) {//构造函数Person
        this.name = name
        this.age = age
    }

    Person.prototype.Introduce = function () {//Person的原型对象
        console.log(`我叫${this.name},我的年龄是:${this.age}`);
    }

    const person1 = new Person('JAVIS_L', 18)//Person的实例对象
    // 实例对象使用原型对象中的方法
    person1.Introduce()//我叫JAVIS_L,我的年龄是:18

五、例子

    var foo = {},
    F = function () { };
    Object.prototype.a = 'value a';
    Function.prototype.b = 'value b';


    console.log(foo.a);
    console.log(foo.b);

    console.log(F.a);
    console.log(F.b);

答案

    console.log(foo.a);//value a
    console.log(foo.b);//undefined
    
    console.log(F.a);//value a
    console.log(F.b);//value b

六、 总结

1.一般来说,构造函数中的prototype与其实例对象中的__proto__是指向同一个地方,这个地方就叫做原型对象。

2.

  • 函数Function构造函数的实例

  • 对象Object构造函数的实例

3.

  • function Object()其实也是个函数,所以他是Function构造函数的实例

  • function Function()其实也是个函数,所以他也是Function构造函数的实例

4.原型链的终点是null!!

5.两张图片

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值