2015-11-03 2 views
0

Свойство прототипа и наследование JavaScript не ясны.Свойство и наследование прототипа в JavaScript

У меня есть функция:

function User (name) { 
    this.name = name; 
} 

Вопросы:

1) Почему один из следующих является ложным, а другое верно?

User.prototype.hasOwnProperty('name'); // false 
User.hasOwnProperty('name'); // true 

2) Что такое де разница между следующие:

User.constructor; 
User.prototype.constructor; 

3) Что происходит с User.constructor и User.prototype.constructor если переопределить свойство прототипа, как это:

User.prototype = { 
    changeName: function(newName) { 
     this.name = newName; 
    } 
}; 

А что, если я изменить это так:

User.prototype = { 
    constructor: User, 
    changeName: function(newName) { 
     this.name = newName; 
    } 
}; 

4) Является ли Пользователь функцией или прототипом или что? Следующий сайт ссылается на него как на прототип: «Следующий пример создает прототип ...» https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/constructor

Благодарим вас за ответы.

+0

Возможный дубликат [Как работает JavaScript .prototype?] (Http://stackoverflow.com/questions/572897/how-does-javascript-prototype-work) – Mathletics

ответ

0

Сначала вы должны понять, что прототип есть.

В Javascript, почти все это объект.


Edit (спасибо @Mathletics):

Примитивные BOOLEANS, числа и строки не являются объектами


При создании объекта в Javascript, по умолчанию, его прототип будет Object.

Так что, если я делаю:

var obj = {}; 
console.log(obj.__proto__) 

Это дает:

Object {}


Пауза:

Чтобы понять разницу между obj.prototype и obj.__proto__, пожалуйста, обратитесь к этому thread.


Следующий шаг заключается в понимании концепции prototype chaining.

Вот как наследование структурировано в Javascript. В принципе, прототип является «родителем» другого объекта, из которого он выводит методы и свойства.

Представьте схему, в которой Rabbit наследует от Mammal, который наследует от Animal.Представляя это в Javascript цепи прототипов будет, как:

(Rabbit) -> (Mammal) -> (Animal) -> (Object) -> null 

С кодом:

function Animal(){} 
function Mammal(){} 
function Rabbit(){} 

Mammal.prototype = new Animal(); 
Rabit.prototype = new Mammal(); 

Если вы в состоянии понять эти концепции, вы можете найти ответы на свои вопросы самостоятельно, но я попробуйте уточнить:

1) почему одно из следующих является ложным, а другое верно?

User.prototype.hasOwnProperty('name'); // false 
User.hasOwnProperty('name'); // true 

Вы должны прочитать hasOwnProperty method reference:

Каждый объект происходит от объекта наследует метод hasOwnProperty. Этот метод может быть использован для определения того, имеет ли объект указанное свойство как прямое свойство этого объекта [...]

Это способ гарантировать, что свойство, которое вы ищете, определено внутри объекта а не глубже в цепи прототипов.

Противоположный пример будет:

console.log(User.hasOwnProperty('constructor')); 

Поскольку свойство constructor определяется глубже в прототипе Chaing, это не является «собственностью» из User объекта.

В вашем случае name является свойством, определенным в вашем User объекте, но не определяемом в контексте глобального Object.

2), что де разница между следующим:

User.constructor; 
User.prototype.constructor; 

Кулаком нравится принимает конструктор User, второй принимает конструктор своего прототипа (в данном случае глобальной Object).

3), что происходит с User.constructor и User.prototype.constructor если переопределить свойство прототипа как этого:

User.prototype = { 
    changeName: function(newName) { 
     this.name = newName; 
    } 
}; 

Пожалуйста, прочитайте эту thread.

TL; DR: когда вы непосредственно передаете прототип, вы нарушаете цепочку прототипов, создавая новую.В Rabbit Например, если вы в какой-то момент сделал:

Rabbit.prototype = { 
    // ... 
}; 

Ваш новый прототип цепи будет:

(Rabbit) -> (Object) -> null 

Так, в первом примере, User.prototype.constructor даст:

функция Объект {}

В вашем втором ex достаточно, это даст:

Функция пользователя (имя)

Понял?

4) Пользователь является функцией или прототипом или что?

Пользователь объект прототипом которого является Function объекта, прототипом которого является Object объектом.

Рисунок это:

(User) -> (Function) -> (Object) -> null 

Надежда Я ясно.

+1

Если вы собираетесь зайти в сорняки, важно отметить, что _primitive_ booleans, numbers и string - это объекты __not__. Для каждого из них есть обертки объектов, но по умолчанию они не являются объектами. – Mathletics

+0

Это правда, @Mathletics. Я отредактировал ответ. –

+0

Это то, что я пропустил: «В принципе, прототип ...». Но есть что-то, что я до сих пор не понимаю: console.log (Пользователь.опытный образец); // Пользователь {} // но это должен быть объект {} и console.log (User.prototype.constructor); // User (name), но это должно быть что-то вроде Object() , потому что «родительская» вещь вы объяснили выше. Прекрасно работает и понятен с помощью вашего примера console.log (Mammal.prototype); // Animal {} дает ожидаемый результат. –

0

1) почему одно из следующих является ложным, а другое верно?

User.prototype.hasOwnProperty('name'); // false, A 
User.hasOwnProperty('name'); // true, B 
  • Объект-прототип не был дан имя собственности и не один по умолчанию (в качестве пользователя не является родным), так что это false для прототипа ,
  • КонструкторUser является Функция и вы определили имя функции как . Это устанавливается на объект функции, когда он интерпретируется.

Уверены ли вы, что вы не путаете это с помощью (new User('foo')).hasOwnProperty('name'); // true?

Этот последний случай, то экземпляр из пользователя имеет имя свойства которое "foo", как установлено конструктор пользователя.


2), что де разница между следующие:

User.constructor; 
User.prototype.constructor; 
  • User.constructor является Function потому Пользователь является функция.
  • User.prototype.constructor is undefined, но вы обычно ссылаетесь на него в User. Это то, что позже будет доступен в качестве (new User).constructor; // User

3), что происходит с User.constructor и User.prototype.constructor если переопределить прототип [...]

Ничего не происходит с User.constructor в любом случае.

Что касается User.prototype.constructor, не было определить ранее

  • так остается неопределенной в первом случае
  • установлен в User во втором случае

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


4) является функцией пользователя или прототип или что?

User является функцией и является конструктор. В JavaScript мы вызываем определенные функции конструкторы, если они будут использованы для построения (конструкция) экземпляров.


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

// A function `Foo` which will be our Constructor 
function Foo(baz) { 
    this.bar = baz; 
} 

// notice here we have `Foo.name; // "Foo"` 

// Setting up reference to the constructor through the prototype 
Foo.prototype.constructor = Foo; 
// Setting up reference to some other shared property through the prototype 
Foo.prototype.fizz = ['buzz']; 

И тогда использование

var foo = new Foo('hello world'); 
foo.bar; // "hello world" (own) 
foo.fizz; // ["buzz"] (inherited) 
foo.constructor; // Foo (inherited) 

var bar = new Foo(); 
foo.fizz === bar.fizz; // true, this is the same Object reference - it is shared 

Не бойтесь попробовать вещи в вашей консоли!

+0

'User.prototype.constructor' является' User' , по крайней мере в Chrome 46. – Mathletics

0

«Все» в JS - это объект.

Таким образом, функция представляет собой особый тип объекта, и этот тип объекта имеет свойство name, поэтому User.hasOwnProperty("name") возвращает true. Это не имеет никакого отношения к свойству объекта User, которое может создать одна и та же функция. Попробуйте назвать это чем-то другим, и вы увидите, что это так.

Любой объект происходит от другого объекта, а именно прототипа. Прототип функции имеет свойство constructor и __proto__, но не name. Так Ùser.prototype.hasOwnProperty («имя») `должны возвращать ложные

Поскольку все свойства прототипа производными вы можете сделать это, даже если User.constructorUser.hasOwnProperty("constructor") возвратят ложное

0

Javascript, в отличие от других языков (Java, ЕСС.), Не является классовым, она не дает никакого способа определить класс(на самом деле, следующий Javascript, ES6-Harmony, вводит класс ключевое слово, но это просто синтаксический сахар поверх наследования прототипа и, на данный момент, не доступен ни в одном браузере) ...

Так, Javascript реализует (ака) OOP (Object Ориентированное программирование) через наследование прототипа. Если вы хотите создать пользовательский объект , вам нужно использовать функцию, которая его определяет. Пример:

var Person = (function() { 
 
    /** 
 
    * this is the Constructor (if you have in mind a class-based language) 
 
    **/ 
 
    function Person() {} 
 
    
 
    return Person; 
 
})(window);

Делая что мы определили Person в новый объект и мы можем иметь несколько экземпляров с помощью new оператора:

var me = new Person(); 
 
var you = new Person(); 
 
//...

Как сделать все языки, JavaScript объекты могут иметь методы и Свойства, методы и свойства могут быть как Instance и класса.

var Person = (function() { 
 
    function Person() {} 
 
     
 
    /** 
 
    * Static Method 
 
    **/ 
 
    Person.sayCiao = function() {}; 
 
     
 
    /** 
 
    * Static Property 
 
    **/ 
 
    Person.ciao = 'Ciao'; 
 
    
 
    
 

 
    /** 
 
    * Instance Method 
 
    **/ 
 
    Person.prototype.sayHello = function() {}; 
 

 
    /** 
 
    * Instance Property 
 
    **/ 
 
    Person.prototype.hello = 'Hello'; 
 
    
 
    
 
    return Person; 
 
})(window);

Как вы можете видеть (попробуйте в консоли), используя прототип свойства мы можем определить методы или свойства, что все объекты, созданные с помощью вызова new Person наследовать.

1) почему одно из следующих является ложным, а другое верно?

Конечно, статические методы или свойства не принадлежат экземпляру, а hasOwnProperty возвращает true только тогда, когда вызывается с помощью функции-конструктора. Viceversa, методы или свойства экземпляров принадлежат только их экземплярам, ​​а hasOwnProperty возвращает true только тогда, когда вызывается с помощью оператора . Это нормальное поведение, которое вы можете встретить на других языках программирования.

Примечание: in ES6 the Function Object has a property name и это причина, по которой ваш тест возвращает true, но не ссылается на свойство name, которое вы определяете в конструкторе Person (read more).

  1. Пример использования:

var Person = (function() { 
 
    function Person(name) { 
 
    this.firstname = name 
 
    } 
 
    
 
    Person.prototype.firstname = ''; 
 
    
 
    Person.factory = function(name) { 
 
    return new Person(name); 
 
    }; 
 
    
 
    return Person; 
 
})(window); 
 

 
var hitmands = Person.factory('Giuseppe'); 
 
console.log('you are', hitmands); 
 

 
var you = Person.factory('BatMan'); 
 
console.log('hitmands is', you); 
 

 
console.info('Person has a name?', Person.hasOwnProperty('firstname')); 
 
console.info('You have a name?', you.hasOwnProperty('firstname'));

Свойство prototype относится к цепи прототипов, это является причиной того, как ваш вернуть ложь ... ({}).hasOwnProperty('prototype'). .. You can read more following this link. Просто prototype и то, что он содержит, не является собственностью Недвижимость вашего объекта.

2), что де разница между следующее (ЕСС.)

Как кто-то сказал, один относится к функции, а другой к свойству прототипа.

3), что происходит с User.constructor и User.prototype.constructor если переопределить свойство прототипа, как этот (Еккл.)

Вы можете использовать этот способ расширить поведение от одного класса к другому ... Read more about this.

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