2016-01-26 5 views
0

Прежде всего, извините за мой сломанный английский - я не носитель языка.Переопределение методов в JavaScript

Теперь перейдем к проблеме:

Я учусь JavaScript шаблонов проектирования и при попытке реализовать немного более сложный пример декоратор я понял, что я не могу изменить методы, определенные в конструкторе, но я могу изменить методы, определенные с помощью прототипа.

Может кто-нибудь объяснить мне, почему это так, или если я пропустил что-то действительно важное на этом пути.

Это код шаблона:

// Basic constructor with one parameter and test method 
var ExampleOne = function (param1) { 
    this.param1 = param1; 
    this.test = function() { 
    console.log('Test One'); 
    } 
} 
// Adding logParam1 method using prototype 
ExampleOne.prototype.logParam1 = function() { 
    console.log(this.param1); 
} 
// Adding testTwo method using prototype 
ExampleOne.prototype.testTwo = function() { 
    console.log('Prototype Test'); 
} 
// Creating instance of ExampleOne 
var example = new ExampleOne('Parameter One'); 
// Simple decoration 
example.decorate = function() { 
    console.log('Decoration One'); 
} 
// More complicated decoration 
var ExampleTwo = function(param1, param2) { 
    ExampleOne.call(this, param1); 
    this.param2 = param2; 
} 
// Creating separate prototype from original one 
ExampleTwo.prototype = Object.create(ExampleOne.prototype); 
// Trying to change test (defined in constructor) 
ExampleTwo.prototype.test = function() { 
    console.log('Test Two'); 
} 
// Trying to change logParam1 (defined using prototype) 
ExampleTwo.prototype.logParam1 = function() { 
    console.log(this.param1 + ' ' + this.param2); 
} 
// Creating instance 
var examplee = new ExampleTwo('Test Two', 'Decoration Two'); 

// Testing 
example.test(); // Expecting: Test One, Returns: Test One 
example.testTwo(); // Expecting: Prototype Test, Returns: Prototype Test 
example.logParam1(); // Expecting: Parameter One, Returns: Parameter One 
example.decorate(); // Expecting: Decoration One, Returns: Decoration One 

examplee.test(); // Expecting: Test Two, Return: Test One << WHY? 
examplee.testTwo(); // Expecting: Prototype Test, Returns: Prototype Test 
examplee.logParam1(); // Expecting: Test Two Decoration Two, Returns: Test Two Decoration Two 
// examplee.decorate(); // Expecting: error, Returns: error 

Thnx.

ответ

1

Свойства аксессуаров всегда будут обращаться к собственным свойствам объекта, прежде чем создавать цепочку прототипов. В вашем случае объекты имеют свойство test, которое выводит «Test 1», а их прототипы имеют свойство теста, которое выводит «Test 2», но эту функцию прототипа невозможно получить напрямую obj.test, так как тест 1 на первом месте в цепочке ,

Вы все еще можете получить доступ к «Тест 2»: Object.getPrototypeOf(example).test();.


Вы можете также все еще переопределять оригинальный тест, но это должно быть сделано в расчете на объекте основе, а не на прототипе:

example.test = function() { console.log('Test Two'); } 

Или, если вы сделаете подкласс вы можете переопределить его в конструкторе:

function ExampleFour (param) { 
    ExampleOne.call(this, param); 

    var superTest = this.test; 
    this.test = function() { 
      console.log('In overridden test, about to call Test 1'); 
      superTest.call(this); 
    }; 

} 

ExampleFour.prototype = Object.create(ExampleOne.prototype); 
+0

Ооо, я понимаю. Thnx для очень четких объяснений и примеров. Вместо 'ExampleTwo.prototype.test = function() { console.log ('Test Two'); }; ' я должен использовать ' уаг ExampleTwo = функция (param1, param2) { ExampleOne.call (это, param1); this.param2 = param2; this.test = function() { console.log ('Test Two'); } }; ' Я искал неправильную вещь. – ArminMeth

3

Функция ExampleTwo вызывает ExampleOne.call(this, param1); минуя ExampleTwo как контекст. Итак, ExampleOne метод this.test теперь указывает ваш ExampleTwo.

Таким образом, каждая переменная, вызывающая ExampleTwo с «новым», будет иметь собственную функцию свойства, называемую test(). Этот вызов будет вызван до функции test() прототипа ExampleTwo. Javascript сначала ищет собственные свойства, если он не находит, он следит за цепочкой прототипов (в этом случае объект ExampleTwo.prototype).