之前
看了网上很多相关介绍,终是对原型无法透彻的理解,介乎于感性和理性之间,像点点星光,虽有光辉,却无恒热。
再会一会
这段时间学习VUE等框架,学到酣处,总想探一探它的原理,便发现自己对原型的理解有些不足。前面虽有两篇关于原型的理解记录,但现如今再看一遍,自己竟也不知当时如何写就。
开篇
其实作为一枚JAVA后端人员,对JS的第一感觉便是,这丫的怎么那么像一个山寨货?类,对象,构造函数,继承,父类,子类,等等,但确定它不是JAVA。JAVA中的一些概念在它的进化之路上可以发现慢慢变丰富了。JAVA是一门面向对象的语言,这些概念也是面向对象编程语言的部分特征,为啥要面向对象编程,简单说就是项目大了,面向对象编程语言能更轻松开发与维护。以前你可见过JS用作服务端开发语言?反正从我认识它的时候,它就在每个页面的script标签里为一个一个button或form的事件处理兢兢业业,很平凡,直到后来的某一天,在node的环境中见到时,震惊了。
正文
- JS的原型和设计模式中原型是不太一样的,原型设计模式的主要目标是降低创建大量相似对象的成本,JS的原型虽有一部分这样的考虑,更多的是要实现对象属性的继承。在JS朝着面向对象编程发展的时候,原型便成了实现父类子类间继承的关键。它唯一的目标便是提供像子类与父类这样在编程上的关系。所以,你说JS的原型,就是在说JS中的继承。当你说某个对象的原型,其实就是在说某个的对象的父类,在JAVA中,每个对象都有两个特殊的指针(属性),this指代当前对象,super指当前对象的父类。在JS中,this也是指的当前对象,当前对象的原型(父类),却是用__proto__这个特殊的指针(属性)。
- 面向对象编程中,构造函数的作用便是在创建对象的时候初始化对象的一些属性值,别的想法就没了。JS中的对象也有构造函数的指针(属性) constructor ,它所指向的就是对象的构造函数。
- JS中呢,是没有真正的类的,它没有类来作为创建一个对象的模版,只有作用类似于类的构造函数,由它来指定所有通过new 出来的对象的共同属性。
- JS中要实现继承,由于它没有类,便用另一种方式实现,它的实现方式便是在构造函数上加了一个属性,名为 prototype,也是一个指针,指向的是一个对象,这个对象就是父对象。
- 你问,JS中对象的构造函数是哪个,就找它的 constructor 属性,你问它的父对象(类)是哪个,你就找它的 __proto__属性或者找 constructor 属性对象的prototype属性,这两个属性指向的都是同一个对象。
- 其实原型到这就没了,它所解决的问题就是找父类的问题,你已经知道如何找父类了,也知道,要定义一些所有子类都要有的属性,就去给它的构造函数的prototype属性对象上加属性,那么原型还有什么其他的追求么,真没了,你再想更多的东西,那都是和这门语言的作者过不去。
- 如果你要问Function和Object ,你肯定是没搞明白这两个到底是什么,它俩是构造函数,是函数,如果你说它是类,你见过能 Function()或Object()的类么?如果你见过,可以学习学习JAVA或任意一门面向对象的语言。JS中是没有真正的类的,class 标识符也仅仅是一个语法糖,通过class 定义的类,也限定了只能通过 new 来创建,本质还是构造函数,可以看看new 出来的对象的constructor 的属性指向了谁,看看其中的属性是否和函数有什么差别。通常在JS中说的类,其实说的是构造函数。只是这两个函数的父类和构造函数比较特殊而已。
- 另外,你看见的以大写开头的东西,比如,Array,Boolean,Date,Math,Number,String,RegExp 等等,他们都是构造函数,是函数,也是一个对象,他们是内置的,你可以new 也可以直接当方法调用。当你把它看成构造函数的时候,你应该想的就是用它创建一个对象,或者用它的prototype属性给此类所有对象加一个共同属性或方法。如果你将它看成一个函数,你应该想的的是它的功能,如何使用(调用),别的就别想了,当你将它看成函数的时候,也别想这着什么面向对象编程了,函数不是面向对象编程中的名词,而是面向过程编程中的,面向对象编程中,你应该叫它方法。并且,调用方式是 [对象.方法]。如果你将它看成一个对象,那你想的应该是如何支撑你的数据模型,应该具有哪些属性和功能。
- 原型链,就是继承链,谈这个是想说啥,属性继承,但是JS不谈这个,它想说如何查找属性。其实都是一个意思。怎么查找属性,当然是沿着父类一直找下去。
结束
如果有为你带来任何一点感悟或疑惑,请让我也知道,星星之光,一路同伴。