2016-05-06 6 views
6

Я стараюсь, чтобы переопределить метод и сценарий:Javascript не вызывается метод прототипа

function wrapper(target) { 
    target.doABC = function() { 
     alert('in wrapper'); 
    }; 
    return target; 
} 

function Model() { 
    wrapper(this); 
} 

Model.prototype.doABC = function() { 
    alert('in Model'); 
}; 

var a = new Model(); 
a.doABC(); 

В результате «в обертке». Я не знаю почему?

+0

«Модель» - это «объект», а «объект» не может иметь 2 ключа одинакового имени! – Rayon

+0

@Rayon: 'shadow', а не' override', чтобы использовать лучшую терминологию. ОП не присваивает свойство «Модели» дважды, он назначает «Модель» и прототип. –

+0

@JeremyJStarcher, True .. Термин 'override' будет неверно истолковывать вещи. – Rayon

ответ

5

Любой объект JavaScript имеет собственный и унаследован объектов недвижимости. Собственные - это те, которые определены непосредственно на экземпляре, и унаследовано взяты с объекта prototype.
При использовании property accessor JavaScript выполняет поиск в объекте собственный список недвижимости. Если свойство не найдено, оно ищет в цепочке прототипов объекта.

В вашем примере метод wrapper() определяет у экземпляра объекта собственное свойство doABC, которое является функцией, которая оповещает 'in wrapper'. Даже если у объекта есть прототип с тем же свойством doAbc, который оповещает 'in Model', JavaScript в любом случае будет использовать собственное свойство.

function wrapper(target) { 
    // Define an own property "doABC" 
    target.doABC = function() { 
     alert('in wrapper'); 
    }; 
    return target; 
} 

function Model() { 
    wrapper(this); 
} 

// Define an inherited property "doABC" 
Model.prototype.doABC = function() { 
    alert('in Model'); 
}; 

var a = new Model(); 

//Use the own property "doABC". The inherited "doABC" is ignored. 
a.doABC(); 

В дополнении, собственное свойство может быть удален с использованием delete оператора. После удаления объект будет использовать унаследованное свойство.

// delete the own property "doABC" 
delete a['doABC']; 

// the inherited "doABC" will be used. Alerts "in Model" 
a.doABC(); 

Отметьте working demo.

+0

Спасибо за ваш ответ! – user3468795

+0

Я попытался отладить этот скрипт. Перед выполнением оператора target.doABC объект a уже имеет метод doABC(), который исходит от прототипа.После запуска target.doABC эта функция обновляется. – user3468795

+0

@ user3468795 Да, так происходит в конструкторе. Мой ответ на вопрос «Результат - в обертке». Я не знаю почему? ». –

1

Позвольте мне увидеть, если я могу объяснить:

У вас есть две отдельные версии doABC здесь.

target.doABC Your создает функцию, специфичную для что экземпляра вашего Model и каждый Model получить свой собственный doABC.

Поскольку Model имеет doABC, у механизма JavaScript нет необходимости искать «цепочку» для чего-то еще, поэтому он никогда не будет искать версию Model.prototype.doABC.

Вы можете увидеть это, добавив следующие строки:

Model.prototype.doXYZ = function() { 
    alert('in Model'); 
}; 

и вызов

a.doXYZ(); 

Поскольку a не имеет свой собственный doXYZ тогда и только тогда, он будет искать цепь и см. метод в прототипе.