Почему свойство прототипа JavaScript undefined для новых объектов?
Я новичок в концепции концепции прототипа JavaScript.
Учитывая следующий код:
var x = function func(){
}
x.prototype.log = function() {
console.log("1");
}
var b = new x();
Как я понимаю, b.log() должен возвращать 1, так как x является его прототипом. Но почему свойство b.prototype undefined?
Не предполагается ли b.prototype вернуть ссылку на функцию x?
Ответы
Ответ 1
Только конструкторские функции имеют прототипы. Поскольку x
является конструкторской функцией, x
имеет прототип.
b
не является конструкторской функцией. Следовательно, у него нет прототипа.
Если вы хотите получить ссылку на функцию, которая построила b
(в данном случае x
), вы можете использовать
b.constructor
Ответ 2
Свойство .prototype
функции находится именно там, чтобы настроить наследование нового объекта, когда функция вызывается как конструктор.
Когда новый объект создается, он получает свое внутреннее свойство [[Prototype]]
, заданное объекту, на которое указывает свойство .prototype
.
Сам объект не получает свойство .prototype
. Его отношение к объекту полностью внутренне.
Вот почему это работает b.log()
. Когда движок JS видит, что сам объект b
не имеет свойства log
, он пытается найти его на объекте internal [[Prototype]]
, где он успешно находит его.
Чтобы быть ясным, свойство [[Prototype]]
не доступно напрямую. Это внутреннее свойство, которое только косвенно изменено с помощью других конструкций, предоставляемых механизмом JS.
Ответ 3
Прежде чем переходить к вашему коду, я хочу убедиться, что некоторые концепции прототипа необходимы для понимания поведения вашего кода.
-
[[prototype]]
является скрытым свойством объекта JavaScript. Это скрытое свойство - это не что иное, как ссылка на Object.prototype
(если создается объектными литералами). Нет стандартного способа доступа к этому свойству [[prototype]]
.
- Функции в JavaScript - это объекты, поэтому они также имеют свойство
[[prototype]]
. Здесь, в случае функции это скрытое свойство является ссылкой на Function.prototype
. Также нет стандартного способа доступа к этому свойству [[prototype]]
.
- Помимо этой скрытой ссылки
[[prototype]]
, всякий раз, когда создается объект функции, в нем создается свойство prototype
, которое отделено от скрытого свойства [[prototype]]
.
Теперь переходим к вашему коду:
var x = function func() {}
Когда эта строка выполняется, создается объект-функция x
с двумя ссылками:
- Функция.прототип (недоступен),
- x.prototype(доступно).
x.prototype.log = function() { console.log( "1" ); }
как мы теперь знаем, x
- это объект функции, поэтому x.prototype
доступен, поэтому здесь вы можете включить с ним метод журнала.
var b = new x();
b
- объект, но не объект функции. У него есть скрытая ссылка [[prototype]]
, но она недоступна. поэтому, когда вы пытаетесь получить доступ, как b.prototype
, он дает undefined
в качестве результата. Если вы хотите проверить прототип b
, чем вы видите (x.prototype).isPrototypeOf(b);
, он вернет true
. поэтому вы можете сказать, что скрытая ссылка ссылается на x.prototype
.
Вот некоторые факты о прототипе:
- Если объект
O
создан с помощью O = new func(){}
, чем O [[prototype]] равен Function.prototype
.
- Если объект
O
создается с помощью O = {}
, чем O [[prototype]], это Object.prototype
.
- Если объект
O
создан с помощью O = Object.create(obj)
, чем O [[prototype]], это obj
.
Ответ 4
Каждый объект в JavaScript имеет прототип (примечание: прототип здесь не относится к свойству прототипа). Стандарт ECMAScript (http://www.ecma-international.org/ecma-262/6.0/index.html) указывает, что это свойство называется [[Prototype]]. Вы можете получить доступ к этому свойству двумя способами: нестандартным свойством __proto__ и свойством прототипа.
__ proto__ не может быть надежно доступен в браузерах. __proto__ становится официальной собственностью в ECMAScript 6
Вы также можете получить доступ к свойству прототипа определенных типов, например, к основным типам JavaScript (Date, Array и т.д.). Также функция JavaScript (которая может рассматриваться как конструктор) имеет свойство общедоступного прототипа. Однако экземпляры функции не имеют свойства прототипа.
В вашем случае b.prototype - undefined, но если вы выходите в Firefox, например версии 43.0.4
console.log(b.__proto__);
Вы увидите его свойство [[Prototype]], как показано ниже:
func { log=function()}
Ответ 5
Потому что prototype
является свойством функций (фактически, конструкторов), поскольку он определяет свойства/методы объектов этого класса (те, которые были созданы из конструктора, к которому принадлежит этот прототип). Взгляните на эту ссылку