Подтвердить что ты не робот

Javascript: Прототип функции перезаписи - плохая практика?

Поскольку, когда мы объявляем функцию, мы получаем, что ее свойство конструктора прототипа указывает на саму функцию, неудобно ли переписывать прототип функции так:

function LolCat() {
}

// at this point LolCat.prototype.constructor === LolCat

LolCat.prototype = {
    hello: function () {
        alert('meow!');
    }
    // other method declarations go here as well
};

// But now LolCat.prototype.constructor no longer points to LolCat function itself

var cat = new LolCat();

cat.hello(); // alerts 'meow!', as expected

cat instanceof LolCat // returns true, as expected

Это не то, как я это делаю, я по-прежнему предпочитаю следующий подход

LolCat.prototype.hello = function () { ... }

но я часто вижу, как другие люди делают это.

Так есть ли какие-либо последствия или недостатки, удалив ссылку на конструктор из прототипа, перезаписав объект-прототип функции для удобства, как в первом примере?

4b9b3361

Ответ 1

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

Следует отметить, что свойство constructor, если вы его не уничтожите, также будет доступно на созданном объекте. Мне кажется, что это может быть полезно:

var ClassOne = function() {alert("created one");}
var ClassTwo = function() {alert("created two");}

ClassOne.prototype.aProperty = "hello world"; // preserve constructor
ClassTwo.prototype = {aProperty: "hello world"}; // destroy constructor

var objectOne = new ClassOne(); // alerts "created one"
var objectTwo = new ClassTwo(); // alerts "created two"

objectOne.constructor(); // alerts "created one" again
objectTwo.constructor(); // creates and returns an empty object instance

Так мне кажется, что это архитектурное решение. Вы хотите разрешить созданному объекту повторно вызвать его конструктор после его создания? Если это так, сохраните его. Если нет, уничтожьте его.

Обратите внимание, что конструктор objectTwo теперь точно равен стандартной функции конструктора объектов - бесполезно.

objectTwo.constructor === Object; // true

Таким образом, вызов new objectTwo.constructor() эквивалентен new Object().

Ответ 2

Это неплохая практика, но вы должны знать, что вы делаете и почему. Это очень полезно для прототипного наследования. Объект, из которого вы перезаписываете прототип, получит все свойства объекта, который вы назначили ему прототипом:

Вы вызываете объект для наследования с помощью

ChildClassName.prototype = new ParentClass();.

Теперь у ChildClassName есть все функции ParentClass, но теряет все функции, которые ранее были назначены прототипу. Вам нужно запомнить reset свойство конструктора для объекта с помощью

ChildClassName.prototype.constructor=ChildClassName. 

В противном случае объект будет сообщаться (при тестировании типа объекта) типа ParentClass вместо типа ChildClassName.

И теперь вы можете добавить другие методы к объекту ChildClassName так, как вы сами описали.

ChildClassName.prototype.myMethod = function(){
    //do stuff
}

Результат - родительский объект/'класс' (в Java нет реальных классов) и дочерний объект/'класс', который наследует его и расширяет его функциональность.

Вам просто нужно знать, что если вы перепишете прототип, любые свойства, которые там были назначены, исчезнут. При построении наследующих объектов это может быть именно то, что вы хотите.

Ответ 3

Эта форма:

LolCat.prototype = {
  hello: function () {
      alert('meow!');
  }
};

Уничтожает любые существующие методы и общедоступные свойства. В примере, как указано, это не имеет значения, поскольку недавно созданный LolCat не имеет никаких свойств или методов. Однако следует помнить об этом в более сложном коде.

Эта форма:

LolCat.prototype.hello = function () { ... }

Добавляет новый метод к существующему объекту и сохраняет существующее без изменений.

Ответ 4

Неплохая практика перезаписывать constructor при использовании прототипального наследования. Infact многие люди делают это так:

LolCat.prototype = {
    constructor: LolCat,
    hello: function () {
        alert('meow!');
    }
};

Ответ 5

Это не плохая практика. Но есть простой и стандартный способ переопределения функции, как показано ниже. Когда когда-либо мы определяем "функцию LolCat()" глобально, она создается под окном, поэтому вы всегда можете использовать код, как показано ниже.

window.LolCat = function() {...};
LolCat.prototype.hello = function () { ... }