前言
这一切都要从一道面试题开始说起
虽然被问的不是我,是我的舍友
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| class Parent { constructor (name = "Parent") { this.name = "Parent"; this.rua = "qaq" }
getName() { return this.name; }
getRua() { return this.rua; } }
class Child extends Parent { constructor (name = "Child", age = 16) { super(); this.name = name; this.age = age; }
getName() { return this.name; }
getSuperName() { return super.getName(); } }
let child = new Child();
|
问题是怎么拿到Parent
上的name
属性(也就是打印Parent
)
正文
我看了一下,我觉得应该是不大可的,想要通过child
拿到Parent
上的name
属性理论上是不可能的
首先我们来看看babel
转义后的代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
| "use strict";
function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; _setPrototypeOf(subClass, superClass); }
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
var Parent = (function () { function Parent(name) { if (name === void 0) { name = "Parent"; }
this.name = "Parent"; this.rua = "qaq"; }
var _proto = Parent.prototype;
_proto.getName = function getName() { return this.name; };
_proto.getRua = function getRua() { return this.rua; };
return Parent; })();
var Child = (function (_Parent) { _inheritsLoose(Child, _Parent);
function Child(name, age) { var _this;
if (name === void 0) { name = "Child"; }
if (age === void 0) { age = 16; }
_this = _Parent.call(this) || this; _this.name = name; _this.age = age; return _this; }
var _proto2 = Child.prototype;
_proto2.getName = function getName() { return this.name; };
_proto2.getSuperName = function getSuperName() { return _Parent.prototype.getName.call(this); };
return Child; })(Parent);
var child = new Child();
|
首先是这一段
1 2 3 4 5 6
| function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; _setPrototypeOf(subClass, superClass); }
|
继承做了3件事
- 通过
Object.create
创建一个对象temp
,并且把对象的constructor
属性设置成子类型的构造函数
- 把创建的对象
temp
设置成子类型构造函数的prototype
- 把子类型构造函数的
__proto__
指向父类型
值的注意的是,Object.create
和new
是不一样的
new
是使用构造方法创造对象,新建一个对象实例,继承原对象的prototype
属性
Object.create
是创建一个空对象,然后把_proto_
指向传入的参数的prototype
所以创建出来的Child
的prototype
是这样的
其中getName
和getSuperName
都是后来挂上去的
然后看看创建出来的child
对象
首先是通过call
调用父构造器
注意看,这里的name
和rua
属性都是Parent
上的
然后Child
构造函数继续处理this
可以看出来,属性是直接存在对象里的,只有一层,所以会被覆盖掉
而类对应的方法,会存在__proto__
里,不会被覆盖掉
所以,拿不到啊,被覆盖掉了啊,要拿到只能自己手写一个新的继承方法了
顺带一提,这里的getSuperName
没有任何用处
因为即使调用了Parent
上的getName
,但是this.name
的值还是Child
,所以还是只能打印出Child