类与原型
什么是原型:
原型是顺应人类自然思维的产物。中文中有个成语叫做“照猫画虎”,这里的猫看起来就是虎的原型,所以,由此我们可以看出,用原型来描述对象的方法可以说是古已有之。最为成功的流派是使用类的方式来描述对象,诞生了如:C++、Java等流行的编程语言,这个流派叫做基于类的编程语言。还有一种就是基于原型的编程语言,它们利用原型来描述对象,Javascript就是其中的代表。
'基于类'的编程提倡使用一个关注分类和类之间关系开发模型。在这类语言中,总会现有类,再从类去实例化一个对象。类与类之间又可能会形成继承、组合等关系。类又往往与语言的类型系统整合,形成一定编译时的能力。
'基于原型'的编程看起来更为提倡程序员去关注一系列对象实例的行为,而后才去关心如何将这些对象,划分到最近的使用方式相似的原型对象,而不是将他们分成类。
Javascript的原型
如果所有对象都有私有字段[[prototype]],就是对象的原型。
读一个属性,如果对象本身没有,则会继续访问对象的原型,直到原型为空或者找到为止。
从 ES6 以来,JavaScript 提供了一系列内置函数,以便更为直接地访问操纵原型。三个方法分别为:
Object.create 根据指定的原型创建新对象,原型可以是 null。
Object.getPrototypeOf 获得一个对象的原型。
Object.setPrototypeOf 设置一个对象的原型。
利用这三个方法,我们可以完全抛开类的思维,利用原型来实现抽象和复用。
我们要把 new 理解成 JavaScript 面向对象的一部分,new 运算接受一个构造器和一组调用参数,实际做了几件事:
以构造器的 prototype 属性(注意与私有字段[[prototype]]的区分)为原型,创建新对象。
将 this 和调用参数传给构造器,执行。
如果构造器返回的是对象,则返回,否则返回第一步创建的对象。
new 这样的行为,试图让函数对象在语法上跟类变得相似,但是,它客观上提供了两种方式,一是在构造器中添加属性,二是在构造器的 prototype 属性上添加属性。
ES6中的类
ES6中引入了class关键字,并且在标准中删除了所有 class 相关的私有属性描述,类的概念正式从属性升级成语言的基础设施,从此,基于类的编程方式成为了 JavaScript 的官方编程范式。
类的写法实际上也是由原型运行时来承载的,逻辑上 JavaScript 认为每个类是有共同原型的一组对象,类中定义的方法和属性则会被写在原型对象之上。此外,最重要的是,类提供了继承能力。