2015-04-30 9 views
0

Если у меня есть следующий код, почему он возвращает сообщение об ошибке «Невозможно установить свойство« second_prop »неопределенного. Я думал, что вы можете расширить свойство прототипа и добавить к прототипу объекта больше переменных и методов. Поскольку два консольных оператора возвращают «Object» и «true», то почему он возвращает ошибку undefined. Мое мышление заключается в том, что если obj является объектом типа Object, то я должен иметь возможность делать temp.prototype.newproperty? Итак, объект будет иметь «newproperty». Но я, очевидно, ошибаюсь, поэтому здесь кое-что отсутствует. Более того, зачем мне нужно Object.create(), когда obj уже является литералом объекта? Разве это уже не объект? Я просто смотрю на некоторые примеры и пытается понять этуРасширение прототипа на литеральном объекте

var obj = { 
     first_property: 'first property' 
    } 
    console.log(typeof obj); 
    console.log(obj instanceof Object); 

    var temp = Object.create(obj); 
    temp.prototype.second_prop = 'second property' 

Выходной

//object 
//true 
//Uncaught TypeError: Cannot set property 'second_prop' of undefined 

Итак, почему не могу я делать temp.prototype или obj.prototype?

+0

только функции конструктора действительно есть '.prototype' собственности. Что вы на самом деле пытаетесь сделать? – Bergi

+0

Я ответил на аналогичный вопрос ранее сегодня, надеюсь, что это полезно: http://stackoverflow.com/a/29977006/4556448 – radiaph

ответ

2

Если у меня есть следующий код, почему он возвращает ошибку, говоря Невозможно установить свойство «second_prop» неопределенной

A Javascript буквального объект уже создан экземпляр объекта и не имеет .prototype имущество. Это свойство находится в функции-конструкторе, а не уже созданном объекте. В любом текущем браузере (IE9 +) вы можете использовать Object.getPrototypeOf() для получения прототипа для уже построенного объекта.

Но это похоже на то, что вы скорее всего клонируете объект, а затем добавите свойства клона. Или, если вы хотите, чтобы оба объекта обладали одним и тем же дополнительным свойством, добавьте свойство, а затем клонируйте его. Или, если вы просто хотите использовать свой литеральный объект, просто используйте его как есть.

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

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

Я думал, что вы можете расширить свойства прототипа и добавить больше переменные и методы объекта прототипа.

Вы можете, но свойство .prototype находится на конструкторе, а не на уже построенном объекте.

Поскольку два оператора консоли возвращают 'Object' и true, то почему возвращает ошибку неопределенного. Мое мышление заключается в том, что если «obj» - это объект типа Object, то я должен уметь делать temp.prototype.newproperty?

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

Еще больше, зачем мне нужно Object.create(), когда obj уже объект литерал? Разве это уже не объект?

Целью Object.create() является создание нового объекта с использованием существующего объекта в качестве прототипа. Если вы объявлены буква Javascript, и вы просто хотите использовать литерал как объект сам по себе, то нет причин использовать Object.create(). Просто используйте литерал как уже построенный объект, которым он является.

+0

Скажем, «обычные» браузеры в наши дни :-) «Новые» браузеры будут реализовывать 'Reflect.setPrototypeOf' (ES6), только старые браузеры не поддерживают ES5. – Bergi

+0

@Bergi - Я сделал ссылку более конкретным (IE9 +). Даже браузеры ES6 будут поддерживать 'Object.getPrototypeOf()', правильно? – jfriend00

+0

Да, ES6 совместим с обратной связью, поэтому они будут реализовывать ES5 'Object.getPrototypeOf' точно. – Bergi

0

temp не имеет прототипа. Объект имеет прототип. Вы можете изменить прототип для всех объектов, вызвав Object.prototype, но вы не можете изменить его только для одного объекта.

+0

У этого есть прототип ('obj'), но не свойство' .prototype'. – Bergi

+0

, но не наследует temp от Object? И у объекта есть прототип. – user1142130

+0

'temp' наследует от' obj', который наследует от 'Object.prototype', который наследует от' null' – Bergi

0

.prototype - это свойство, которое не всегда связано с фактическим прототипом объекта. Реальный прототип может быть accesed через .__proto__

var obj = { 
    first_property: 'first property' 
} 
console.log(typeof obj); 
console.log(obj instanceof Object); 

var temp = Object.create(obj); 

temp.__proto__.second_prop = 'second property'; 

console.log(Object.getPrototypeOf(temp)); 

//{ first_property: 'first property', 
//second_prop: 'second property' } 
+0

Лучше использовать только 'Object.getPrototypeOf' и вообще не упоминать' __proto__'. – Bergi