1,前言
早期,js的使用还主要集中于浏览器中,但是随着nodejs进军服务器开发和react native逐渐向移动端渗透,一个属于js的全栈时代就要来临了,而且js界还流传一句名言:“所有能用js开发的应用程序,最终都会用js开发,就问你怕不怕?”
好了,说了这么多,我并不是说js是世界上最好的语言(显然是PHP才是,对半?),也不是觉得js回替代谁,我只是觉得js将会是一个大家都应该了解和学习的语言工具。
2,面向对象
2.1实现思路
面向对象是大家都很熟悉的程序设计思想,是对真是世界的抽象,目前主要oop语言用来实现面向对象的是类,通过类的封装,继承来映射真实世界,包括Java,c#,甚至是Python等都是通过类的设计来实现面向对象的,但是仔细想起来也会觉得有问题,因为真实的世界没有类这种概念,只有一个个不同的对象,真实世界中继承只发生在一个个不同的对象中,继承关系发生在对象和对象之间,而不是类,就比如孩子是对象,父母也是对象,孩子继承自父母。
2.2原型概念
相关的概念其实我研究了好几天,除开原型概念本身,与之练习的对象的产生,构造函数,proto,prototype的区别,为什么对象没有prototype这个指向原型的属性,而是使用proto来指向原型呢?
好,我们先来谈谈原型这个概念,js中一切皆对象,而每个对象都有一个原型(object除外),这个原型大概就像Java中的父类,即每个对象(object除外)内部都保存了他自己的父对象,如果没有特别指定的原型,那么它的原型就是object(这就很类似Java中所有的类默认继承自object类)。
2.3对象创建
在js中,对象创建的方法有很多中,最常见的如下:
这三种写法创建的对象的原型都是object。需要提到的是,ES6通过引入class,extends等关键字,以一种语法糖的形式把构造函数包装成类的概念,更便于大家理解。是希望开发者不再花时间和精力去关注原型以及原型链,也充分说明原型的设计意图和类是一样的。
2.3查看对象原型
当对象被创建以后查看对象原型的方法不止一种,以前一般使用对象的proto属性,ES6推出后,推荐使用Object.getPrototypeOf(a)方法来获取对象的原型。
无论对象是如何创建的,默认原型都是Object,在这里需要提及的比较特殊的一点是,通过构造函数来创建对象,函数A本身也是一个对象,而A有两个指向表示原型的属性,分别是proto和prototype,而且两个属性并不相同
函数的prototype属性只有在当做构造函数创建的时候,把自身的prototype属性赋值给对象的原型。而实际上,作为函数本身,它的原型应该是function对象,然后function对象的原型才是object。
总之,建议使用ES6推荐的查看原型和设置原型的方法。
2.4原型的用法
其实原型的用法和类的继承的用法是一致的,当你想用某个对象的属性时,将当前对象的原型指向该对象,你就拥有该对象的使用权了
如果使用ES6来做的话简单很多,甚至不涉及prototype这个属性
怎么样?是不是已经完全看不到原型的影子了,活脱脱就是类继承,但是你也看到实际上A的类型是function,所以本质上class是js中的一种语法糖,js继承的本质依然是原型,不过,ES6韵如class,extends来掩盖原型的概念也是一个很友好的举动,对于长期学习那些类继承为基础的面向对象语言的程序员,我的建议是竟可能理解原型,尽可能用class这种语法糖
2.5原型链
这个概念其实也变得比较简单,可以类比类的继承链条,即每个对象的原型往上追溯,一直到object为止,这组成了一个链条,将其中的对象串联起来,当查找当前对象的属性时,如果没找到,就会沿着这个链条去查找,一直到object,如果还没发现,就会报underfined。那么也意味着你的原型链不嫩太长,否则会出现效率问题
3,总结
对于原型概念的理解:类比类的继承,对象的原型就是它的父对象
原型的运用:尽可能使用ES6的标准,使用class,extends,object.getPrototypeOf(),object.setPrototypr()等等
需要注意的点是:原型链条不要太长,指定原型是constructor也会改变