Я изучил ES6, когда учился реагировать в эти дни.class extendsМетод наследования, давайте рассмотрим механизм наследования ES5 и разберемся с ним.
- Механизм наследования ES5
- Механизм наследования ES6
- Краткое изложение разницы между ними
Механизм наследования ES5
В js все является объектом, но мы по-прежнему различаем обычные объекты и объекты-функции, поэтому всем нужно знать, что только объекты-функции имеютprototypeсвойства, но все объекты имеют свойство __proto__
function A(){
}
var B = new A;
Вот несколько формул:
B.__proto__== A.prototype;
B.constructor == A;
a.prototype.constuctor = A;
Это основа для реализации наследования; Другими словами, A.prototype — это объект-прототип A, A — конструктор, B — экземпляр A, а объект-прототип (A.prototype) — экземпляр конструктора (A). На данный момент это указывает на экземпляр. Очень просто понять, что эта связь реализует наследование! Взгляните на код ниже
Наследование цепочки прототипов
Путем переопределения прототипа подкласса, равного экземпляру суперкласса (экземпляр суперкласса становится свойством прототипа подкласса)
function father() {
this.faName = 'father';
}
father.prototype.getfaName = function() {
console.log(this.faName);
};
function child() {
this.chName = 'child';
}
child.prototype = new father();
child.prototype.constructor = child;
child.prototype.getchName = function() {
console.log(this.chName);
};
Комбинированное наследование (чаще используется, но также имеет недостатки)
Наследование достигается тем, что объект-прототип подкласса указывает на экземпляр родительского класса.Нетрудно обнаружить, что цепочка прототипов образована __proto_ вместо прототипа.Экземпляр подкласса может обращаться к методам на прототип родительского класса, потому что экземпляры подкласса проходят _protoЕсть подключение к объекту-прототипу родительского класса
//先来个父类,带些属性
function Super(){
this.flag = true;
}
//为了提高复用性,方法绑定在父类原型属性上
Super.prototype.getFlag = function(){
return this.flag;
}
//来个子类
function Sub(){
this.subFlag = false;
}
//实现继承
Sub.prototype = new Super;
//给子类添加子类特有的方法,注意顺序要在继承之后
Sub.prototype.getSubFlag = function(){
return this.subFlag;
}
//构造实例
var es5 = new Sub;
Наследование паразитарного состава (наиболее рекомендуемый метод в отрасли)
Так называемое паразитическое композиционное наследование означает наследование свойств с помощью конструкторов и наследование методов путем смешивания цепочки прототипов. Основная идея заключается в том, что вместо вызова конструктора супертипа для указания прототипа подтипа все, что нам нужно, — это копия прототипа супертипа. По сути, вы используете паразитное наследование для наследования прототипа супертипа, а затем присваиваете результат прототипу подтипа.
function inserit(son, father) {
var obj = Object.create(father.prototype);
son.prototype = obj;
obj.constructor = son
}
function SuperType(name,colors) {
this.name = name;
this.colors = colors;
}
SuperType.prototype.sayName = function () {
return this.name;
}
function SubType(job,name,color) {
SuperType.call(this, name,color);
this.job = job;
}
//核心方法
inserit(SubType, SuperType);
SubType.prototype.sayjob = function () {
return this.job;
}
var instance= new SubType("doctor","John",["red","green"]);
console.log(instance.sayjob(),instance.sayName()) //doctor,John
- [x] Недостатки наследования по цепочке прототипов: родительский класс содержит атрибут ссылочного типа, тогда все экземпляры подкласса будут совместно использовать атрибут (включая ссылочный типпрототипсвойства будут общими для экземпляра), при создании экземпляра подкласса нельзя передавать параметры в конструктор родительского класса
- [x] Недостатки комбинированного наследования: вызов конструктора родительского класса дважды: (первый раз — при создании прототипа подкласса, второй раз — внутри конструктора подкласса) Подкласс наследует свойства родительского класса, набор экземпляр подкласса, набор свойств с тем же именем в прототипе подкласса (создание ненужных избыточных свойств в прототипе подкласса) (замаскированный прототип в экземпляре) неэффективен
- [x] Преимущества комбинированного наследования: конструктор родительского класса вызывается только один раз, что позволяет избежать создания ненужных и избыточных свойств на прототипе подкласса, а цепочка прототипов остается неизменной
Краткое изложение механизма наследования ES5
Механизм наследования ES5 прост: суть в том, чтобы сначала создать экземпляр объекта this подкласса, а затем добавить к этому метод родительского класса (Parent.apply(this))
Механизм наследования ES6
class Point {
constructor(x) {
this.x = 1;
this.p = 2;
}
print() {
return this.x;
}
}
Point.prototype.z = '4'
class ColorPoint extends Point {
constructor(x) {
this.color = color; // ReferenceError
super(x, y);
this.x = x; // 正确
}
m() {
super.print();
}
}
Наследование ES6 осуществляется черезclass,extendsКлючевое слово для достижения наследования Point — это родительский класс, а ColorPoint — подкласс.Реализуйте наследование, создав новый подкласс класса extends для наследования родительского класса, что намного проще, чем ES5.
constructor
Метод конструктора является конструктором класса и является методом по умолчанию, который автоматически вызывается при создании экземпляра объекта с помощью новой команды. Класс должен иметь метод конструктора, если он не определен явно, метод конструктора по умолчанию будет добавлен по умолчанию. Поэтому, даже если вы не добавите конструктор, будет конструктор по умолчанию. Как правило, метод конструктора возвращает объект экземпляра this , но вы также можете указать, что метод конструктора возвращает совершенно новый объект, чтобы возвращаемый объект экземпляра не был экземпляром класса.
class Points {
constructor(x) {
this.x = 1;
this.p = 2;
}
print() {
return this.x;
}
statc getname(){
return new.target.name;
}
}
等同于:
function Points(x) {
this.x = x;
this.p = 2;
}
Points.prototype.print = function() {
return '(' + this.x +')';
}
Другими словами, конструктор представляет собой добавление атрибутов к родительскому классу, а добавление атрибутов метода к объекту класса эквивалентно добавлению атрибутов к прототипу. И эти методы атрибутов можно получить только через новые экземпляры или экземпляры, унаследованные от расширений, поэтому мы можем получить
new Points().__proto__.print() //可以调用到Points的print方法
new Points().x = 1 //可以调用到constructor 里面的 this.x=1
super
superЕго можно использовать либо как функцию, либо как объект — два варианта использования совершенно разные.время функции: метод super должен вызываться в конструкторе, потому что подкласс не имеет своего объекта this, а наследует объект this родительского класса, а затем обрабатывает его, а super представляет собой конструктор родительского класса. Хотя super представляет конструктор родительского класса A, он возвращает экземпляр подкласса B, то есть this внутри super ссылается на B, поэтому super() здесь эквивалентно
A.prototype.constructor.call(this, props)
Когда super() выполняется, он ссылается на конструктор подкласса B, а не на конструктор родительского класса A. То есть this внутри super() указывает на B. Итак, в первом примере es6 this подкласса указывает на себя. ,
использовать как объект: в обычных методах указывает на объект-прототип родительского класса, в статических методах указывает на родительский класс. Итак, в методе подкласса super.print() указывает на метод прототипа родительского класса.Однако из-за двух вариантов использования super ES6 предусматривает, что использование должно быть явно использовано, например, только console.log(super), будет сообщено об ошибке.
static
Как следует из названия, это означает статический метод, а класс эквивалентен прототипу экземпляра, все методы, определенные в классе, будут унаследованы экземпляром. Если ключевое слово static добавлено перед методом, это означает, что метод не будет унаследован экземпляром, а будет вызываться непосредственно через класс, который называется «статическим методом». Вызовы статических методов выполняются непосредственно в классе и не могут вызываться в экземплярах класса. Статические методы часто используются для создания служебных/служебных функций.
new.target
Свойство new.target позволяет определить, была ли функция или конструктор вызваны с помощью оператора new. В функции или конструкторе, инициализированном оператором new, new.target возвращает ссылку на конструктор или функцию. При обычном вызове функции значение new.target не определено.
Другими словами, функция new.target заключается в том, чтобы определить, создает ли вызов функции новый объект посредством операции new, а new.target возвращает ссылку на функцию, что означает, что мы можем определить, какая функция вызывает новую операцию.
Краткое изложение механизма наследования ES6
Сначала создайте экземпляр родительского класса this. Определите подкласс с помощью ключевых слов class, extends и super и измените указатель на this. Super сам по себе является конструктором, который указывает на родительский класс, но после вызова функции он возвращает экземпляр подкласса, который на самом деле является родительским классом.Класс .prototype.constructor.call(this) указывает на родительский класс .prototype при вызове объекта, чтобы добиться наследования.