JavaScript什么是原型和原型链JS

本文详细解析了JavaScript中的原型和原型链概念,包括构造函数、原型对象及其相互关系。通过实例展示了如何通过构造函数创建对象,并阐述了对象的__proto__属性以及如何访问和使用原型中的属性和方法。还探讨了对象属性查找机制以及原型链的工作原理,最后提到了与原型相关的几个关键属性和方法。通过阅读,读者将能够清晰理解这一核心JavaScript概念。

从事前端这么久,发现原型和原型链一直都是云里雾里,网上看了好多文章、博客也还是不怎么明朗,相信被它困扰的小伙伴,不在少数
以下是我总结的原型和原型链,个人认为是比较浅显易懂的:
原型:构造函数中的 prototype 就是显示原型

一、首先大家在对JS原型进行解释的时候,会涉及两个概念:构造函数、原型对象
  1. 构造函数:通俗的一句话说,就是你在script标签里面声明的函数:
function Person(params) {
    /**我就是构造函数*/
            
}
  1. 原型对象:当我们创建了一个函数A,浏览器就会在内存中创建一个对象B——即函数A的原型对象,并且每个函数都默认有一个prototype属性指向了内存中的对象,(即prototype的属性就是这个对象),而原型对象B默认有一个constructor属性指向了这个函数A(即constructor属性的值是函数A)
    构造函数

构造函数和原型对象

二、使用构造函数创建对象

当我们把函数作为一个构造函数使用new关键字来创建对象的时候:

function Person(params) {
    /**我就是构造函数*/
            
}

var p1 = new Person();

对象p1构造函数Person创建出来之后,对象p1和构造函数Person已经没有任何关系了,此时p1对象中会存在一个默认不可见的属性[[prototype]] ,指向了构造函数Person的原型对象
[[prototype]]是不可访问的,但是一些浏览器也提供了对这个属性的访问,比如:Chrome和火狐浏览器,ie不支持
访问方式:p1.__proto__

注意p1是没有prototype属性的,prototype属性只在构造函数(Person)中存在

在这里插入图片描述
由图可知,p1的__proto__属性指向的是构造函数的原型对象!
这里我们用一个图来再次梳理一下构造函数、原型对象和构造对象三者之间的关系:
在这里插入图片描述
说明:

  1. 创建p1虽然使用的是Person构造函数,但创建完成后对象p1已经和构造函数Person没有关系了,对象p1的__proto__属性指向的是构造函数的原型对象
  2. 如果使用 构造函数new Person()创建多个对象p1,p2,p3…,则多个对象同时指向Person构造函数的原型对象
  3. 当我们手动给这个原型对象添加属性和方法Person.prototype.name='小明',那么p1,p2,p3…这些对象就会共享这些在原型中添加的属性和方法
  4. 如果我们访问p1中的一个属性name,如果在p1对象中找到,则直接返回,如果没有,则直接去p1对象的__proto__属性指向的原型对象中找,如果找到则返回。(如果原型中也没找到,则继续向上找原型的原型——原型链。后面讲)
  5. 通过p1对象只能读取原型中的name属性值,不能修改name的值。p1.name='张三'并不是修改了原型中的值,而是给p1对象添加了一个属性name。
  6. 如果通过p1对象添加了一个属性name(p1.name='张三'),则对p1来说就屏蔽了原型中的属性name,即p1中无法访问到原型的name属性了

下面看详细代码:

        function Person(params) {
            // 我就是构造函数

        }

        // 可以使用Person.prototype 直接访问到原型对象
        Person.prototype.name="小明" // 给函数Person的原型对象添加属性name,值为'张三'
        Person.prototype.age = 18

        /**
         * 访问p1对象的属性name,虽然p1中没有添加name属性,但p1对象__proto__指向的原型对象中有name属性,所以能访问到属性name
        */
        var p1 = new Person();
        console.log(p1.name) //小明

        var p2 = new Person()
        console.log(p2.name) //小明
        

        p1.name='张三' // 由于不能修改原型中的值,所以这种方法只是在p1中添加了一个新属性name,然后在p1中就无法访问到原型中的name属性了
        console.log(p1.name) //张三
        console.log(p2.name) //小明
三、与原型有关的几个属性和方法

1. prototype属性
prototype存在于构造函数中(其实任意函数中都有,只是不是构造函数的时候prototype我们不关注而已),它指向了这个构造函数的原型对象
2.constructor属性
constructor属性存在于原型对象中,它指向了构造函数

 function Person(params) {
      // 我就是构造函数
 }
 console.log(Person.prototype.constructor===Person) //true

3. __proto__ 属性(注意:左右各是2个下划线)
用构造方法创建一个新的对象之后,这个对象中默认会有一个不可访问的属性 [[prototype]] , 这个属性就指向了构造方法的原型对象。

​ 但是在个别浏览器中,也提供了对这个属性[[prototype]]的访问(chrome浏览器和火狐浏览器。ie浏览器不支持)。访问方式:p1.__proto__

​ 但是开发者尽量不要用这种方式去访问,因为操作不慎会改变这个对象的继承原型链

参考文章:https://blog.csdn.net/u012468376/article/details/53121081

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值