2015-08-21 7 views
0

Я не совсем получаю создание объектов и методы добавления/расширения в JavaScript. Я знаю, что все является объектом и использованием функций в качестве конструкторов, но я не совсем получаю прототип и создаю/вызываю новые методы.Доступ к объектам и прототипу в Javascript

var c1 = { 
    name: "Neil", 
}; 

var c2 = function() { 
this.name = "Neil"; 
}; 

С и выше, я могу добавить новый материал:

c1.town = "a town"; 
c2.town = "a town"; 

c1.setTown = function(newTown) { this.town = newTown;}; 
c2.setTown = function(newTown) { this.town = newTown;}; 

Где я опрокинуться это с функцией подхода я могу это сделать:

c2.prototype.setTown2 = function(newTown) { this.town = newTown;}; 
c3 = new c2(); 
c3.setTown2("new3"); 

1: Что такое разница между setTown и setTown2 и почему для c3 я могу вызвать c3.town = "x" и c3.setTown2 ("x"), но не вызвать c3.setTown ("x"); ?

2: Кажется, у меня нет доступа к «прототипу» для c1 (подход литералов-конструкторов), почему это?

спасибо.

+0

В принципе, это потому, что 'c1' является объектом, а' c2' является конструктором. Я пишу более подробный ответ прямо сейчас. –

ответ

1

Это потому, что JavaScript буквальные конструкторы как c1 создать реальную Object, в то время как функции с this как c2 создавать конструктор, которые могут быть использованы для создания объектов, как вы делали с c3. Ниже приведен анализ вашего кода с помощью комментариев JavaScript:

//This is a literal object with property name equal to "Neil": 
var c1 = { 
    name: "Neil", 
}; 
//We do not need to access the prototype here because c1 is an object, not a constructor: 
console.log(c1.name); 

//This is a constructor that creates an object with property name of "Neil". 
var c2 = function() { 
    this.name = "Neil"; 
}; 

//This creates a property town of "a town" on c1. This works because c1 is a regular object. 
c1.town = "a town"; 
//This creates a property town of "a town" on c2. However, if you create an object with c2, the object will not inherit town because it is not on the prototype. 
//This does not throw an error because even though c2 is a function, you can still set the property town on it because this property is what's called a _static property_. Static properties are properties that are set without the prototype like the property below: 
c2.town = "a town"; 
//With c1, we do not need to access prototype because it's a regular object and with c2, we do not need to access prototype because it's a static property. 
console.log(c1.town, c2.town); 

//This works the same as above, except now, we're using functions instead of regular properties. 
c1.setTown = function(newTown) { this.town = newTown;}; 
c2.setTown = function(newTown) { this.town = newTown;}; 
//This sets the town property of c1 like with a regular object: 
c1.setTown("HI!"); 
//This sets the static property town of c2 because "this" in the static method c2.setTown is c2, so "this.town" is "c2.town", or the static property town which we set above: 
c2.setTown("HI!"); 
//Both of the following outputs "HI!" because of the .setTown() calls above. 
console.log(c1.town, c2.town); 

//This method is set on the prototype of c2, meaning that objects made with c2 will inherit this method. 
c2.prototype.setTown2 = function(newTown) { this.town = newTown;}; 

//This is an object made with the constructor c2. It inherits name because of the actual constructor function and it inherits setTown2 from the prototype. However, it does NOT inherit c2.town and c2.setTown because those are static properties not on the prototype. 
c3 = new c2(); 
//This sets the town property of c3 because c3 inherited the setTown2 method from c2.prototype, so that method now sets the properties of c3. 
c3.setTown2("new3"); 
//c3.name outputs "Neil" because of the c2 constructor function and c3.town outputs "new3" because of the above c3.setTown2() call: 
console.log(c3.name, c3.town); 
+2

«хотя c2 не является объектом» - конечно, 'c2' является объектом; все функции. – melpomene

+0

Спасибо, это полезно, и я вижу, что очень запутано, исходя из Java. Я следил за ссылкой из другого ответа (Luigi), но там он говорит, что буквальный (c1) тоже имеет «прототип», но я не могу использовать его для добавления новых методов? –

+0

@melpomene Да, 'c2' - это объект, но это объект' Function', который еще более запутан для новичков. –

1

Вы знакомы с наследством? Общей концепцией в программировании является способ имитации наследования в javascript.

В основном, когда вы добавляете новые методы или переменные в прототип, вы изменяете основную структуру объекта ... Итак, когда вы решили создать новый объект из класса «modify» (в JS нет классов Я знаю), единственный способ, которым он остается, - это те, что находятся внутри прототипа.

Подробнее: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain

1

1: В чем разница между setTown и setTown2

Они обе функции, однако вы создаете новую функцию каждый раз, когда вы хотите добавить, что, как метод, в котором с prototype вы автоматически унаследовать:

var c3 = new c2(); 
var c4 = new c2(); 

c3.setTown = function(newTown) { this.town = newTown;}; 
c4.setTown = function(newTown) { this.town = newTown;}; 

console.log(c3.setTown === c4.setTown) // false 
console.log(c3.setTown2 === c4.setTown2) // true 

Al так, setTown является собственностью объектов c3 и c4, где setTown2 нет. Это унаследовано. Это означает:

console.log(c3.hasOwnProperty("setTown")); // true 
console.log(c3.hasOwnProperty("setTown2")); // false 

И поэтому Object.keys не вернется setTown2; но если вы выполните цикл for…in, вы получите как собственные свойства, так и унаследованные свойства.

и почему для с3 можно назвать c3.town = «х»

Потому что вы просто добавить свойство.Если объект не является frozen, или sealed, вы можете добавить любые объекты недвижимости в любое время. Вы также можете добавить c3.foo = "bar", даже если он не находится в прототипе или не добавлен в конструктор.

и c3.setTown2 ("x"), но не вызывать c3.setTown ("x");

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

2: Кажется, у меня нет доступа к «прототипу» для c1 (подход литералов-конструкторов), почему это?

Потому что prototype - это свойство только для функций, которые вы можете использовать в качестве конструкторов. c1 уже является объектом, поэтому не нужно, чтобы другой объект был «прототипом». Вы можете использовать непосредственно c1 в качестве прототипа объекта для создания другого объекта на его основе:

var cc1 = Object.create(c1); 

Это наследует все методы и свойства c1 имеет, так:

console.log(cc1.name) // "Neil" 
console.log(cc1.hasOwnProperty("name")) // false 

Как мы видим, в первой точке ,

Надеюсь, это поможет.

+0

спасибо, это тоже помогло :) Я думаю, мне нужно больше узнать о прототипе. –

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