美文网首页
【JS原型&原型链】一张图说清楚

【JS原型&原型链】一张图说清楚

作者: _BuzzLy | 来源:发表于2019-02-20 23:44 被阅读0次

JavaScript原型&原型链

原型链图

原型链.png

如果你看到这张图一脸懵,不要怕,往下看,下面会一步一步教你认识原型&原型链

前置知识

js的初学者一般很难理解原型和原型链的概念,但原型和原型链又是js中最重要的点之一。从jQuery到现在最火的框架之一Vue,原型的应用无处不在,那我们该怎么学好JavaScript的原型和原型链呢?

  • 想要弄清楚原型和原型链,这几个属性必须要搞清楚,__proto__prototypeconstructor
  • 其次你要知道js中对象和函数的关系,函数其实是对象的一种。
  • 最后你要知道函数、构造函数的区别,任何函数都可以作为构造函数,但是并不能将任意函数叫做构造函数,只有当一个函数通过new关键字调用的时候才可以成为构造函数。如:
var Parent = function(){

}
//定义一个函数,那它只是一个普通的函数,下面我们让这个函数变得不普通
var p1 = new Parent();
//这时这个Parent就不是普通的函数了,它现在是一个构造函数。因为通过new关键字调用了它
//创建了一个Parent构造函数的实例 p1

如果到这你都能理解,
我们再引出一个概念,开始说过了要想清楚原型就要先搞清楚,__proto__prototypeconstructor

  • 我们记住两点
    1.__proto__constructor属性是对象所独有的;
    2.prototype 属性是函数独有的;
    3.上面说过js中函数也是对象的一种,那么函数同样也有属性__proto__constructor

下面开始进入正题↓↓↓

1.prototype属性

prototype属性.png

它是函数独有的属性,它从一个函数指向另一个对象,代表这个对象是这个函数的原型对象,这个对象也是当前函数所创建的实例的原型对象。
prototype设计之初就是为了实现继承,让由特定函数创建的所有实例共享属性和方法,也可以说是让某一个构造函数实例化的所有对象可以找到公共的方法和属性。有了prototype我们不需要为每一个实例创建重复的属性方法,而是将属性方法创建在构造函数的原型对象上(prototype)。那些不需要共享的才创建在构造函数中。
继续引用上面的代码,当我们想为通过Parent实例化的所有实例添加一个共享的属性时,

Parent.prototype.name = "我是原型属性,所有实例都可以读取到我";

这就是原型属性,当然你也可以添加原型方法。那问题来了,p1怎么知道他的原型对象上有这个方法呢,往下看↓↓↓

2.proto属性

proto属性.png

__proto__属性是对象(包括函数)独有的。__proto__属性是从一个对象指向另一个对象,即从一个对象指向该对象的原型对象(也可以理解为父对象)。显然它的含义就是告诉我们一个对象的原型对象是谁。
prototype篇章我们说到,在上面添加的属性和方法叫做原型属性和原型方法,该构造函数的实例都可以访问调用。那这个构造函数的原型对象上的属性和方法,怎么能和构造函数的实例联系在一起呢,就是通过__proto__属性。每个对象都有__proto__属性,该属性指向的就是该对象的原型对象。

p1.__proto__ === Parent.prototype; // true

__proto__通常称为隐式原型,prototype通过成为显示原型,那我们可以说一个对象的隐式原型指向了该对象的构造函数的显示原型。那么我们在显示原型上定义的属性方法,通过隐式原型传递给了构造函数的实例。这样一来实例就能很容易的访问到构造函数原型上的方法和属性了。
我们之前也说过__proto__属性是对象(包括函数)独有的,那么Parent.prototype也是对象,那它有隐式原型么?又指向谁?

Parent.prototype.__proto__ === Object.prototype; //true

可以看到,构造函数的原型对象上的隐式原型对象指向了Object的原型对象。那么Parent的原型对象就继承了Object的原型对象。由此我们可以验证一个结论,万物继承自Object.prototype。这也就是为什么我们可以实例化一个对象,并且可以调用该对象上没有的属性和方法了。如:

//我们并没有在Parent中定义任何方法属性,但是我们可以调用
p1.toString();//hasOwnProperty 等等的一些方法

我们可以调用很多我们没有定义的方法,这些方法是哪来的呢?现在引出原型链的概念,当我们调用p1.toString()的时候,先在p1对象本身寻找,没有找到则通过p1.__proto__找到了原型对象Parent.prototype,也没有找到,又通过Parent.prototype.__proto__找到了上一层原型对象Object.prototype。在这一层找到了toString方法。返回该方法供p1使用。
当然如果找到Object.prototype上也没找到,就在Object.prototype.__proto__中寻找,但是Object.prototype.__proto__ === null 所以就返回undefined。这就是为什么当访问对象中一个不存在的属性时,返回undefined了。

3.constructor属性

constructor属性.png
constructor是对象才有的属性,它是从一个对象指向一个函数的。指向的函数就是该对象的构造函数。每个对象都有构造函数,好比我们上面的代码p1就是一个对象,那p1的构造函数是谁呢?我们打印一下。
console.log(p1.constructor); // ƒ Parent(){}

通过输出结果看到,很显然是Parent函数。我们有说过函数也是对象,那Parent函数是不是也有构造函数呢?显然是有的。再次打印下。

console.log(Parent.constructor); // ƒ Function() { [native code] }

通过输出看到Parent函数的构造函数是Function(),这点也不奇怪,因为我们每次定义函数其实都是调用了new Function(),下面两种效果是一样的。

var fn1 = new Function('msg','alert(msg)');
function fn1(msg){
    alert(msg);
}

那么我们再回来看下,再次打印Function.constructor

console.log(Function.constructor); // ƒ Function() { [native code] }

可以看到Function函数的构造函数就是本身了,那我们也就可以说Function是所有函数的根构造函数。
到这里我们已经对constructor属性有了一个初步的认识,它的作用是从一个对象指向一个函数,这个函数就是该对象的构造函数。通过栗子我们可以看到,p1constructor属性指向了Parent,那么Parent就是p1的构造函数。同样Parentconstructor属性指向了Function,那么Function就是Parent的构造函数,然后又验证了Function就是根构造函数。

总结

  • 看到这我相信大家已经对原型和原型链有了一定的理解了,还没有特别理解的同学也不要担心,原型原型链以及闭包都是js中最难的几部分,需要一定的技术积累和时间沉淀。每天打开文章看一遍,自己画一遍这个原型链的图,因为其中有些原理是说不出来的,得靠自己去体会理解。不积跬步无以至千里不积小流无以成江海。

相关文章

  • 【JS原型&原型链】一张图说清楚

    JavaScript原型&原型链 原型链图 如果你看到这张图一脸懵,不要怕,往下看,下面会一步一步教你认识原型&原...

  • 再来看一次JS继承

    原型链继承 理解原型链的概念 用一张图来理解原型链再合适不过了。 总结概括JS红宝书上对原型链的概念:每个函数都有...

  • 原型和原型链

    今天发现一张特别好的图(↑↑↑上图↑↑↑),对原型和原型链的理解特别直观友好。 原型和原型链 基础储备:每个 JS...

  • 廖雪峰JS小记

    (function(){})() 原型,原型链 浅谈Js原型的理解JS 原型与原型链终极详解 对象 对象:一种无序...

  • 原型链和class继承

    从网上找了一张图,比较清楚的描述了原型链 原型链 1.原型链的定义 每个对象都可以有一个原型proto,这个原型还...

  • Javascript(三)之原型继承理解

    进阶路线 3 原型继承 3.1 优秀文章 最详尽的 JS 原型与原型链终极详解 一 最详尽的 JS 原型与原型链终...

  • JS的__proto__和prototype

    最近在回顾JS的原型和原型链的知识,熟悉JS的同学都知道JS的继承是靠原型链实现的,那跟原型链相关的属性__pro...

  • js继承完全理解

    认识原型链 要理解js的继承原来要先理解原型链,要理解原型链要先清楚下面两个结论: 任何一个构造函数(其实是任何一...

  • 关于JS中的原型和原型链

    目录 关于js 对象和原型 原型链 基于原型链的继承 参考资料ECMAScript 6 入门JavaScript原...

  • js_继承及原型链等(四)

    js_继承及原型链等(三) 1. 继承 依赖于原型链来完成的继承 发生在对象与对象之间 原型链,如下: ==原型链...

网友评论

      本文标题:【JS原型&原型链】一张图说清楚

      本文链接:https://www.haomeiwen.com/subject/afskyqtx.html