最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • JavaScript揭秘之原型和原型链

    正文概述 掘金(Moonshine)   2021-02-26   455

    前言

    作为一名前端从业者,如果理不清JavaScript原型和原型链都显得不够专业,毕竟这是原生JavaScript的重难点和面试必考点,那么到底原型和原型链到底是什么呢?下面我们一起来谈谈吧。

    原型和原型链

    首先我们看一段代码

     function Animal(){}
     
     let dog = new Animal();
     dog.name = 'black'
     console.log(dog.name) // 'black'
     
    

    在这个代码中,我们创建了一个Animal的构造函数,然后通过构造函数new出来一个dog实例,那么此时的dog就是Animal的实例对象。

    prototype是每一个函数都有的属性,它的作用是指向自己的原型,比如:

    所以 Animial的原型就是 Animial.prototype

    我们可以用一张图表示构造函数和实例原型之间的关系:

    JavaScript揭秘之原型和原型链

    既然Animial构造函数的原型 是 Animial.prototype,那它的实例dog的原型又是谁呢?

    我们看下一段代码

    function Person(){}
    // 此处我们用prototype属性在Person原型上创建一个属性name,值为Anny
    Person.prototype.name = 'Anny'
    
    // 然后我们实例化一个person
    
    let person = new Person()
    
    console.log(person.name) // 'Anny'
    
    // 此时可以看出,我们并未在实例上定义name这个属性,为啥访问persone.name可以打印出原型的name属性值呢?
    
    我们测试一下:
    
    // 我们给person这个实例定义一个name属性,值为Sam
    person.name = 'Sam'; 
    
    console.log(person.name) // 'Sam' 此时我们打印的值为Sam
    
    // 我们在删除person.name属性
    delete person.name
    
    console.log(person.name) // 'Anny' 此时值又成了 Anny了
    
    通过上面的例子 我们发现,当实例中没有一个属性的时候,它就会从构造函数的 Person.prototype 原型中去寻找这个属性,然后将其的信息展示出来。
    
    

    那么什么是原型呢?你可以这样理解:每一个JavaScript对象(null除外)在创建的时候就会与之关联另一个对象,这个对象就是我们所说的原型,每一个对象都会从原型"继承"属性

    这是每一个JavaScript对象(除了 null )都具有的一个属性,叫__proto__,这个属性会指向该对象的原型。

    那么有了 __ proto __ ,我们就知道我们实例的原型了,我们看下一段代码

      function Person(){}
      let person = new Person()
      
      // 我们通过 __proto__来指向person和Person的原型是不是同一个
      
      console.log(person.__proto__ == Person.prototype) // true
      
      // 由此可以看出,上面的说法是对的,person和Person的原型指向同一个,Person.prototype
    

    得到以下关系图: JavaScript揭秘之原型和原型链

    既然实例对象和构造函数都可以指向原型,那么原型是否有属性指向构造函数或者实例呢?

    function Person(){}
    
    console.log(Person === Person.prototype.constructor) // true
    
    // Person.prototype 代表原型,Person.prototype.constructor代表原型的构造函数,所以上面的值为true
    

    所以我们得到以下关系图 JavaScript揭秘之原型和原型链

    上面我们说到,实例读取实例的属性时,如果找不到,就会查找与对象关联的原型中的属性,那如果原型上也没有呢?那它会一直找,找原型的原型,一直找到最顶层为止。

    原型的原型

    在前面,我们已经说了,原型也是一个对象,既然是对象,那我们的原型的原型是不是Object的原型呢?下面我们看以下代码:

    // 我们在Object的原型上定义一个name叫'Kangknag'
    Object.prototype.name = 'kangkang'
    
    // 定义一个Person构造函数
    function Person(){}
    
    // 在Person的原型上定义一个属性name 为 'Sam'
    Person.prototype.name = 'Sam';
    
    // 此时我们创建一个实例
    let person = new Person() 
    
    // 此处大家都知道,如果实例上没有name属性,回去它的原型上找,所以此处打印的是Sam
    console.log(person.name) // 'Sam'
     
     // 此时我们删除Person上的属性name
     
     delete Person.prototype.name
     
     console.log(person.name) // 'KangKang'
     
     // 此时我们发现,当删除了构造函数Person的属性name后,我们在打印实例的值变成了'KangKang',上面说道,实例的属性如果没有就会去原型上面找,如果原型上找不到就会去原型的原型上面去找,那此处的Person的原型就是Object.prototype,我们可以验证一下
     
     console.log(person.__proto__.__proto__ == Object.prototype) // true
     // 可以看出 person原型的原型就是Object.prototype
     
     
    

    所以我们得到以下关系图

    JavaScript揭秘之原型和原型链

    person原型的原型就是Object.prototype,那么我们的Object.prototype的原型又是什么呢? 我们可以打印看一下:

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

    那么null究竟代表了什么呢?,此处引用阮一峰老师的《undefined与null的区别》一文的说法: JavaScript揭秘之原型和原型链

    所以Object.prototype.__proto __ 的值为null跟Onject.prototype没有原型其实表达了一个意思。null就是原型链的终点,所以一般查找到Object.prototype就可以停止查找了

    此时我们可以得到一个关系

    那么什么我们就可以得出结论:

    所以我们可以得到以下关系图 JavaScript揭秘之原型和原型链

    以上图中蓝色的箭头就是原型链。

    • 当获取 person.constructor 时,其实 person 中并没有 constructor 属性,当不能读取到constructor 属性时,会从 person 的原型也就是 Person.prototype 中读取,正好原型中有该属性。
    person.constructor === Person.prototype.constructor // true
    
    • 其次是 proto ,绝大部分浏览器都支持这个非标准的方法访问原型,然而它并不存在于 Person.prototype 中,实际上,它是来自于 Object.prototype ,与其说是一个属性,不如说是一个 getter/setter,当使用 obj.proto 时,可以理解成返回了 Object.getPrototypeOf(obj)

    new操作符新建了一个空对象,这个对象原型指向构造函数的prototype,执行构造函数后返回这个对象

    • 创建一个空的对象
    • 链接到原型
    • 绑定this指向,执行构造函数
    • 确保返回的是对象

    文章最后

    通过以上的知识梳理,是不是对原型和原型链有了更深的理解呢?是不是发现所谓的模棱两可的知识理解起来也不是那么难?,对的,其实就是这样,只要知道它们的关系,发现原型链也不过如此。此文带有个人见解,如有错误还请大家指出,我及时更正。大家一起努力,加油。

    文章借鉴:
    github.com/mqyqingfeng…
    www.ruanyifeng.com/blog/2014/0…
    www.cnblogs.com/jane-panyiy…


    起源地下载网 » JavaScript揭秘之原型和原型链

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元