Прежде чем углубляться в детали, давайте рассмотрим пример наследования реализации ES6.
class Point {
static NAME='point';
constructor(x, y) {
this.x = x;
this.y = y;
}
outPoint(){
console.log('point:'+this.x+this.y);
}
}
class ColorPoint extends Point {
static COLOR_NAME='ColorPoint';
constructor(x, y, color) {
super(x, y);
this.color = color;
}
outColorPoint(){
console.log('ColorPoint:'+this.x+this.y+this.color);
}
}
Теперь конвертируйте его в es5 через babel;
'use strict';
var _createClass = function() {
function defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
return function(Constructor, protoProps, staticProps) {
if (protoProps) defineProperties(Constructor.prototype, protoProps);
if (staticProps) defineProperties(Constructor, staticProps);
return Constructor;
};
} ();
function _possibleConstructorReturn(self, call) {
if (!self) {
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
}
return call && (typeof call === "object" || typeof call === "function") ? call: self;
}
function _inherits(subClass, superClass) {
if (typeof superClass !== "function" && superClass !== null) {
throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
}
subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: {
value: subClass,
enumerable: false,
writable: true,
configurable: true
}
});
if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
}
function _classCallCheck(instance, Constructor) {
if (! (instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
var Point = function() {
function Point(x, y) {
_classCallCheck(this, Point);
this.x = x;
this.y = y;
}
_createClass(Point, [{
key: 'outPoint',
value: function outPoint() {
console.log('point:' + this.x + this.y);
}
}]);
return Point;
} ();
Point.NAME = 'point';
var ColorPoint = function(_Point) {
_inherits(ColorPoint, _Point);
function ColorPoint(x, y, color) {
_classCallCheck(this, ColorPoint);
var _this = _possibleConstructorReturn(this, (ColorPoint.__proto__ || Object.getPrototypeOf(ColorPoint)).call(this, x, y));
_this.color = color;
return _this;
}
_createClass(ColorPoint, [{
key: 'outColorPoint',
value: function outColorPoint() {
console.log('ColorPoint:' + this.x + this.y + this.color);
}
}]);
return ColorPoint;
} (Point);
ColorPoint.COLOR_NAME = 'ColorPoint';
Это все еще выглядит грязно, мы упрощаем код, удаляем проверочную информацию, используем прототип вместо _createClass и упрощаем код
'use strict';
function _inherits(subClass, superClass) {
subClass.prototype = Object.create(superClass.prototype, {
constructor: {
value: subClass,
enumerable: false,
writable: true,
configurable: true
}
});
subClass.__proto__ = superClass;
}
var Point = function(x, y) {
this.x = x;
this.y = y;
}
Point.prototype.outPoint = function outPoint() {
console.log('point:' + this.x + this.y);
}
Point.NAME = 'point';
var ColorPoint = function(_Point) {
_inherits(ColorPoint, _Point);
function ColorPoint(x, y, color) {
ColorPoint.__proto__.call(this,x,y);
this.color = color;
}
ColorPoint.prototype.outColorPoint = function() {
console.log('ColorPoint:' + this.x + this.y + this.color);
}
return ColorPoint;
} (Point);
ColorPoint.COLOR_NAME = 'ColorPoint';
Упрощенный код можно увидетьМетод _inherits предназначен для реализации наследования объекта-прототипа родительского класса,Конструктор родительского класса применяется к ColorPoint.__proto__Точка, используйтеColorPoint.__proto__.call(this,x,y), используйте call для наследования свойств в конструкторе родительского класса
Давай поговоримObject.create
function _inherits(subClass, superClass) {
subClass.prototype = Object.create(superClass.prototype, {
constructor: {
value: subClass,
enumerable: false,
writable: true,
configurable: true
}
});
subClass.__proto__ = superClass;
}
Используя объект-экземпляр, сгенерируйте другой объект-экземпляр!
В приведенном выше кодеObject.create
метод сA
Объект является прототипом, который генерируетB
объект.B
наследоватьA
Все свойства и методы .
Фактически,Object.create
можно заменить следующим кодом.
Object.create = function (obj) {
function F() {}
F.prototype = obj;
return new F();
};
Приведенный выше код показывает, чтоObject.create
Суть метода заключается в создании пустого конструктораF
, тогда пустьF.prototype
свойство указывает на объект параметраobj
, который, наконец, возвращаетF
, чтобы экземпляр наследовалobj
характеристики.
или
Object.create = function (obj) {
var B={};
Object.setPrototypeOf(B,obj);
return B;
};
более интуитивный
Object.create = function (obj) {
var B={};
B.__proto__=obj;
return B;
};
Если вы хотите сгенерировать свойство, которое не наследует никакие свойства (например, отсутствиеtoString
а такжеvalueOf
метод), вы можете использоватьObject.create
Параметры установлены наnull
.
var obj = Object.create(null);
object.create
Новый объект, сгенерированный методом, динамически наследует прототип. Любой метод, добавленный или измененный в прототипе, немедленно отражается в новом объекте.
var obj1 = { p: 1 };
var obj2 = Object.create(obj1);
obj1.p = 2;
obj2.p // 2
В приведенном выше коде измените прототип объектаobj1
Влияет на объекты экземпляраobj2
.
Второй параметр Object.create
Помимо прототипа объекта,Object.create
Метод также может принимать второй параметр. Этот параметр является объектом описания свойства, и описываемое им свойство объекта будет добавлено к экземпляру объекта как свойство самого объекта.
var obj = Object.create({}, {
p1: {
value: 123,
enumerable: true,
configurable: true,
writable: true,
},
p2: {
value: 'abc',
enumerable: true,
configurable: true,
writable: true,
}
});
// 等同于
var obj = Object.create({});
obj.p1 = 123;
obj.p2 = 'abc';
После понимания Object.create вы сможете легко понять код наследования ES6 в ES5!