Методы JavaScript переопределить
допустим, у вас есть код ниже:
function A() {
function modify(){
x = 300;
y = 400;
}
var c = new C();
}
function B() {
function modify(){
x = 3000;
y = 4000;
}
var c = new C();
}
C = function () {
var x = 10;
var y = 20;
function modify() {
x = 30;
y = 40;
};
modify();
alert("The sum is: " + (x+y));
}
теперь вопрос, если есть какой-либо способ, в котором я могу переопределить метод modify из C с методами, которые находятся в A и B. В Java вы бы использовали ключевое слово super, но как вы можете достичь чего-то подобного в JavaScript?
7 ответов:
Edit: прошло уже шесть лет с тех пор, как был написан оригинальный ответ, и многое изменилось!
- если вы используете более новую версию JavaScript, возможно, скомпилированную с помощью такого инструмента, как Бабель вы можете использовать реальные классы.
- если вы используете конструкторы компонентов типа класса, предоставляемые Угловое или реагировать, вы хотите посмотреть в документах для этой структуры.
- если вы используете ES5 и делая "поддельные" классы вручную, используя прототипы, ответ ниже по-прежнему так же прав, как и когда-либо.
удачи!
наследование JavaScript выглядит немного иначе, чем Java. Вот как выглядит собственная объектная система JavaScript:
// Create a class function Vehicle(color){ this.color = color; } // Add an instance method Vehicle.prototype.go = function(){ return "Underway in " + this.color; } // Add a second class function Car(color){ this.color = color; } // And declare it is a subclass of the first Car.prototype = new Vehicle(); // Override the instance method Car.prototype.go = function(){ return Vehicle.prototype.go.call(this) + " car" } // Create some instances and see the overridden behavior. var v = new Vehicle("blue"); v.go() // "Underway in blue" var c = new Car("red"); c.go() // "Underway in red car"к сожалению, это немного некрасиво и не включает в себя очень хороший способ "супер": вы должны вручную указать, какой метод родительского класса, который вы хотите вызвать. В результате, существуют различные инструменты, чтобы сделать создание классов приятнее. Попробуйте посмотреть на прототип.js, позвоночник.js или аналогичная библиотека, которая включает в себя более приятный синтаксис для выполнения ООП в js.
Так как это топ-хит на Google, я хотел бы дать обновленный ответ.
используя ES6 классы делает наследование и переопределение метода намного проще:
'use strict'; class A { speak() { console.log("I'm A"); } } class B extends A { speak() { super.speak(); console.log("I'm B"); } } var a = new A(); a.speak(); // Output: // I'm A var b = new B(); b.speak(); // Output: // I'm A // I'm BThe
superключевое слово относится к родительскому классу при использовании в наследующем классе. Кроме того, все методы родительского класса привязаны к экземпляру дочернего, поэтому вам не нужно писатьsuper.method.apply(this);.что касается совместимости: совместимость с ES6 таблица показывает только самые последние версии основных классов поддержки игроков (в основном). Браузеры V8 имеют их с января этого года (Chrome и Opera), а Firefox, используя движок SpiderMonkey JS, увидит классы в следующем месяце с их официальным выпуском Firefox 45. На мобильной стороне Android по-прежнему не поддерживает эту функцию, в то время как iOS 9, выпущенная пять месяцев назад, имеет частичную поддержку.
к счастью, есть Бабель, библиотека JS для повторная компиляция кода гармонии в код ES5. Классы и множество других интересных функций в ES6 могут сделать ваш код Javascript намного более читаемым и поддерживаемым.
один раз следует избегать эмуляции классического OO и вместо этого использовать прототипический OO. Хорошая библиотека утилит для прототипического OO-это черт.
вместо перезаписи методов и настройки цепочек наследования (всегда следует отдавать предпочтение объектной композиции над объектным наследованием) вы должны объединять повторно используемые функции в Признаки и создавать объекты с ними.
Видео
var modifyA = { modify: function() { this.x = 300; this.y = 400; } }; var modifyB = { modify: function() { this.x = 3000; this.y = 4000; } }; C = function(trait) { var o = Object.create(Object.prototype, Trait(trait)); o.modify(); console.log("sum : " + (o.x + o.y)); return o; } //C(modifyA); C(modifyB);
modify () в вашем примере-это частная функция, которая будет доступна только из вашего определения A, B или C. Вам нужно будет объявить его как
this.modify = function(){}C не имеет ссылки на своих родителей, если вы не передадите его в C. Если C настроен для наследования от A или B, он унаследует свои публичные методы (а не его частные функции, как вы определили modify ()). Как только C наследует методы от своего родителя, вы можете переопределить унаследованные методы.
метод
modify()то, что вы вызывали в последнем, вызывается в глобальном контексте если вы хотите переопределитьmodify()сначала вы должны наследоватьAилиB.может быть, вы пытаетесь сделать это:
в этом случае
CнаследуетAfunction A() { this.modify = function() { alert("in A"); } } function B() { this.modify = function() { alert("in B"); } } C = function() { this.modify = function() { alert("in C"); }; C.prototype.modify(); // you can call this method where you need to call modify of the parent class } C.prototype = new A();
нет, если вы не сделаете все переменные "публичными", т. е. не сделаете их членами
Functionлибо напрямую, либо черезprototypeсобственность.var C = function( ) { this.x = 10 , this.y = 20 ; this.modify = function( ) { this.x = 30 , this.y = 40 ; console.log("(!) C >> " + (this.x + this.y) ) ; } ; } ; var A = function( ) { this.modify = function( ) { this.x = 300 , this.y = 400 ; console.log("(!) A >> " + (this.x + this.y) ) ; } ; } ; A.prototype = new C ; var B = function( ) { this.modify = function( ) { this.x = 3000 , this.y = 4000 ; console.log("(!) B >> " + (this.x + this.y) ) ; } ; } ; new C( ).modify( ) ; new A( ).modify( ) ; new B( ).modify( ) ;
- .
затем,
x,yиmodifyвсе" публичные " члены, так что назначение другойFunctionв них<name>.prototype.modify = function( ) { /* ... */ }будет "перекрывать" оригинал
FunctionС таким именем.наконец, вызов
modifyне может быть сделано вFunctionобъявление, потому что неявный вызов "суперкласса" будет выполнен опять же, когда мы устанавливаем предполагаемый "супер-класс" вprototypeсвойство предполагаемых "подклассов".но хорошо, это более или менее, как вы будете делать такие вещи в JavaScript.
HTH,
FK
function A() { var c = new C(); c.modify = function(){ c.x = 123; c.y = 333; } c.sum(); } function B() { var c = new C(); c.modify = function(){ c.x = 999; c.y = 333; } c.sum(); } C = function () { this.x = 10; this.y = 20; this.modify = function() { this.x = 30; this.y = 40; }; this.sum = function(){ this.modify(); console.log("The sum is: " + (this.x+this.y)); } } A(); B();
Comments