(先给csdn点个赞,富文本编辑器改版好用多了,我终于能用水平线啦)
从对象的创建谈原型
在Java中,创建对象的方法是:先用class把问题抽象出来,再用new实例化产生对象
在js中,创建对象的方法当然可以用new实例化类得到(如 let obj = new Type());
也可以用 let obj = {}的方法创建。
比较熟悉Java或C++的同僚自然而然就觉得js第二种创建对象的方式太奇怪了,作为面向对象语言,这样都行??
那么怎么理解js的这种看似“奇葩”的方式,在这种方式下怎么理解类与对象的关系呢?
答案就是:js没有类,而是用了一套原型系统
又一个问题来了,什么是原型系统,怎么用的??
在js中,每一个对象都是基于另一个对象的克隆,而不是真正的实例化类。
每次创建一个对象是要找到另一个对象作为原型并克隆它,新创建的对象会记住它的原型。
如果这个对象无法响应某个请求,它会把这个请求委托给自己的原型(找他老爸去)。
这也就是原型链的概念
举个栗子:对象c克隆于b,b克隆于a。即c的原型是b,b的原型是a,a的原型就是终极原型(老祖宗):Object.prototype
讲到这,我们回过头看一下对象创建的两种方式的具体原理,上两张图:
方式一:
方式二:
其中,create方法是es5提供的,用来创建一个具有指定原型且可选择性地包含指定属性的对象。
而__proto__是对象的属性,指向构造该对象的构造函数的原型。看下面介绍:
JS对象分为普通对象和函数对象。
凡是通过new Function()创建的对象是函数对象,其他都是普通对象。
所有的对象都有__proto__属性,用于构建原型链,但只有函数对象具备prototype属性。
对于特殊的顶层对象函数Function,Function.__proto__ === Function.prototype。
let obj = new Type() 完整的原型链如下:
obj-->Type.prototype-->Function.prototype-->Object.prototype
(当然,es6已经引入了语法糖,允许用class创建对象)