Объект пуст, когда свойство к прототипу функции добавляется через Object.setPrototypeOf () - PullRequest
3 голосов
/ 23 января 2020

Давайте рассмотрим следующий код,

let f = function () {
   this.a = 1;
   this.b = 2;
}

let o = new f(); 
f.prototype.c = 3;
console.log(Object.getPrototypeOf(o)); 

Печать

[объект] {c: 3}

Но если я использую setPrototypeOf вместо f.prototype. c объект пуст.

let f = function () {
   this.a = 1;
   this.b = 2;
}

let o = new f();   
Object.setPrototypeOf(f, {c: 3}); 
console.log(Object.getPrototypeOf(o));

Отпечатки

[объект Объект] {...}

Но если я использую

let f = function () {
   this.a = 1;
   this.b = 2;
}

let o = new f(); 
Object.setPrototypeOf(f, {c: 3}); 
console.log(Object.getPrototypeOf(f)); 

Отпечатки

[объект Объект] {c: 3}

Короче вопрос при использовании Object.setPrototypeOf (o) объект печатается пустым, а при использовании Object.setPrototypeOf (f) объекты печатают добавленное свойство. где, как и при установке прототипа с использованием f.prototype. c = 3, он доступен как прототипом Objects, так и прототипом функций.

1 Ответ

2 голосов
/ 23 января 2020

Когда вы Object.setPrototypeOf(f, ... ), цепочка фактически 3 длинная:

Прототип o равен f. Прототип f равен {c:3}.

Таким образом, ваши примеры не эквивалентны друг другу:

1) В первом примере вы добавляете свойство c непосредственно к прототипу, который будут использовать экземпляры f, поэтому прототип o содержит c, поскольку f является конструктором для o.

В последних двух примерах Вы добавляете c к прототипу f, поэтому прототип f был создан с помощью. Помните, что функции также являются просто объектами и что вы устанавливаете прототип функции, которую вы используете в качестве конструктора. Таким образом, протокол o содержит протокол f, который содержит c.

2) Во втором примере вы получаетеPrototypeOf () o. В третьем вы получаете PrototypeOf () f. Следовательно, только 3-й пример снова показывает c.

3) Если вы осмотрите элемент в chrome, вы увидите, что конструктор 2-го примера равен f, так как вы спрашиваете у прото o.

В третьем примере вы увидите, что конструктор Object, так как вы спрашиваете у прото f, который был установлен для объекта {c} и пропустите прото с o до f.

PS: я знаю, что это может быть запутанным объяснением.

PPS: Если вы хотите наследования, придерживайтесь child.prototype = Object.create( parent.prototype ); child.constructor = child; или класс ES6 class child extends parent, когда его можно было использовать, лично меня смущало.

var first = function first() {
  this.value = 'first function';
};
// before .prototype.extra, first inherist from Function.
console.log( 'constructor of first before:', first.constructor );
first.prototype.extra = 'implemented with .prototype.extra';
// after .prototype.extra, first still inherits from Function, we did not change anything to first itself.
console.log( 'constructor of first after:', first.constructor );
// When first is used as a prototype, the instances will get "extra".
// Aka, everything that inherist from first.
var first_instance = new first();
console.log( 'extra on instance of first:', first_instance.extra );
// f itself does NOT have the extra property, only instances of first do.
console.log( 'extra on first itself:', first.extra );
console.log( '------' );
var second = function second() {
  this.value = 'second function';
};
// before setPrototypeOf, second inherist from Function, like above.
console.log( 'constructor of second before:', second.constructor );
Object.setPrototypeOf( second, { extra: 'implemented with .setPrototypeOf()' });
// after setPrototypeOf, second inherist from Object, we broke the default inheritance chain.
console.log( 'constructor of second after:', second.constructor );
// BY doing this, we effectively turned second into an object.
// It no longer is a function, so we cannot use function methods like .call() or .apply()
console.log( 'second is object, not function: function.apply', second.apply );
console.log( 'second is object, not function: object.hasOwnProperty', second.hasOwnProperty );
// When second is used as a prototype, the instances will not get "extra".
var second_instance = new second();
console.log( 'extra on instance of second:', second_instance.extra );
// second itself Does have the extra property, sine we assigned it on the prototype used by second. not when second is used as the prototype.
console.log( 'extra on second itself:', second.extra );
...