继承(Inheritance)是一种在新对象上复用现有对象的属性的形式。这有助于避免重复操作。在JavaScript中,继承原理与其他面向对象语言有些不同。我们通过三步操作来看一下如何实现继承。
1、用函数的“原型对象”实现继承,如【清单-1】,程序执行后,三个日志全部打印了出来,这说明Woman继承自Person,wman既是Person又是Woman,同时wman也有sing方法,证明这样实现了继承。
/*
清单-1
*/
function Person(){}
Person.prototype.sing = function(){};
function Woman(){}
//通过将Woman的原型对象赋值为Person的实例,实现继承Person
Woman.prototype = new Person();
const wman = new Woman();
if(wman instanceof Woman)
console.log("wman is a instance of Woman");
if(wman instanceof Person)
console.log("wman is a instance of Person");
if(typeof wman.sing === "function")
console.log("wman can sing!");
2、在清单-1的14行打个断点调试一下,通过调试的方法深入研究一下继承究竟是怎么实现的。如图-1
【图-1】
3、我们将图-1中1、2、3 的关系用图的方式表现一下,如图-2:
【图-2】
从图-2可以看出
1)Woman是包含了Person(Prototype : Person),可以理解为继承了Person。
2)wman是Woman的对象(wman : Woman),wman包含了Person(proto : Person),可以理解为wman也是Person的对象。
【总结】
这里我们用函数的“原型对象”和对象的“原型链”实现了“继承”,注意原型对象(prototype)和原型(proto)不是一个概念,通过图-1和图-2都可以看出。不过这里有wman.constructor 不指向Woman 而是指向了person,就不能通过new wman.constructor()创建Woman对象了。
针对总结中出现的问题,通过修改属性的方式,将constructor指向Woman,修改代码如【清单-2】。
/*
清单-1
*/
function Person(){}
Person.prototype.sing = function(){};
function Woman(){}
//通过将Woman的原型对象赋值为Person的实例,实现继承Person
Woman.prototype = new Person();
const wman = new Woman();
if(wman instanceof Woman)
console.log("wman is a instance of Woman");
if(wman instanceof Person)
console.log("wman is a instance of Person");
if(typeof wman.sing === "function")
console.log("wman can sing!");
//定义一个新的不可枚举的constructor属性,属性值为Woman
Object.defineProperty(Woman.prototype, "constructor", {
enumerable: false,
value: Woman,
writable: true
});
if(wman.constructor == Woman)
console.log("wman's constructor is Woman")