JS原型链

至于为什么讲JS原型链这些JS原理基础,因为本人在学习React时,JS基础薄弱感觉自己白学了,因为没能理解。然后学完JS,再去学React,就能稍微理解React了。大家要明白一个事实就是React、Vue等框架或是插件的底层都是JS,所以学好JS还是非常有必要的。但这也只是个人的建议,仅供参考。希望大家能在理解原型链的基础上去记忆,这样能学的更好。

 

首先来说说prototype属性,不像每个对象都有__proto__属性来标识自己所继承的原型,只有函数才有prototype属性。

为什么只有函数才有prototype属性?ES规范就这么定的。

其实函数在JS中真的很特殊。JS不像其它面向对象的语言,它没有类(class,ES6引进了这个关键字,但更多是语法糖)的概念。JS通过函数来模拟类。

当你创建函数时,JS会为这个函数自动添加prototype属性, 值是一个有 constructor 属性的对象,不是空对象。而一旦你把这个函数当作构造函数(constructor)调用(即通过new关键字调用),那么JS就会帮你创建该构造函数的实例,实例继承构造函数prototype的所有属性和方法(实例通过设置自己的__proto__指向承构造函数的prototype来实现这种继承)。

 

那么简单的讲解下原型链:

假设我们访问Person实例对象中的 name 属性时,它会先在自己身上找有没有 name 属性。如果自身有 name 属性,那么Person就会直接使用自己身上 name 属性;

如果没有 name 属性,Person就会顺着  _proto_   (原型链) 去查找 name 属性,若是找到就会调用 name 属性。

如果前面都没找到,最后就只能找到 Object的原型对象(原型链的尽头),还是没有找到那么就会返回  undefined

下面结合代码和图解,来更详细地解释:

function Fn() {
    this.test1 = function () {
        console.log('test1()');
    }
 }

 Fn.prototype.test2 = function () {
      console.log('test2()');
 }

 var fn = new Fn()

 fn.test1() //输出  test1()
 fn.test2() //输出  test2()

 

特别要注意的是,函数是函数,对象是对象,不然理解下面的内容可能会有点难度。

首先我们声明了Fn()函数,并且使Fn函数对象上有了test1()这一方法,然后通过 prototype 在Fn的原型对象上声明了test2()方法。

然后我们创建了Fn的实例对象 fn( 注意是Fn的实例对象是对象Object,Fn()是函数function ),fn是对象

调用 fn.test1()   由于自身上拥有test1()方法,可以直接调用Fn实例对象自身的方法test1()。

调用   fn.test2() 自身上没有 test2() 方法,那么顺着原型链去查找,并且在Fn的原型对象上找到了test2(),最后在调用。

 

 

 

 

我们可以在控制台,查看具体的信息

console.log('fn的类型为', typeof fn);          //fn的类型为 object
console.log('fn.test1 的类型为',typeof fn.test1);    //fn.test1 的类型为 function
console.log('Fn的类型为',typeof Fn);          //Fn的类型为 function
  console.log('new Fn() 的类型为',typeof new Fn());  //new Fn() 的类型为 object

console.log(fn);

fn的具体信息:

 

由此图,我们可以看出test1()确实是在 fn对象自身上的,test2()在Fn原型对象上,剩余的方法和属性全在Object原型对象上。

并且fn可以使用上图中的所有方法和属性。

 

posted @ 2021-04-23 11:08  AkeAke  阅读(77)  评论(0)    收藏  举报