最近大家都在聊 React,还老提到 “super”,看起来有点儿难懂。这到底是个啥玩意儿呀?
可能,同学会不会误会了?以为咱们这儿说的“超级”就是找爹地(父类)构造函数。千万别漏掉,给构造函数加点超级(super),否则程序就不对头咯。
原因很简单因为子类得告诉祖宗构造函数关于自个儿 this 对象的事儿,让祖宗心里有底。这就搞定了,咱们就可以把自家的个性加进去!要是不安特地叫 super,那还怎么拿到这个 this 对象?
// Shape - 父类(superclass) function Shape() { this.x = 0; this.y = 0; } // 父类的方法 Shape.prototype.move = function(x, y) { this.x += x; this.y += y; console.info('Shape moved.'); }; // Rectangle - 子类(subclass) function Rectangle() { Shape.call(this); // call super constructor. } // 子类续承父类 Rectangle.prototype = Object.create(Shape.prototype); Rectangle.prototype.constructor = Rectangle; var rect = new Rectangle(); console.log('Is rect an instance of Rectangle?', rect instanceof Rectangle); // true console.log('Is rect an instance of Shape?', rect instanceof Shape); // true rect.move(1, 1); // Outputs, 'Shape moved.'
你知道吗?ES6居然把这对象给改了跟以前可大不相同咯!有没有想起咱们那时研究的那本讲JS的书《JavaScript高级程序设计》里提到过的“寄生组合式继承”?这个概念就是在构造函数里面加上属性,然后和this捆绑起来;至于函数,就在 prototype上放着,这样子无论怎样继承,都是共享一份数据哟。
咱们该咋办?就让子类一开始就按着apply或call来模仿老妈的初始化方法呗。这么一搞,就像克隆一样,把老爸的程序整个搬过来。然后,用个新的招式——Object.create(Child.prototype),就好了。其实就是让Child.prototype跟Parent.prototype成为亲戚关系(让原型链从子类上去到老爸那儿)。
急性子先别急,ES6给继承搞舒服多了!增新了个extends代替老掉牙的super。而且连函数都可以是class。或许你觉得麻烦,但实际上,就跟平时咱们用的那些语法糖差不多。那么,怎么弄?跟着babel学学看呗。
class Point { constructor(x, y) { this.x = x; this.y = y; } toString() { return '(' + this.x + ', ' + this.y + ')'; } } class ColorPoint extends Point { constructor(x, y, color) { super(x, y); // 调用父类的constructor(x, y) this.color = color; } toString() { return this.color + ' ' + super.toString(); } }
嘿。看看这个,这就是Babel帮我们做的事,只要搞懂几个重点就没问题了!
这个规则是强调了构造函数要用“new”才能调用!
var ColorPoint = /*#__PURE__*/ function (_Point) { _inherits(ColorPoint, _Point); function ColorPoint(x, y, color) { var _this; _classCallCheck(this, ColorPoint); _this = _possibleConstructorReturn(this, _getPrototypeOf(ColorPoint).call(this, x, y)); // 调用父类的constructor(x, y) _this.color = color; return _this; } _createClass(ColorPoint, [{ key: "toString", value: function toString() { return this.color + ' ' + _get(_getPrototypeOf(ColorPoint.prototype), "toString", this).call(this); } }]); return ColorPoint; }(Point);
其实,就是先把现在这东西弄到手(’this’),然后给下一代接着用。这样下一代就能借着我们的文化遗产和个人本领,直接搞出点新鲜事儿咯!
如果这么做,那么子类中的 `this` 就不见了,绝对会搞砸的
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }
好了,现在得给属性和方法找个新家!要是构造函数里的原型属性,直接把它们安在构造函数的原型上就行;至于那些静态属性和方法,直接交给构造函数就完事了!
ColorPoint.__proto__ === Point; ColorPoint.prototype.__proto__ === Point.prototype;
你是不是在好奇为什么类里面总要有个”超级”?其实这货能让我们享用之前那个类的特色和方法,然后再发挥点儿我们自己的创新,简直就是绝配!有了它,继承就变得轻而易举了,棒极了!这下明白了?下次可别忘了把”超级”加到类中,这样继承起来才更加轻松。还是不懂的话?赶紧问,咱们立刻解决!别忘了顺便点个赞或转下贴子这样我会更有劲儿滴
function _classCallCheck(instance, Constructor) { if (!_instanceof(instance, Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
评论0