前言

这一切都要从一道面试题开始说起

虽然被问的不是我,是我的舍友

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 = /*#__PURE__*/ (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 = /*#__PURE__*/ (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.createnew是不一样的

  • new 是使用构造方法创造对象,新建一个对象实例,继承原对象的prototype属性
  • Object.create是创建一个空对象,然后把_proto_指向传入的参数的prototype

所以创建出来的Childprototype是这样的

image-20210416222802376

其中getNamegetSuperName都是后来挂上去的

image-20210416222934763

然后看看创建出来的child对象

首先是通过call调用父构造器

image-20210416223109704

注意看,这里的namerua属性都是Parent上的

然后Child构造函数继续处理this

image-20210416223514204

可以看出来,属性是直接存在对象里的,只有一层,所以会被覆盖掉

而类对应的方法,会存在__proto__里,不会被覆盖掉

所以,拿不到啊,被覆盖掉了啊,要拿到只能自己手写一个新的继承方法了

顺带一提,这里的getSuperName没有任何用处

因为即使调用了Parent上的getName,但是this.name的值还是Child,所以还是只能打印出Child