JS继承设计的缘由
看了阮一峰老师文章,总结了如下的几点:
- JS是基于面向对象的语言,需要一种机制,实现对象之间的关联
- 借鉴面向类的语言中
constructor构造函数的思想,和new关键字 - 解决数据共享的问题,引入
prototype
继承的实现方式
继承FAQ
__proto__ 与 prototype
__proto__(隐式原型)与prototype(显式原型)
首先,让我们明确以下的三点
显式原型:每一个
函数在创建之后,都会拥有一个名为prototype的属性,这个属性指向函数的原型对象
隐式原型:JavaScript中任意对象都有一个内置属性
[[prototype]],在ES5之前没有标准的方法访问这个内置属性,但是大多数浏览器都支持通过__proto__来访问。ES5中有了对于这个内置属性标准的Get方法Object.getPrototypeOf().- 隐式原型指向
constructor的prototype
两者的作用:
- 显式原型的作用:用来实现基于原型的继承与属性的共享。
- 隐式原型的作用:构成原型链,同样用于实现基于原型的继承。举个例子,当我们访问obj这个对象中的x属性时,如果在obj中找不到,那么就会沿着__proto__依次查找。
几点注意的地方:
- 通过
Function.prototype.bind方法构造出来的函数是个例外,它没有prototype属性 Object.prototype这个对象是个例外,它的__proto__值为null- 只有函数才有
prototype属性,这个属性值为一个object对象
实例对象时没有这个属性的,实例对象通过__proto__这个内部属性([[prototype]])来串起一个原型链的,通过这个原型链可以查找属性,方法
通过new操作符初始化一个构造函数对象的时候就会构建出一个实例对象,访问实例的constructor其实是访问实例的__proto__上的constructor对象,该对象指向的是prototype属性所在函数的指针。
关于Object.getPrototypeOf :
Object.getPrototypeOf 与__proto__ 的指向是一直的, prototype 是用于类型的,而 Object.getPrototypeOf() 是用于实例的(instances)
当执行以下的简单的代码时:
Bob.someProp
它会检查是否存在 someProp 属性。如果没有,它会查找 Object.getPrototypeOf(o).someProp ,如果仍旧没有,它会继续查找 Object.getPrototypeOf(Object.getPrototypeOf(o)).someProp ,一直查找下去,直到它找到这个属性 或者 Object.getPrototypeOf() 返回 null
注意:Object.getPrototypeOf(Object.prototype) 为null