2014-10-10 3 views
1

как работает прототип? почему к «объекту» не удается получить доступ к «xc»?javascript прототип объекта

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

var x={a:"xa",b:"xb",c:"xc"}; 
var e={a:"ea",b:"eb"}; 
console.log(Object.prototype); // this is {} why? i am expecting it to be null 
console.log(e.prototype); 
e.prototype=x; 
console.log(e.prototype); 
console.log(x.c); 
console.log(e.c);//this is undefined , why? i am expecting it to be "xc" 
console.log(e.a); 
console.log(e.b); 
console.log(e.prototype.a); 
console.log(e.prototype.b); 

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

var css={ 

    'classSelectorExpressionIDOnly1':{ 
     css_Ruls_name1:xxxx, 
     css_Rulss_name2:xxxx 

    } 

    'classSelectorExpressionIDOnlyX':{ 
     css_Ruls_name1:xxxx, 
     css_Rulss_name9:xxxx 

    } 

    'classSelectorExpressionIDOnly2':{ '()inherit':["classSelectorExpressionIDOnly1","classSelectorExpressionIDOnlyX"] 
     css_Ruls_name3:xxxx, 
     css_Rulss_name5:xxxx 

    } 


} 


var mergeResult = Object.create(css.classSelectorExpressionIDOnly2); 
for(var entry in mergeResult){ 
    mergeResult[entry]= mergeResult[entry]; 
} 
mergeResult.__proto__=css.classSelectorExpressionIDOnly1; 
for(var entry in mergeResult){ 
    mergeResult[entry]= mergeResult[entry]; 
} 
mergeResult.__proto__=css.classSelectorExpressionIDOnlyX; 
for(var entry in mergeResult){ 
    mergeResult[entry]= mergeResult[entry]; 
} 

------ зависимость переписана --------

.classSelectorExpressionIDOnly1,.classSelectorExpressionIDOnly2{ 
     css_Ruls_name1:xxxx, 
     css_Rulss_name2:xxxx 
} 
.classSelectorExpressionIDOnlyX,.classSelectorExpressionIDOnly2{ 
     css_Ruls_name1:xxxx, 
     css_Rulss_name9:xxxx 
} 
.classSelectorExpressionIDOnly2{ 
     css_Ruls_name3:xxxx, 
     css_Rulss_name5:xxxx 
} 
+4

Вы вводите в заблуждение нормальное свойство '.prototype' с внутренней ссылкой [[prototype]] наследования. – Bergi

+0

Возможно, следующий ответ поможет вам понять прототип: http://stackoverflow.com/questions/16063394/prototypical-inheritance-writing-up/16063711#16063711 – HMR

ответ

1

Это не то, что для собственности .prototype. Несмотря на название, свойство функций .prototype на самом деле не является прототипом объектов, с которыми вы привыкли работать. Это одна из самых трудных вещей, чтобы разобраться в JavaScript, так что это не только вы.

Ключ к пониманию прототипа системы в JavaScript является то, что оператор new создает два объектов, а не один. Я буду говорить об этом в терминах четырех переменных:

[[myPrototype]]
Прототип объекта. Каждый объект теоретически имеет один (хотя для некоторых объектов он может быть неопределенным).
[[Конструктор]]
Функция, которая вызывается с новым оператором
[[newObject]]
Объект, который в конечном итоге будут возвращены
[[newPrototype]]
Объект, который станет [[newObject]]. [[MyPrototype]]

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

При использовании оператора new JavaScript выполняет следующие шаги.

  1. Создать объект [[newPrototype]].
  2. Set [[newPrototype]]. [[MyPrototype]] to [[Constructor]].prototype
  3. Создать объект [[newObject]].
  4. Set [[newObject]]. [[MyPrototype]] в [[newPrototype]]
  5. Set [[newObject]]. [[MyPrototype]]. Конструктор [[Конструктор]]
  6. вызов [[ Constructor]], с [[newObject]] как «это».

Обратите внимание, что [[newObject]]. [[MyPrototype]] не идеально подходит для прототипа [[newObject]] или [[Constructor]]. Вот почему нам нужен третий объект между ними: он несет информацию, которую вы хотите наследовать (через [[newPrototype]]. [[MyPrototype]]), но также содержит информацию, специфичную для объекта, который вы создаете (в [ newObject]]. конструктор).

И поэтому мы добираемся до функции .prototype. Это не функция [[myPrototype]], и это не [[myPrototype]] для создаваемых вами объектов с new. На самом деле это два уровня в цепочке прототипов, а не один.

Я надеюсь, что это объяснение поможет вам понять, что такое функция .prototype. Это не простой материал, и не каждое объяснение щелкает со всеми. Это часть того, почему у нас так много объяснений.

При первом создании объекта вы можете установить его прототип напрямую с помощью Object.create(). Эта функция работает с IE9 и выше (плюс все другие современные браузеры), и ее можно полилизовать, если вам нужно работать со старыми браузерами. Чтобы увидеть этот прототип позже, вы используете Object.getPrototypeOf(), который также имеет приличную поддержку браузера (хотя IE поддерживает его только в версии 9 и выше). Используя только эти две функции, вы можете создавать свои объекты, как это:

var x = {a:"xa",b:"xb",c:"xc"}; 
var e = Object.create(x); 
x.a = "ea"; 
x.b = "eb"; 
console.log(Object.getPrototypeOf(Object)); 
console.log(Object.getPrototypeOf(e)); 
console.log(x.c); 
console.log(e.c);//this is undefined , why? i am expecting it to be "xc" 
console.log(e.a); 
console.log(e.b); 
console.log(Object.getPrototypeOf(e).a); 
console.log(Object.getPrototypeOf(e).b);  

После того, как объект был создан, не стандартный способ сбросить его прототип еще. ECMAScript 6 определяет одно (функция Object.setPrototypeOf()), но пока только Chrome и Firefox поддерживают его: IE и Safari этого не делают. Тем не менее, если это нормально, вы могли бы сделать что-то вроде этого:

var x = {a:"xa",b:"xb",c:"xc"}; 
var e = {a:"ea",b:"eb"}; 
console.log(Object.getPrototypeOf(object)); 
console.log(Object.getPrototypeOf(e)); 
Object.setPrototypeOf(e, x); 
console.log(Object.getPrototypeOf(e)); 
console.log(x.c); 
console.log(e.c); 
console.log(e.a); 
console.log(e.b); 
console.log(Object.getPrototypeOf(e).a); 
console.log(Object.getPrototypeOf(e).b); 

Там является нестандартным способом сбросить прототип существующего объекта, и он даже пользуется хорошей поддержкой браузера в настоящее время. Для этого вы устанавливаете свойство .__proto__ на любой стандартный объект. Вы можете использовать его как это:

var x = {a:"xa",b:"xb",c:"xc"}; 
var e = {a:"ea",b:"eb"}; 
console.log(object.__proto__); 
console.log(e.__proto__); 
e.__proto__ = x; 
console.log(e.__proto__); 
console.log(x.c); 
console.log(e.c); 
console.log(e.a); 
console.log(e.b); 
console.log(e.__proto__.a); 
console.log(e.__proto__.b); 

Теперь, на ваш последний вопрос: почему Object.prototype равно {}, а не неопределенными? Поскольку функция конструктора Object имеет свойство .prototype, которое становится прототипом по умолчанию всех объектов, созданных через него. Спецификации называют этот объект [[ObjectPrototype]], и в нем живут вещи вроде функции .hasOwnProperty().

+0

Большое спасибо. – Johnny

1

Посмотрите здесь: https://stackoverflow.com/a/9959753/2768053

После прочтения этого, вы превратите код в этом:

var x={a:"xa",b:"xb",c:"xc"}; 
var e={a:"ea",b:"eb"}; 
console.log(Object.prototype.__proto__); 
console.log(e.__proto__); 
e.__proto__=x; 
console.log(e.__proto__); 
console.log(x.c); 
console.log(e.c); 
console.log(e.a); 
console.log(e.b); 
console.log(e.__proto__.a); 
console.log(e.__proto__.b); 

и вы получите результаты, которые вы ожидаете :)

+2

Это технически работает, но было бы более идиоматично говорить: 'var e = Object.create (x); e.a = 'ea'; e.b = 'eb'; '. '__proto__' еще не является частью стандарта, и доступ к нему напрямую является своего рода хаком. –

+0

Большое спасибо. – Johnny

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