一、继承与原型链
要点1:(__proto__与prototype)
说到JS中的继承,在ES6之前就只有原型链,ES6出现了class,但只是语法糖,JS的继承仍然是基于原型的。
__proto__: 隐式原型。每个对象都有一个私有属性[[Prototype]], 它指向它的构造函数的原型对象(prototype)。
而__proto__是[[Prototype]]的非标准实现(绝大多数浏览器都已经实现),但是不建议直接操作该属性。
ES5中有了对这个属性的标准Get方法,Object.getPrototypeOf()
prototype:显式原型,叫做原型对象。
关于__proto__与prototype: 知乎链接https://www.zhihu.com/question/34183746中的doris已经讲的很好了。
他的图中有一点不是很清楚,就是 function Foo() ---(Foo created by Function)---- __proto__--->Function.prototype
跟function Object() ---(Object created by Function)----__proto__------>Function.prototype
应该是这样理解吧:如下代码
Foo.__proto__ === Function.prototype// ture
Object.__proto__ === Function.prototype//true,这里的Object是构造函数,eg: const obj = new Object();
他的总结为:
1.对象有属性__proto__,指向该对象的构造函数的原型对象。
2.方法除了有属性__proto__,还有属性prototype,prototype指向该方法的原型对象。
要点2:(原型链)
所有的原型对象最终都可以上溯到Object.prototype,这里提到的上溯指的是不断地通过__proto__链接上去,比如
Function.prototype.__proto__ === Object.prototype// true
也就是说,所有对象都继承了Object.prototype的属性,这就是所有对象都有valueOf和toString方法的原因。
那么Object.prototype的原型是什么呢?
Object.getPrototypeOf(Object.prototype)//null
二、基于原型链的继承
假设有一个Parent,有个Child需要通过原型链的方式继承Parent
function Parent() {
this.a = a;
}
function Child () {
Parent.call(this, a);//
this.b = b;
}
Child.prototype = Object.create(Parent.prototype);//应该跟Object.setPrototypeOf(Child.prototype, Parent.prototype)是一样的效果吧
Child.prototype.constructor = Child;//这里需要将constructor属性重新赋值为Child,不然new出来的不是Child的实例
Child.prototype.method = function () {...}
这里之所以需要将Child.prototype = Object.create(Parent.prototype), 而不是Child.prototype = Parent.prototype,不然后面两行对Child.prototype的操作会直接修改掉父类的原型Parent.prototype. 这样的话Object.create或者Object.setPrototypeOf到底做了什么呢?
2.1 Object.create()
根据定义:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create
The Object.create()
method creates a new object, using an existing object to provide the newly created object's __proto__.
Child.prototype = Object.create(Parent.prototype);
//根据定义,可以理解为
Child.prototype = {
__proto__: Parent.prototype
}
根据定义:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/setPrototypeOf
The Object.setPrototypeOf()
method sets the prototype (i.e., the internal [[Prototype]]
property) of a specified object to another object or null
.
可以通过Object.setPrototypeOf(obj, prototype)修改obj的[[Prototype]]属性(在浏览器中即是__proto__)为指定的prototype.所以它类似Object.create(),不同的是Object.create会新建一个Object。
三、ES6 class
明天继续