Почему необходимо установить конструктор прототипа? - PullRequest
276 голосов
/ 10 декабря 2011

В разделе о наследовании в статье MDN Введение в объектно-ориентированный Javascript я заметил, что они установили prototype.constructor:

// correct the constructor pointer because it points to Person
Student.prototype.constructor = Student;  

Служит ли это какой-либо важной цели? Можно ли это опустить?

Ответы [ 13 ]

0 голосов
/ 15 ноября 2016

Это не обязательно.Чемпионы ООП стараются превратить прототипическое наследование JavaScript в классическое наследование - это лишь одна из многих традиционных вещей.Единственное, что делает следующее

Student.prototype.constructor = Student; 

, - это то, что теперь у вас есть ссылка на текущий «конструктор».

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

Person.prototype.copy = function() {  
    // return new Person(this.name); // just as bad
    return new this.constructor(this.name);
};  

с кодом ниже (просто замените this.constructor на Person)

Person.prototype.copy = function() {  
    // return new Person(this.name); // just as bad
    return new Person(this.name);
}; 

Слава Богу, что с ES6 классические наследники могут использовать пуристыНативные операторы языка, такие как class, extends и super, и мы не должны видеть, как, например, исправления prototype.constructor и родительские ссылки.

0 голосов
/ 13 сентября 2016

С учетом простой функции конструктора:

function Person(){
    this.name = 'test';
}


console.log(Person.prototype.constructor) // function Person(){...}

Person.prototype = { //constructor in this case is Object
    sayName: function(){
        return this.name;
    }
}

var person = new Person();
console.log(person instanceof Person); //true
console.log(person.sayName()); //test
console.log(Person.prototype.constructor) // function Object(){...}

По умолчанию (из спецификации https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/constructor), все прототипы автоматически получают свойство с именем constructor, которое указывает на функцию, для которой оно является свойством. В зависимости от конструктора, к прототипу могут быть добавлены другие свойства и методы, что не является обычной практикой, но все же допускается для расширений.

Итак, просто отвечу: нам нужно убедиться, что значение в prototype.constructor установлено правильно, как предполагается в спецификации.

Должны ли мы всегда правильно устанавливать это значение? Это помогает в отладке и делает внутреннюю структуру согласованной со спецификацией. Мы должны определенно, когда наш API используется третьими сторонами, но не совсем, когда код наконец выполняется во время выполнения.

0 голосов
/ 10 декабря 2011

РЕДАКТИРОВАТЬ, я был на самом деле не так. Комментирование строки не меняет ее поведение вообще. (Я проверял это)


Да, это необходимо. Когда вы делаете

Student.prototype = new Person();  

Student.prototype.constructor становится Person. Следовательно, вызов Student() вернет объект, созданный Person. Если вы тогда делаете

Student.prototype.constructor = Student; 

Student.prototype.constructor сбрасывается обратно на Student. Теперь, когда вы вызываете Student(), он выполняет Student, который вызывает родительский конструктор Parent(), он возвращает правильно унаследованный объект. Если вы не сбросили Student.prototype.constructor перед вызовом, вы получите объект, у которого не было бы ни одного из свойств, установленных в Student().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...