Чаму Прататыпам клас атрымаў у спадчыну дзіця асобнік іншага класа дзіцяці?

Можа быць, я раблю гэта няправільна. Я хачу, каб стварыць базавы клас і два класы, якія ўспадкуюць ад гэтага класа. Тым не менш, гэта кажа мне, што адзін дзіця з'яўляецца InstanceOf іншага дзіцяці ... гэта не можа быць правільным, ці не так? Што я раблю няправільна тут?

function BaseClass(){}
function Child1(){}

Child1.prototype = BaseClass.prototype;
Child1.prototype.constructor = Child1;

function Child2(){}
Child2.prototype = BaseClass.prototype;
Child2.prototype.constructor = Child2;

console.log((new Child1() instanceof Child2));//true
0
Вось добры рэсурс на многіх спосабаў выкарыстання атрымання ў спадчыну ў JS: 3site.eu/doc
дададзена аўтар Cᴏʀʏ, крыніца

4 адказы

Вы ўсталявалі прататып абодвух вашых класаў сапраўды гэтак жа аб'екта ( «BaseClass.prototype»), і ўсталюйце ўласцівасць «канструктар» на ім у «Child2». Іншымі словамі «Child1.prototype» і «Child2.prototype» адны і тыя ж, так што ёсць толькі адно ўласцівасць «Канструктар» удзельнічае ў вашым кодзе, і ён заканчвае тым, што «Child2».

Можа быць, вы хочаце ўсталяваць гэтыя прататыпы </асобнікі EM> у BaseClass?

Child1.prototype = new BaseClass();
Child1.prototype.constructor = Child1;

Child2.prototype = new BaseClass();//a different object
Child2.prototype.constructor = Child2;

(@Raynos ўказвае на тое, што инстанцирование значэння прататыпа як гэта можа прывесці да тонкім праблемах, так што вы можаце аддаць перавагу выкарыстоўваць падыход у сваім адказе.)

3
дададзена
Вы сапраўды павінны пазбягаць .prototype = новы X() вы не хочаце ініцыялізаваць .prototype як асобнік X, вы проста жадаеце стварыць асобнік. (То бок не выклікаць канструктар!)
дададзена аўтар Raynos, крыніца
@ShyGuy вы не ініцыялізаваць іх там і тады, вы робіце гэта ў канструктару дзіцяці.
дададзена аўтар Raynos, крыніца
@Pointy :( шмат межаў аб'ектаў рэкамендуюць «INIT», таму што яны брудныя хакі вы проста не канструктарамі пры атрыманні ў спадчыну (рада: Object.create гэта тое, што вы хочаце) ..
дададзена аўтар Raynos, крыніца
@Pointy Так, у мяне ёсць гэтая дрэнная звычка думаць «ES5» кожны раз, калі хтосьці кажа, што JavaScript. Я проста не магу яго выключыць!
дададзена аўтар Raynos, крыніца
Што адбываецца, калі ваш канструктар базавага класа мае аргументы - вы павінны ініцыялізаваць іх прама там і тады? Мой рэальны дзіця код класа ёсць выклік BaseClass.call (гэта, «argument1», «Argument2»); у сваім канструктару.
дададзена аўтар Paul, крыніца
OK @Raynos Так, гэта, верагодна, справядліва; Я не рабіць такога роду рэчы досыць часта мелі справу з такімі пытаннямі :-) Я дадам няма.
дададзена аўтар Pointy, крыніца
@ShyGuy Я думаю, менавіта таму шматлікія структуры аб'ектаў выкарыстоўваюць ўмоўнасць, якія маюць «INIT» функцыю для выкліку.
дададзена аўтар Pointy, крыніца
@Raynos вы, вядома, ведаеце пра гэта больш, чым я :-) Я не напісаў «аб'ект-к» кода ў JavaScript на працягу доўгага часу, хоць я пішу шмат JavaScript. (Акрамя таго, не Object.create ES5 рэч? Верагодна, ёсць polyfill ў MDN.)
дададзена аўтар Pointy, крыніца

<�Код> Child1.prototype = BaseClass.prototype;

Should be Child1.prototype = Object.create(BaseClass.prototype)

You don't want the prototype object to be the same, you want a new prototype object that inherits from BaseClass

Жывы прыклад

Disclaimer: Object.create is ES5, use the ES5-shim for legacy platform support.

Каб даць вам больш пільны прыклад:

// Create base prototype
var Base = {
  method: function() {
    return this.things;
  },
  constructor: function (things) {
    this.things = things;
  }
};
// Link constructor and prototype
Base.constructor.prototype = Base;

// Create child prototype that inherits from Base
var Child = Object.create(Base);
// overwrite constructor
Child.constructor = function (things) {
  things++;
  Base.constructor.call(things);
}
// Link constructor and prototype
Child.constructor.prototype = Child;

// Swap prototype and constructor around to support new
ChildFactory = Child.constructor;

var c = new ChildFactory(41);
console.log(c.method());//42

<�Моцны> Візуальна:

<�Код> вар Base = {...}

тут мы проста ствараем аб'ект з метадамі і ўласцівасцямі. Мы хочам, каб мець магчымасць стварыць асобнік гэтага аб'екта. Такім чынам, Base з'яўляецца «клас» і ўсё гэта метады і ўласцівасці могуць быць даступныя з асобнікаў (уключаючы Канструктар ).

<�Код> Base.constructor.prototype = Базавы;

Вы павінны звязаць «канструктара функцыю», якая з'яўляецца функцыяй вы можаце патэлефанаваць з новы , які дасць вам новы асобнік аб'екта ConstructorFunction.prototype разам з аб'ектам прататыпа , Гэта ў асноўным трохі клею вам трэба зрабіць уручную, таму што ES ня робіць гэта для вас.

Калі вы забыліся зрабіць гэта, то функцыя канструктара (што X.constructor ) не мае .prototype ўласцівасці, каб зрабіць асобнікі ўспадкуюць ад.

<�Код> вар Child = Object.create (Base);

Стварыць новы аб'ект, [[Prototype]] з'яўляецца Base . У асноўным гэта пачатак вашай ланцугу прататыпаў

Child -> ([[Prototype]] = Base) -> ([[Prototype]] = Object.prototype) -> null

<�Код> Child.x = ...

Цяпер мы дадамо ўласцівасць нашага даччынага аб'екта, якія з'яўляюцца метадамі асобнікі дзіцяці пярэймуць. У асноўным мы ствараем новы аб'ект-прататып, каб атрымаць у спадчыну. Усе асобнікі будуць падзяляць метады, а таксама падзяляць метады па ланцужку прататыпаў (у тым ліку Base ).

<�Код> ChildFactory = Child.constructor;

кнопку новы ключавое слова працуе толькі на функцыі канструктара, а не прататып аб'ектаў, таму мы павінны ў асноўным кажуць «пераключыць нашу аб'ектную зменную прататып функцыі канструктара зменнай»

Асабіста пры будаўніцтве да «класы» Я лічу, што аб'екты прататыпа сапраўды прыемна непасрэдна звяртацца і пры стварэнні асобнікаў я знаходжу канструктар функцыю прыемнай для апрацоўкі.

Now when we call var c = new Child(41);

Ён будзе выклікаць функцыю канструктара мы вызначылі, які будзе павялічвацца рэчы , а затым выклікаць базавы канструктар.

Звярніце ўвагу на дадзены момант прататып ланцуга з выглядае

c -> ([[Prototype]] = Child) 
  -> ([[Prototype]] = Base) 
  -> ([[Prototype]] = Object.prototype) 
  -> null
2
дададзена
Дзякуй! Гэта працуе як шарм ... Я павінен зрабіць яшчэ некаторы чытанне на гэта, каб убачыць, што адбываецца за кулісамі. Ёсць так шмат розных прыкладаў у сеткі аб тым, як зрабіць атрыманне ў спадчыну правільна, і ўсе яны, падобна, канструктары без параметраў, каб пазбегнуць жорсткіх біт :)
дададзена аўтар Paul, крыніца

Гэта не азначае, што праверка ці з'яўляецца аб'ект новы Child1() ствараецца канструктарам «Child1». <�Код> InstanceOf Аператар прымае толькі аб'ект прататып. - (новы child1 ()) [[Prototype]] і правярае яго наяўнасць у ланцугу прататыпаў, у галоўнай ролі экспертызы ад «ребенка1 .prototype ». Аператар InstanceOf актывуюцца праз унутраны [[HasInstance]] метад канструктара. Такім чынам, вы павінны змяніць свой код наступным чынам:

function BaseClass(){}
function Child1(){}

Child1.prototype = new BaseClass();
Child1.prototype.constructor = Child1;

function Child2(){}
Child2.prototype = new BaseClass();
Child2.prototype.constructor = Child2;
console.log((new Child1() instanceof Child2));//false

І гэта будзе правільна рэалізацыя ААП ў JavaScript

1
дададзена

Калі прысвоіць прататып, ці не азначае гэта, што вы перазапісаць яго цалкам? Так што Child1 і Child2 фактычна становяцца аб'ектамі BaseClass, а не даччыныя класы.

Глядзіце таксама http://www.zipcon.net/~swhite /docs/computers/languages/object_oriented_JS/inheritance.html . Належная OO ў JS займае даволі шмат намаганняў.

1
дададзена