你真的知道js的原型链吗??

577 阅读3分钟

在去了解原型链之前,一定要先搞清楚两个概念,一个是prototype,一个__proto__。耐心往下看哦

1.prototype

    首先什么是prototype?prototype是函数的一个属性,它是一个对象,里面含有两个属性  constructor,__proto__,分别是什么呢??如下图,constructor是一个构造器,它指向自身,而__proto__指向的是对象

    记住:一切对象的根源 - Object.prototype


2.__proto__

     __proto__是对象(出去null)所拥有的一个属性,它指向的构造这个函数的原型对象(prototype),取个栗子

function a(){}
console.log(a.__proto__ === Function.prototype)   //true

      应该会有人会问,Object的

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


3.原型链

   怎么解释原型链,其实需要靠大家去理解

   写一小段简单的代码,在进行解释

function Person(){}
let p1 = new Persion()

    1.每个函数(通常指构造函数,如Person)都有一个属性:prototype

    2.prototype是一个对象, 里面有constructor , __proto__ 隐式原型

    3.构造函数的原型对象指向当前构造函数 Person.prototype.constructor === Person  

    4.实例对象的隐式原型指向构造函数的显示原型 

               p1.__proto__ === Person.prototype 

    5.在构造函数显示原型中添加的方法,所有的实例对象共享 

    6.访问属性和方法,是基于原型连进行访问 在当前的实例对象去找--》构造函数的原型 ==》.... =》 Object的原型 

      

   光看这几句话会很干,可以看看下面的例子

    

4.简单的原型链的题及其解释

        var F = function(){}
        F.prototype.b = function (){            
          console.log('b()');}       
        Function.prototype.c = function () {    
          console.log('c()');}       
        Object.prototype.a = function () {      
          console.log('a()')   
        };       
        var f = new F();      
        F.a();      
        F.b();     
        F.c();         
        f.a();        
        f.b();      
        f.c();  

  这道题完全就是和原型相关,如果你能准确的说出答案,那么原型和原型链的理解基本就是明白的了,做这道题的关键需要分清楚原型链的访问(实例对象直接访问构造函数的显示原型的函数)

  画一张图就能很清楚的看出答案,话不多少,看图

看完图之后,可以看出原型链分为两条 - 一条是红色,一条是绿色,原型链上的方法,实例对象都是可以访问的

 F.b(),报错,访问F的b方法,应该为F.prototype.b(),记住一句就是实例对象可以直接访问构造函数显示原型的方法

 f.c(), 报错,c并不是在f的原型链上面,而是在F的原型链上


5.Object和Function之间的关系

  第一,万事万物皆对象   

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

  然后,js的所有类都是Function的实例,也是Object的派生类,Object对象直接继承Function对象

 console.log(Object.constructor === Funciton)  //true
 console.log(Object instanceof Function) //true
 console.log(Function instanceof Object)//true 
 console.log(Object.__proto__  === Function.__proto__) //true       
 console.log(Object.__proto__ === Function.prototype); //true 
 console.log(Function.__proto__ === Function.prototype); //true

也就是说可以理解为对象其实也是由函数构造,Object其实也是个函数,而任何函数都是Function的实例对象(Object.__proto__ === Function.prototype),而函数自己构造了自己(Function.__proto__ === Function.prototype),也来看图理解


但是,敲黑板,不要进入一个误区,如果说一切对象都能访问到Object的prototype里面的方法,像hasOwnProperty,toString,valueOf,toLocaleString等等,那是不是对象都可以访问到在函数原型的方法,答案是,no. 原因又回到了原型链,大家不要进入误区,值得注意的是,原型链的指向,最后指向了Object.prototype而不是Object.__proto__,Object.prototype.__proto__ === null


所以原型链只需要要死死的记住二句话就行了,1.函数的实例对象的隐式原型(__proto__)指向的构造函数的原型对象(prototype),2.所有的最后都指向了对象的显示原型(prototype)


哈哈,终于写完了