问题
- 在继承时,为什么需要调用 super 方法?
- B 类继承 A 类后,可以访问到A类中的私有方法和属性吗?
- A 类中在属性上添加方法和直接添加方法有什么区别?
先上代码
class A {
constructor() {
this.a1 = 'a1';
}
private a1: string;
private a2 = 123
private a3 = function() {
console.log('a3');
}
private a4() {
console.log('a4');
}
a5 = function() {
console.log('a5');
}
a6() {
console.log('a6');
}
a7 = 'a7'
a8: string;
static a8 = '123';
static a9 = function() {
console.log('a9');
}
static a10() {
console.log('a10');
}
static a11: string;
}
class B extends A {
constructor() {
super();
console.log(this);
}
private b1 = function() {
console.log('b1')
}
b2 = function() {
console.log('b2');
}
private b3() {
console.log('b3');
}
b4() {
console.log('b4');
}
static b5() {
console.log('b5');
}
}
问题一
我们先分别来看下有写
super()和没有写super()语句,经过babel编译后对应的es5代码是什么 没有super()时
function B() {
var _this;
console.log(_assertThisInitialized(_this));
return _assertThisInitialized(_this);
}
有super()时
function B() {
var _this;
_this = _A.call(this) || this;
..省略..
console.log(_assertThisInitialized(_this));
return _this;
}
可以看到,如果
- 执行了
super(), 在实例化B类时,会使用函数B的this对象去执行A函数, 从而可以在B函数中访问到A函数中绑定到this对象上的属性,从而实现this的继承。 - 如果没有执行
super(),在B函数内部 this 对象为undefined,并且无法从访问A函数中绑定到this对象上的属性;
问题二
从下面代码中可以很明显的看到,经过babel编译后在B类中可以访问到A类的私有属性和方法
问题三
A 类中使用属性添加方法和直接添加方法,如:A类中的
a3方法和a4方法经过babel编译后
// a3 方法添加到了 A 函数的this对象上
_defineProperty(this, "a3", function () {
console.log("a3");
});
// a4 方法添加到了 A 函数的 prototype 对象上
var _proto = A.prototype;
_proto.a4 = function a4() {
console.log("a4");
};
这样会导致我们可以直接通过 A.prototype.a4 访问 a4方法,但是无法通过这样的方式访问到a3方法
如果在A类的属性或方法前添加 static 关键字,那么该属性和方法将会直接添加在A函数对象上,这些属性也无法被继承
使用babel编译后的完整代码如下:
function _assertThisInitialized(self) {
if (self === void 0) {
throw new ReferenceError(
"this hasn't been initialised - super() hasn't been called"
);
}
return self;
}
function _inheritsLoose(subClass, superClass) {
subClass.prototype = Object.create(superClass.prototype);
subClass.prototype.constructor = subClass;
_setPrototypeOf(subClass, superClass);
}
function _setPrototypeOf(o, p) {
_setPrototypeOf = Object.setPrototypeOf
? Object.setPrototypeOf.bind()
: function _setPrototypeOf(o, p) {
o.__proto__ = p;
return o;
};
return _setPrototypeOf(o, p);
}
function _defineProperty(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
var A = /*#__PURE__*/ (function () {
function A() {
_defineProperty(this, "a2", 123);
_defineProperty(this, "a3", function () {
console.log("a3");
});
_defineProperty(this, "a5", function () {
console.log("a5");
});
_defineProperty(this, "a7", "a7");
this.a1 = "a1";
}
var _proto = A.prototype;
_proto.a4 = function a4() {
console.log("a4");
};
_proto.a6 = function a6() {
console.log("a6");
};
A.a10 = function a10() {
console.log("a10");
};
return A;
})();
_defineProperty(A, "a8", "123");
_defineProperty(A, "a9", function () {
console.log("a9");
});
var B = /*#__PURE__*/ (function (_A) {
_inheritsLoose(B, _A);
function B() {
var _this;
_this = _A.call(this) || this;
_defineProperty(_assertThisInitialized(_this), "b1", function () {
console.log("b1");
});
_defineProperty(_assertThisInitialized(_this), "b2", function () {
console.log("b2");
});
console.log(_assertThisInitialized(_this));
return _this;
}
var _proto2 = B.prototype;
_proto2.b3 = function b3() {
console.log("b3");
};
_proto2.b4 = function b4() {
console.log("b4");
};
B.b5 = function b5() {
console.log("b5");
};
return B;
})(A);