2016-06-23 2 views
1

Я новичок в Javascript и смущен информацией об итогах следующих утверждений. Не могли бы вы помочь пояснить причину каждого результата? Было бы полезно, если бы вы могли также предложить ресурсы, которые четко объясняют ожидаемое поведение в этих случаях.Объекты и прототипы Javascript

function Person(){ 
    this.a = function(){alert("a")}; 
} 

Person.prototype.b = function(){alert("b")}; 
Person.c=function(){alert("c")}; 

var test = new Person(); 
test.a(); // works 
test.b(); // works 
test.prototype.b(); //error 

Person.prototype.a(); // error (why?) 
Person.prototype.b(); //works (why?) 

Person.c(); //works 

Person(); 
Person.a(); /* error (Person() call should have set this.a 
       on the Person object just like the c method, 
       why doesn’t it work?) */ 

Person.b();//error (why?) 
+3

Только функции имеют объект 'prototype',' test' - это объект. '' 'не определен в' Person.prototype', но 'b'. – Teemu

+0

Возможный дубликат [Понимание прототипного наследования в JavaScript] (http://stackoverflow.com/questions/892595/understanding-prototypal-inheritance-in-javascript) –

+0

@JaredSmith, вы ошибаетесь, связанный с вами вопрос не имеет отношения со статическими свойствами и свойствами экземпляра. Пожалуйста, оставьте свой комментарий – frankies

ответ

0

Когда вы Person.c = ..., вы настраиваете статические свойства, таким образом, они не являются частью прототипа.

Позже вы пытаетесь вызвать методы прототипа для конструктора, и их не существует, поскольку прототип представляет собой схему для экземпляров этого конструктора.

+0

'this.a' не создает статическое свойство. –

+0

Позаботьтесь, чтобы объяснить, что это такое? – frankies

+0

Его добавление свойства для каждого созданного экземпляра. 'Person.a()' будет ошибкой. Я также не понимаю, как ваш ответ каким-либо образом улучшается по любому из вопросов в вопросе, который я обозначил как обман. –

0

class.prototype действует как ссылка между объектами и вашим классом. class.prototype вы можете назначить функции и свойства, которые будут разделены между всеми экземпляр вашего класса и, когда вызов функции будет искать в prototype объекте class

// так можно назвать прообразом здесь

Person.prototype.fun; 

// но здесь вы непосредственно называть Func

test.fun 

MDN

0

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

test.a(); // works -> Yes because it accessing the property that exists in Person it self 
test.b(); // works ->First It will look into test instance properties if it doesn't find it will look one level up into the Person prototype object and it will find it there. 

test.prototype.b(); //error because test is an instance and instances do not have a prototype property. 

Person.prototype.a(); // error (why?) Because you are going to look for a property a inside Person prototype which does not have it. Property lookup goes only forward not backward. 
Person.prototype.b(); //works (why?) because b is a property of the Person prototype. 
//typeof Person.prototype is object same as var prototype={} than prototype.b=function(){} so now you can call prototype.b(); 

Person.c(); //works c is 'static' (more like object literal property assignment because every function in js still is an object) property of Person same as var Person2={};Person2.c=function(){}; that is why you can access it without needing to initialize Person. 

Person(); 
Person.a(); /* error (Person() call should have set this.a 
          on the Person object just like the c method, 
          why doesn’t it work?) */ That property requires you to create an instance of Person. 

Person.b();//error (why?) it is the same as a but b is a property of prototype of Person 
+0

«* свойство, которое существует в функции Person *», является неправильной или, по крайней мере, очень запутанной терминологией для свойств экземпляров Person. – Bergi

+0

a является свойством объекта/функции Person. Да, каждый экземпляр Человека будет иметь это свойство. Чтобы сделать его менее запутанным, я удаляю функцию и заменяю ее экземпляром. Thnx – Dynamikus

+1

'c' является свойством объекта функции' Person'. 'a' является свойством экземпляра' test' – Bergi

1

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

function Person(){ 
    this.a = function(){alert("a")}; 
} 

Определяет функцию Person. Пока ничего особенного. Вызов Person() будет, в зависимости от того, работает ли он в строгом режиме, выдает ошибку «не может установить свойство» «неопределенного» или он будет создавать глобальную переменную «a», поскольку vaue является функцией, которая предупреждает «a», ,

Однако, по соглашению, капитализированные функции в Javascript должны быть конструкторами и вызываться с помощью оператора new. Вызов new Person() делает для вас волшебство. Он создает новый объект и устанавливает его в значение this в функции конструктора. Новый объект также неявно возвращается конструктором, поэтому он не имеет оператора возврата. Значение нового человека имеет метод a, который предупреждает «a» при вызове.

Но это редко делается на практике, использование прототипа является гораздо более распространенным явлением. Оператор new также устанавливает внутренний прототип вновь созданного объекта как значение свойства функции конструктора .prototype (объект фактически не получает свойство .prototype). Все, что определено в объекте конструктора .prototype, будет доступно для каждого экземпляра, созданного путем вызова этого конструктора с помощью new.

Person.prototype.b = function(){alert("b")}; 

Это определяет функцию Ь на личности (функция конструктора) 'ы .prototype объекта. Он будет доступен для всех созданных экземпляров Лица, сделанных по телефону new Person(). Его также можно вызвать непосредственно Person.prototype.b(). Этот метод лучше, чем тот, который используется для присоединения метода «а», потому что все люди разделяют значение «b», но все имеют свою собственную копию «a».

Person.c=function(){alert("c")}; 

В JavaScript все является объектом, в том числе функции. Объекты могут иметь назначенные им свойства. Здесь вы назначаете функцию для свойства c самой функции Person. Если вы привыкли к языкам на основе классов, это похоже на статический метод класса.

Надеюсь, к тому времени остальное станет яснее. Каждый человек, включая 'test', будет иметь метод 'a', потому что конструктор назначает его. Но прототип человека не имеет метода «а», его просто назначают в конструкторе. Прототип человека имеет метод «b», то есть все экземпляры Person имеют доступ к этому общему методу «b». Сама функция Person имеет метод «c», но она не передается экземплярам, ​​поэтому «test» не имеет метода «c».

1

Хорошо, я сделаю снимок. Я беру интервью в ближайшее время, а так это хорошая практика :)

function Person(){ 
    this.a = function(){alert("a")}; 
} 

Person.prototype.b = function(){alert("b")}; 
Person.c=function(){alert("c")}; 

var test = new Person(); 
test.a(); // works 
test.b(); // works 
test.prototype.b(); //error 

Похоже, у вас есть, но test является объектом, а не конструктор. На нем нет прототипа.

Person.prototype.a(); // error (why?) 
Person.prototype.b(); //works (why?) 

Вот где все потехи. Посмотрите на функцию Person(); все это действительно ссылается на переданные ему параметры и возвращает новый объект. Не кажется более сложным. Тем не менее, именно в этом заключается безумное прототипное наследование JavaScript.

Скажите, что вы написали метод прототипа более высокого уровня на String, например String.prototype.capitalize = function()..., а метод заглавной строки. Каждая новая строка, которую вы создали, будет иметь метод capitalize(), но это не похоже на то, что строка является объектом с этим ключом метода на нем.

Это то же самое, что и Person.prototype.a() и Person.prototype.b() делает. Запуск объекта с помощью функции Person() создает объект с этими ключами. Поскольку Person() конструктор только возвращает объект с ключом а, это то, что test выглядит так далеко:

console.log(test); // {a: [Function]} 

Но почему test.b() работу? Это связано с тем, что любой объект, созданный конструктором, наследует все свойства этих конструкторов .prototype. Добавление чего-то к прототипу не изменяет ключи, добавленные к сконструированному объекту, но вместо этого дает доступ к его сконструированным объектам. Вызов метода на что-то сначала смотрит на его ключи, тогда это скрытое значение конструктора [[prototype]], потом оно родительское и так далее. Вы можете увидеть это в console.log s в Chrome.

Person(); 
Person.a(); /* error (Person() call should have set this.a 
       on the Person object just like the c method, 
       why doesn’t it work?) */ 

Person.b();//error (why?) 

Ваша ошибка здесь в том, что Person() - это объект. Это не; это функция. Ссылка на конструктор ссылается на передаваемый ему объект; это означает переменную, на которую она установлена.Поскольку мы просто вызываем Person() и не устанавливаем результат на что-либо, не определено, и результат Person() не определен, так как вернуть нечего. Функция не может иметь ключи или методы.

Надеюсь, что смогу помочь. Это была хорошая практика для меня тоже!

+0

Возможно, это лучший ответ, отличный от того, который я написал, но каким образом он улучшается на моем? –

Смежные вопросы