前言
今天在复习原型的知识点时, 发现有些对原型继承有点模糊. 上网查了一下 ES5 原型继承的方法, 各种继承方法看的有点小晕. 大家比较认可的应该是 寄生组合式继承 . 我在知乎上看到一篇文章, 让我受益良多, 这篇文章是我自己做的学习总结. JS 的继承 - 若川
原型
首先复习一下原型, 我画了个图
原型关系图
当寻找一个对象的属性是, 如果对象本身没有这个属性, 则在对象的原型链上一层一层往上找 (原型链是靠隐式原型__proto__链接起来的).
关于继承
引用大佬的一句话:
继承对于 JS 来说就是父类拥有的属性和原型方法, 静态方法等, 子类也要拥有.
之前我一直以为, 只要 Child.prototype.__proto__ = Parent.prototype 就可以了. 但是看了若川大佬的文章, 我才发现, 这样只能让子类继承父类的实例属性和实例方法 (在我看来, 原型方法也叫实例方法).
要拿到父类的静态属性和静态方法, 还需要注意构造器的原型链继承 Child.__proto__ = Parent;
代码
- // 父亲
- function Parent(num) {
- this.num = num;
- }
- // 原型属性和原型方法
- Parent.prototype.type = 'human';
- Parent.prototype.sayNum =function(){
- console.log('num:' + this.num);
- }
- // 静态属性和静态方法
- Parent.staticType = 'staticHuman';
- Parent.sayHello = function () {
- console.log('Hello')
- }
- // 儿子
- function Child(num,age) {
- // 相当于 super
- // 子类构造器里调用父类构造器, 继承父类的属性.
- Parent.call(this,num);
- this.age = age;
- }
- Child.prototype.sayAge = function () {
- console.log('age:' + this.age);
- }
继承
- // 子类构造函数的 prototype 的__proto__指向父类构造器的 prototype, 继承父类的方法.
- Child.prototype.__proto__ = Parent.prototype;
- // 子类构造函数的__proto__指向父类构造器, 继承父类的静态方法
- Child.__proto__ = Parent;
测试
- const parent = new Parent(1);
- console.log(parent.type); //human
- console.log(Parent.staticType); //staticHuman
- parent.sayNum(); //1
- Parent.sayHello(); //Hello
- const child = new Child(2,18);
- console.log(child.type); //human
- console.log(Child.staticType); //staticHuman
- child.sayNum(); //2
- child.sayAge(); //18
- Child.sayHello(); //Hello
- Object.setPrototypeOf()
其中__proto__是浏览器自己的实现, 也可以用 Object.setPrototypeOf() 的方法设置隐式原型
- Child.prototype.__proto__ = Parent.prototype
- // 等同于
- Object.setPrototypeOf(Child.prototype, Parent.prototype)
小结
我也用 ES6 的语法写了一遍, 测试结果是一样的. 虽然 ES6 的 class,extends 语法糖真的很香, 但是我觉得理解一下 ES5 的原型继承也是很有必要的. 如果有大佬发现哪里有问题, 欢迎评论指出~
来源: http://www.jianshu.com/p/90619bb85cb1