要理解继承,首先需要理解原型链
function Person(name, age, gender){ this.name = name this.age = age this.gender = gender } Person.prototype.hi = function (){ console.log(`Hi, I'm ${this.name}`) } let f = new Person('zoe', 18, 'female') f.__proto__ === Person.prototype // true,ES5写法 Object.getPrototypeOf(f) === Person.prototype // true,ES6写法, __proto__ 是浏览器厂商私建 Person.prototype.__proto__ === Object.prototype // true 首先定义几个基本名词:
实例对象:通过new xxx出来的对象叫做实例对象 构造函数:如上方代码中的Person,一般以大写字母开头命名 - __proto__:ES6 之前,没有明确访问原型的方法,只能通过__proto__来访问,它的作用就是找到实例对象的原型 prototype:原型,是构造函数的一个属性 constructor:构造函数,写过 Java 这类 oop 的同学应该不陌生,这个在 ES5 中不经常接触到,ES6 中的 Class 经常用到, 然后通过上面的代码,我们可以得到这样的公式:
实例对象.__proto__ === 构造函数.prototype 构造函数.prototype.__proto__ === Object.prototype (长继承不适用,这里的继承链是 Person 继承 Object) 其次,Object 是原型链的顶端 Object.prototype.__proto__ === null ok,那么明白了这个,我们就来讨论继承,继承本质上只是用来减少重复代码的一种编程手段,如果我们有多个类,并且都有重复的属性,那么我们可以将重复的属性提取到父类身上,再由父类通过继承给子类。再简化一下:子类构造函数的实例对象也能访问到父类的属性或方法。
function Male(name, age){ this.name = name this.age = age this.gender = 'male' } let m = new Male("m", 24) function Female(name, age){ this.name = name this.age = age this.gender = 'female' } let f = new Female("f", 24) 在上面这个例子中,我们定义了两个构造函数,分别来构造男性和女性,但是 name 和 age 重复了,此时我们可以创建一个父类,来优化掉重复的代码
...