JavaScript.prototype necə işləyir?

Mən dinamik proqramlaşdırma dillərini sevirəm, amma JavaScript kodumun payım yazdım. Mən bu praktik proqramlaşdırma haqqında düşünməmişəm, hər kəs bunun necə işlədiyini bilirmi?

 var obj = new Object(); obj.prototype.test = function() { alert('Hello?'); }; var obj2 = new obj(); obj2.test(); 

Bir müddət əvvəl insanlar ilə olduğum bir çox müzakirələrimi xatırlayıram (mən nə etdiyinə tam əmin deyiləm), amma başa düşdüyüm kimi, bir sinif konsepsiyası yox idi. Bu yalnız bir obyektdir və bu obyektlərin nümunələri orijinal, hüququ klondur?

Amma bunun hansı məqsədi var? Javascriptdə prototip mülkiyyəti? Bu, obyektlərin yaradılması ilə necə əlaqəlidir?

Yeniləmə: Doğru

 var obj = new Object(); // not a functional object obj.prototype.test = function() { alert('Hello?'); }; // this is wrong! function MyObject() {} // a first class functional object MyObject.prototype.test = function() { alert('OK'); } // OK 

Həm də bu slaydlar həqiqətən kömək etdi.

1912
21 февр. John Leidegren tərəfindən 21 Fevralda təyin olundu 2009-02-21 15:31 '09 at 15:31 'da 2009-02-21 15:31
@ 25 cavab

Hər JavaScript obyekti [[Prototype]] adlı bir daxili mülkiyyətə malikdir. obj.propName və ya obj['propName'] vasitəsilə obj.propName və obyekt obj.hasOwnProperty('propName') ilə yoxlanıla biləcək bir xüsusiyyətə malik deyilsə, - [[[ Prototip]] əvəzinə prototip obyekti belə bir mülkiyyətə malik deyilsə, onun prototipi növbə ilə yoxlanılır və beləliklə, bir oyun tapıldığı və ya sona çatana qədər orijinal obyekt prototipi zənciri boyunca gəzir.

Bəzi JavaScript tətbiqləri, [[Prototype]] əmlakına, məsələn, __proto__ adlı qeyri-standart əmlak vasitəsilə birbaşa çıxış əldə etməyə imkan verir. Ümumiyyətlə, bir obyektin yaradılması zamanı bir obyektin prototipini təyin etmək mümkündür: new Func() vasitəsilə new Func() bir obyekt Func.prototype , [[Prototype]] obyektinin mülkiyyəti Func.prototype tərəfindən istinad olunan obyektə təyin olunacaq.

Bu, JavaScript-nin JavaScript-dəki modelləşdirilməsinə imkan verir, baxmayaraq ki, JavaScript miras sistemi - bu prototipdir və sinif bazlı deyildir:

Konstruktiv funksiyalarını prototipin sinifləri və xüsusiyyətləri (yəni, prototype konstruktor əmlakı ilə istinad edilən obyekt) ümumi idarələr, yəni hər bir nümunə üçün eyni olan üzvlər kimi düşünün. Sinif bazlı sistemlərdə metodlar hər bir nümunə üçün eyni şəkildə tətbiq olunur, belə ki üsullar adətən prototipə əlavə olunur, obyekt sahələri nümunəyə aiddir və buna görə də tikinti zamanı obyektin özünə əlavə olunur.

953
21 февр. 21 fevralda Christoph tərəfindən verilmiş cavab . 2009-02-21 16:33 '09 at 16:33 'da 2009-02-21 16:33

Java, C # və ya C ++ kimi klassik miras həyata keçirən bir dildə, bir sinif yaratmaqla başlayırsınız - obyektləriniz üçün bir plan və sonra bu sinifdən yeni obyektlər yarada və ya yeni bir sinif mənbə sinfi.

JavaScript-də ilk növbədə bir obyekt yaratmaq (bir sinif konsepsiyası) deyil, sonra öz obyektinizi genişləndirə və ya yeni obyektlər yarada bilərsiniz. Klassik şəkildə istifadə edilən kimsə üçün çətin deyil, bir az yad və sindirmək çətindir.

Məsələn:

24 янв. Cavab verilir stivlo 24 jan. 2011-01-24 06:42 '11 'də 6:42' də 2011-01-24 06:42 'də

Mən javascript müəlliminin rolunu oynayıram və prototip konsepsiyası mənim öyrətdiyim zaman həmişə mübahisəli bir mövzu olmuşdur. Bu anlayışı aydınlaşdırmaq üçün yaxşı bir yola gəlmək üçün bir az vaxt apardım və indi bu mətndə JavaScript.prototype'in necə işlədiyini izah edəcəyəm.


Bu izahat əsnasında nümunə olaraq qəbul ediləcək, şərh almadan çox sadə prototip obyekt modelidir:

 function Person(name){ this.name = name; } Person.prototype.getName = function(){ console.log(this.name); } var person = new Person("George"); 

Prototip anlayışından keçmədən əvvəl nəzərə alınması lazım olan bir neçə vacib nöqtə var.

1- JavaScript funksiyaları necə işləyir?

İlk addımı atmaq üçün, JavaScript-in funksiyasını, this istifadə edən bir sinif funksiyası və ya onun arqumentləri ilə müntəzəm bir funksiya, nə etdiyini və nə qaytardığını anlamaq lazımdır.

Person obyekt modelini yaratmaq istəyirik. amma bu mərhələdə prototypenew söz açmadan istifadə etməyəcəyəm.

Beləliklə, bu addımda functions , objects və bunların hamısı var.

İlk sual , this new açar sözünü istifadə etmədən faydalı ola biləcəyi səbəbindən olacaqdır.

Yəni cavab vermək üçün boş bir obyekt və iki funksiyanı bildirsinlər:

 var person = {}; function Person(name){ this.name = name; } function getName(){ console.log(this.name); } 

və indi new söz istifadə etmədən , bu funksiyaları necə istifadə edə bilərik. Belə ki, javascript bunu etmək üçün 3 fərqli yola malikdir:

a Birincisi, funksiyanı sadəcə funksiya kimi çağırmaqdır:

 Person("George"); getName();//would print the "George" in the console 

bu halda, bu, ümumiyyətlə brauzerdə qlobal window obyekti və ya Node.js GLOBAL olan mövcud kontekst obyekti olacaq. Bu brauzerdə window.name və ya "George" dəyəri ilə Node.js-də GLOBAL.name olacaq deməkdir.

b. Biz onun obyektlərinə görə, obyektə əlavə edə bilərik

- Bunu etmək üçün ən asan yol boş bir Person obyektini dəyişdirməkdir, məsələn:

 person.Person = Person; person.getName = getName; 

beləliklə də bunları belə zəng edə bilərik:

 person.Person("George"); person.getName();// -->"George" 

İndi Person obyekti belə görünür:

 Object {Person: function, getName: function, name: "George"} 

- Bir obyektin bir obyektə birləşdirilməsinin başqa bir yolu __proto__ adı ilə hər hansı bir JavaScript obyektində tapıla bilən bu obyektin prototype istifadə etməkdir və bunu xülasə hissəsində bir az izah etməyə çalışdım. Beləliklə, biz çalışan kimi oxşar bir nəticə əldə edə bilərik:

 person.__proto__.Person = Person; person.__proto__.getName = getName; 

Amma əslində bir şəkildə Object.prototype dəyişdirmək, çünki biz Object.prototype ( { ... } ) istifadə edərək, bir JavaScript obyekti yaratdığımız zaman Object.prototype əsasında yaradılmışdır, yəni o bağlıdır yeni yaradılan obyektə __proto__ adı ilə bir atribut kimi təqdim __proto__ , buna görə də əvvəlki kod __proto__ olduğu kimi __proto__ , bütün JavaScript obyektləri dəyişdiriləcək, yaxşı bir təcrübə deyil. Beləliklə, indi yaxşı təcrübə nə ola bilər:

 person.__proto__ = { Person: Person, getName: getName }; 

və indi digər obyektlər susdurulublar, amma bu, əlbəttə ki, yaxşı bir təcrübə deyil. Beləliklə, biz başqa bir həll var, lakin bu həlli istifadə etmək üçün biz Person obyektinin yaradıldığı kod satırına qayıtmalıyıq ( var person = {};

 var propertiesObject = { Person: Person, getName: getName }; var person = Object.create(propertiesObject); 

yeni bir JavaScript Object yaradır və __proto__ özniteliklerine propertiesObject əlavə edir. Buna görə də, edə biləcəyinizə əmin olmaq üçün:

 console.log(person.__proto__===propertiesObject); //true 

Ancaq çətin nöqtə, siz Person obyektinin birinci səviyyədə __proto__ də müəyyən edilmiş bütün xüsusiyyətlərə (daha ətraflı məlumat üçün, xülasə bölməsinə bax) daxil __proto__ .


Gördüyünüz kimi, bu iki üsuldan birini istifadə edərək, Person obyektini müəyyən edəcəkdir.

c. Zəngdən istifadə edən və ya funksiyanı çağırmaq üçün müraciət edən this funksiyanı təmin etmək üçün başqa bir yol var.

Application () metodu bir array (və ya bir sıra kimi obyekt) kimi verilən verilən bir dəyər və arqumentlərlə bir funksiyanı çağırır.

Zəng () metodu funksiyanı müəyyən edilmiş dəyərlə və ayrı-ayrı verilən dəlilləri çağırır.

mənim sevimli olduğum bu şəkildə, biz asanlıqla funksiyaları zəng edə bilərik, məsələn:

 Person.call(person, "George"); 

və ya

 //apply is more useful when params count is not fixed Person.apply(person, ["George"]); getName.call(person); getName.apply(person); 

Bu 3 metod .prototip funksiyasını müəyyənləşdirmək üçün vacib ilk addımlardır.


2- new söz necə işləyir?

Bu, .prototype funksionallığını başa düşmək üçün ikinci addımdır. Prosesi simulyasiya etmək üçün mən istifadə edirəm:

 function Person(name){ this.name = name; } my_person_prototype = { getName: function(){ console.log(this.name); } }; 

Bu hissədə new açar sözünü istifadə edərkən newprototype açar sözlərindən istifadə etmədən, JavaScript-nin bütün addımlarını yerinə yetirəcəyəm. Buna görə new Person("George") icra etdikdə, Person funksiyası konstruktor kimi çıxış edir. Bu, JavaScript-ni bir-birinə bənzəyir:

a ilk növbədə, boş bir şey yaradır, əsasən boş bir şeydir:

 var newObject = {}; 

b. javascripti yerinə yetirən növbəti addım bütün prototip obyektlərini yeni yaradılmış obyektə əlavə etməkdir

Burada prototip obyektinə bənzər my_person_prototype var.

 for(var key in my_person_prototype){ newObject[key] = my_person_prototype[key]; } 

Bu, JavaScript-nin həqiqətən prototipdə müəyyən edilmiş xüsusiyyətləri birləşdirməsidir. Həqiqi yol prototip zəncirinin konsepsiyası ilə bağlıdır.


a və b. Bu iki addımın əvəzinə eyni nəticə əldə edə bilərsiniz:

 var newObject = Object.create(my_person_prototype); //here you can check out the __proto__ attribute console.log(newObject.__proto__ === my_person_prototype); //true //and also check if you have access to your desired properties console.log(typeof newObject.getName);//"function" 

İndi getName funksiyasını my_person_prototype :

 newObject.getName(); 

c. sonra bu obyekti qurucuya verir,

bunun nümunəsi ilə bunu edə bilərik, məsələn:

 Person.call(newObject, "George"); 

və ya

 Person.apply(newObject, ["George"]); 

onda konstruktor istədiyi şeyi edə bilər, çünki bu konstruktorun içərisində bu yeni yaradılmış bir obyektdir.

İndi digər addımları təqlid etmədən son nəticə: Object {name: "George"}


Xülasə:

Əsasən, bir funksiya üçün yeni bir söz istifadə etdikdə onu çağırırsınız və bu funksiya konstruktor kimi xidmət edir, buna görə deyirsiniz:

 new FunctionName() 

JavaScript daxili bir obyekt, boş bir karma yaradır və sonra bu obyekti qurucuya verir, sonra konstruktor istədiyi şeyi edə bilər, çünki bu bu qurucunun içərisində sadə bir obyektdir və sonra bu obyekti təbii ki, funksiyanıza qaytarma operatorunu istifadə etmədi və ya return undefined; bədənin funksiyası sonunda.

Belə ki, bir obyekt üzərində bir obyekt axtarmaq üçün davam edərkən, ilk etdiyiniz şey obyektə baxır. Və daha sonra __proto__ kimi adətən malik olan gizli mülk [[prototype]] var və bu əmlak belə görünür. Və __proto__ tarar, yenidən bir JavaScript obyekti olduğundan, öz __proto__ sahibdir, bu yüksəlir və növbəti __proto__ olduğu nöqtəyə çatır. __proto__ JavaScript-nin __proto__ xüsusiyyətinə malik olan __proto__ : null - bu bir Object.prototype obyektidir:

 console.log(Object.prototype.__proto__===null);//true 

və mirasın javascriptla necə işlədiyini öyrənir.

2019

168
13 февр. Cavab 13 fevralda Mehran Xatəmi tərəfindən verilir. 2014-02-13 22:32 '14 at 10:32 pm 2014-02-13 22:32

prototype siniflər yaratmağa imkan verir. prototype istifadə prototype , statik olur.

Burada qısa bir nümunə.

 var obj = new Object(); obj.test = function() { alert('Hello?'); }; 

Yuxarıdakı hallarda statik bir funksiya çağırışı testi var. Bu funksiyaya yalnız obj.test tərəfindən daxil edilə bilər, burada obj bir sinif kimi təqdim edə bilərsiniz.

Aşağıdakı kodda olduğu kimi

 function obj() { } obj.prototype.test = function() { alert('Hello?'); }; var obj2 = new obj(); obj2.test(); 

Nümunə indi yaradılacaq bir sinif halına gəldi. Bir neçə obyekt obj ola bilər və onların hamısı bir test funksiyası var.

Bu mənim anlayışımdır. Bunu wiki icmasında edirəm, buna görə mən səhv olduğum halda insanlar məni düzəldə bilərlər.

72
21 февр. Cavab Ramesh 21 fevralda verilir. 2009-02-21 15:37 '09 at 15:37 'da 2009-02-21 15:37

Yeddi Koana Prototipi

Dərin düşüncə qurtardıqdan sonra Chiro San Saniyə Fox dağından çıxdıqda, ağlı açıq və sakit idi.

Lakin əlləri narahat idi və əlini tutdu və aşağıdakı qeydləri yazdı.


0) İki müxtəlif şey "prototip" adlandırıla bilər:

  • obj.prototype kimi prototip xüsusiyyət

  • ES5-də [[Prototype]] kimi göstərilən prototipin daxili mülkiyyəti.

    Object.getPrototypeOf() vasitəsilə əldə edilə bilər.

    Firefox, onu __proto__ xüsusiyyətiylə bir uzantı olaraq təqdim edir. ES6 indi __proto__ üçün bəzi isteğe bağlı tələbləri qeyd edir .


1) Bu anlayışlar suala cavab vermək üçün mövcuddur:

Mən obj.property , JS axtaran .property ?

Səmərəli, klassik miras xüsusiyyətləri axtarışa təsir etməlidir.


2)

  • __proto__ nöqtəsi üçün istifadə olunur . obj.property kimi əmlak axtarış.
  • __proto__ new bir obyekt __proto__ təyin __proto__ kimi, dolayı yolla birbaşa axtarış etmək üçün istifadə edilmir.

Axtarış sırası:

  • obj xüsusiyyətləri obj.p =... və ya Object.defineProperty(obj,...) ilə əlavə olunmuşdur.
  • obyekt xassələri obj.__proto__
  • obyekt obj.__proto__.__proto__ və s.
  • bəzi __proto__ null olduqda, undefined .

Bu sözdə prototip zənciridir.

Qaça bilərsiniz . obj.hasOwnProperty('key')Object.getOwnPropertyNames(f)


3) obj.__proto__ qurmaq üçün iki əsas yol obj.__proto__ : obj.__proto__ :

  • new :

     var F = function() {} var f = new F() 

    sonra new dəsti:

     f.__proto__ === F.prototype 

    Burada .prototype istifadə olunur.

  • Object.create :

      f = Object.create(proto) 

    dəstləri:

     f.__proto__ === proto 

4) kodu:

 var F = function() {} var f = new F() 

Aşağıdakı diagrama uyğundur:

 (Function) ( F ) (f) | ^ | | ^ | | | | | | | | | | | +-------------------------+ | | |constructor | | | | | | | +--------------+ | | | | | | | | | | | | | | |[[Prototype]] |[[Prototype]] |prototype |constructor |[[Prototype]] | | | | | | | | | | | | | | | | +----------+ | | | | | | | | | | | | +-----------------------+ | | | | | | v | vv | v (Function.prototype) (F.prototype) | | | | |[[Prototype]] |[[Prototype]] | | | | | +-------------------------------+ | | vv (Object.prototype) | | ^ | | | | | +---------------------------+ | | | | +--------------+ | | | | | | | |[[Prototype]] |constructor |prototype | | | | | | | | -------------+ | | | vv | (null) (Object) 

Bu diaqram obyektlərin bir çox əvvəlcədən təyin edilmiş dil qovşaqlarını göstərir: null , Object , Object.prototype , FunctionFunction.prototype . Bizim 2 F.prototype kod yalnız f , FF.prototype .


5). .constructor adətən F.prototype vasitəsilə gəlir . hörmət:

 f.constructor === F !f.hasOwnProperty('constructor') Object.getPrototypeOf(f) === F.prototype F.prototype.hasOwnProperty('constructor') F.prototype.constructor === f.constructor 

f.constructor , javascript edir . necə axtarın:

  • f yoxdur
  • f.__proto__ === F.prototype var f.__proto__ === F.prototype .constructor === F , belə ki, götür

f.constructor == F nəticəsi intuitiv şəkildə düzəldilir, çünki f , məsələn, klassik OOP dillərində olduğu kimi verilən sahələr üçün f üçün istifadə olunur.


6) Klassik miras sintaksis prototip zəncirlərini manipulyasiya edərək əldə edilə bilər.

ES6 class əlavə edir və prototipi manipulyasiya etmək üçün əvvəlcə mümkün dəlillər üçün sintaktik şəkər olan açar sözləri extends .

 class C { constructor(i) { this.i = i } inc() { return this.i + 1 } } class D extends C { constructor(i) { super(i) } inc2() { return this.i + 2 } } 
 // Inheritance syntax works as expected. (new C(1)).inc() === 2 (new D(1)).inc() === 2 (new D(1)).inc2() === 3 
 // "Classes" are just function objects. C.constructor === Function C.__proto__ === Function.prototype D.constructor === Function // D is a function "indirectly" through the chain. D.__proto__ === C D.__proto__.__proto__ === Function.prototype 
 // "extends" sets up the prototype chain so that base class // lookups will work as expected var d = new D(1) d.__proto__ === D.prototype D.prototype.__proto__ === C.prototype // This is what 'd.inc' actually does. d.__proto__.__proto__.inc === C.prototype.inc 
 // Class variables // No ES6 syntax sugar apparently: // http://stackoverflow.com/questions/22528967/es6-class-variable-alternatives Cc = 1 Cc === 1 // Because 'D.__proto__ === C'. Dc === 1 // Nothing makes this work. dc === undefined 

Bütün əvvəlcədən təyin edilmiş obyektlər olmadan sadələşdirilmiş sxem:

  __proto__ (C)<---------------(D) (d) | | | | | | | | | |prototype |prototype |__proto__ | | | | | | | | | | | +---------+ | | | | | | | | | | vv |__proto__ (D.prototype) | | | | | | | | |__proto__ | | | | | | | | +--------------+ | | | | | | | vv | (C.prototype)--->(inc) | v Function.prototype 
63
26 мая '14 в 23:40 2014-05-26 23:40 Ciro Santilli'ye cavab verildi 改造 改造 中心 六四 事件 tövsiyə May 26, '14 at 11:40 2014-05-26 23:40

Bu mövzunu oxuduqdan sonra JavaScript prototipi zənciri ilə utandım, sonra da bu diaqramları tapdım

http://iwiki.readthedocs.org/en/latest/javascript/js_core.html#inheritance 2019

63
07 нояб. Cavab verilən rockXrock 07 Nov. 2012-11-07 12:48 '12 at 12:48 2012-11-07 12:48

Hər bir obyektin daxili mülkiyyəti var, [[Prototype]], başqa bir obyekt ilə əlaqələndirir:

 object [[Prototype]] -> anotherObject 

Ənənəvi javascriptdə əlaqəli obyekt prototype funksiyasının xüsusiyyətidir:

 object [[Prototype]] -> aFunction.prototype 

Bəzi mühitlər [[Prototype]] __proto__ kimi __proto__ :

 anObject.__proto__ === anotherObject 

Bir obyekt yaratarkən [[Prototype]] link yaratmaq.

 // (1) Object.create: var object = Object.create(anotherObject) // object.__proto__ = anotherObject // (2) ES6 object initializer: var object = { __proto__: anotherObject }; // object.__proto__ = anotherObject // (3) Traditional JavaScript: var object = new aFunction; // object.__proto__ = aFunction.prototype 

Belə ki, bu ifadələr bərabərdir:

 var object = Object.create(Object.prototype); var object = { __proto__: Object.prototype }; // ES6 only var object = new Object; 
Operator

new bir keçid hədəfini göstərmir ( Object.prototype ); Bunun əvəzində hədəf konstruktor tərəfindən nəzərdə tutulur ( Object ).

Xatırla:

  • Hər bir obyektin [[Prototype]] linki bəzən __proto__ kimi göstərilir.
  • Hər funksiyanın prototype xüsusiyyətinə malikdir.
  • new yaradılmış obyektlər öz konstruktorlarının prototype xüsusiyyətləri ilə əlaqələndirilir.
  • Bir funksiya heç bir konstruktor olaraq istifadə prototype , onun prototype xüsusiyyətindən istifadə olunmayacaqdır.
  • Bir konstruktor lazım deyilsə, new yerinə Object.create istifadə edin.
36
18 июня '13 в 22:48 2013-06-18 22:48 Cavab SAM tərəfindən 18 İyun 2013 günü saat 10:48 da verilir 2013-06-18 22:48

Bu yazı uzun. Amma əminəm ki, bu, JavaScript iradəsinin "prototipik" təbiəti üçün istəklərinizdən ən çoxunu siləcəkdir. Və daha çox. Tam məqaləni oxuyun.

JavaScript əsasən iki növ veri növünə malikdir.

  • Nesneler deyil
  • Obyektlər

Nesneler deyil

Aşağıdakı qeyri-obyekt növləridir.

  • simli
  • sayı (NaN və sonsuz daxil olmaqla)
  • boolean dəyərləri (doğru, yanlış)
  • undefined

Bu məlumat növləri typeof operatorunu istifadə etdikdən sonra qaytarılır.

typeof "string literal" (və ya bir simli literal olan dəyişən) === 'string'

typeof 5 (və ya sayısal literal ya da NaN və ya Infynity olan ədədi hərfi və ya dəyişən) === 'nömrə'

typeof true (və ya saxta və ya dəyişən bir həqiqət və ya yalan) === 'boolean'

typeof undefined (və ya dəyişən undefined və ya dəyişən olmayan undefined) === 'undefined'

Məlumat növləri , nömrəboolean obyektlərqeyri obyektlər kimi təqdim edilə bilər. Obyekt olaraq təmsil edildikdə, onların typeof hər zaman === 'obyekt' olur. Мы вернемся к этому, когда поняли типы данных объекта.

Объекты

Типы данных объекта можно разделить на два типа

  • Объекты типа функций
  • Объекты не функционального типа

Объекты типа - это те, которые возвращают строку 'function' с оператором typeof . Все пользовательские функции и все встроенные JavaScript объекты, которые могут создавать новые объекты с помощью нового оператора, попадают в эту категорию. Məsələn,

  • Obyekt
  • String
  • Номер
  • Boolean
  • Array
  • Типизированные массивы
  • RegExp
  • Funksiyası
  • Все другие встроенные объекты, которые могут создавать новые объекты с помощью нового оператора
  • функция UserDefinedFunction () {}

Итак, typeof (Object) === typeof (String) === typeof (Number) === typeof (Boolean) === typeof (Array) === typeof (RegExp) === typeof (функция) === typeof (UserDefinedFunction) === 'function'

Все Объекты типа - это фактически экземпляры встроенного объекта JavaScript Функция (включая объект Функция , то есть он рекурсивно определен), Это как если бы эти объекты были определены следующим образом.

 var Object= new Function ([native code for object Object]) var String= new Function ([native code for object String]) var Number= new Function ([native code for object Number]) var Boolean= new Function ([native code for object Boolean]) var Array= new Function ([native code for object Array]) var RegExp= new Function ([native code for object RegExp]) var Function= new Function ([native code for object Function]) var UserDefinedFunction= new Function ("user defined code") 

Как уже упоминалось, объекты Тип функции могут создавать новые объекты с помощью оператора new . Например, для объекта типа Объект , Строка , Число , Логическое , Массив , RegExp или UserDefinedFunction можно создать с помощью

 var a=new Object() or var a=Object() or var a={} //Create object of type Object var a=new String() //Create object of type String var a=new Number() //Create object of type Number var a=new Boolean() //Create object of type Boolean var a=new Array() or var a=Array() or var a=[] //Create object of type Array var a=new RegExp() or var a=RegExp() //Create object of type RegExp var a=new UserDefinedFunction() 

Созданные объекты - это все Объекты типа Non Function и возвращают тип === 'объект . Во всех этих случаях объект "a" не может далее создавать объекты с использованием оператора new. Итак, неправильно:

 var b=new a() //error. a is not typeof==='function' 

Встроенный объект Math - typeof === 'object' . Следовательно, новый объект типа Math не может быть создан новым оператором.

 var b=new Math() //error. Math is not typeof==='function' 

Также обратите внимание, что Объект , Массив и RegExp могут создавать новый объект, даже не используя оператор new , Тем не менее, это не так.

 var a=String() // Create a new Non Object string. returns a typeof==='string' var a=Number() // Create a new Non Object Number. returns a typeof==='number' var a=Boolean() //Create a new Non Object Boolean. returns a typeof==='boolean' 

Пользовательские функции являются особым случаем.

 var a=UserDefinedFunction() //may or may not create an object of type UserDefinedFunction() based on how it is defined. 

Так как объекты Объекты функций могут создавать новые объекты, их также называют Конструкторами .

Каждый Конструктор/Функция (независимо от того, была ли построена или определена пользователем), когда определено автоматически, имеет свойство "prototype" , значение которого по умолчанию задано как объект. Этот объект имеет свойство "конструктор , который по умолчанию ссылается на Конструктор/Функция .

Например, когда мы определяем функцию

 function UserDefinedFunction() { } 

автоматически происходит

 UserDefinedFunction.prototype={constructor:UserDefinedFunction} 

Это свойство "prototype" присутствует только в объектах типа функций (и никогда не в объектах типа Non Function ).

Это связано с тем, что при создании нового объекта (с использованием нового оператора) он наследует все свойства и методы из объекта прототипа функции конструктора, т.е. внутренняя ссылка создается во вновь созданном объекте, который ссылается на объект, на который ссылается объект прототипа функции Constructor.

Эта "внутренняя ссылка , созданная в объекте для ссылки на унаследованные свойства, известна как прототип объекта (который ссылается на объект, на который ссылается конструктор "prototype" , но отличается от него). Для любого объекта (Function или Non Function) это можно получить с помощью метода Object.getPrototypeOf() . Используя этот метод, можно проследить цепочку прототипов объекта.

Кроме того, каждый созданный объект ( Тип функции или Тип нефункции ) имеет конструктор " , которое наследуется от объекта, на который ссылается свойство prototype функции Constructor. По умолчанию свойство " конструктор ссылается на конструктор , который его создал (если <конструктоp > по умолчанию "prototype" не изменен).

Для всех объектов типа функций функция конструктора всегда Функция Function() {}

Для объектов типа Non Function (например, Javascript Built in Math object) функция-конструктор - это функция, которая ее создала. Для объекта Math это функция Object() {} .

Вся описанная выше концепция может быть немного сложной для понимания без какого-либо вспомогательного кода. Прочтите следующий код, чтобы понять концепцию. Попробуйте выполнить его, чтобы лучше понять.

 function UserDefinedFunction() { }  var newObj_1=new UserDefinedFunction() alert(Object.getPrototypeOf(newObj_1)===UserDefinedFunction.prototype) //Displays true alert(newObj_1.constructor) //Displays function UserDefinedFunction //Create a new property in UserDefinedFunction.prototype object UserDefinedFunction.prototype.TestProperty="test" alert(newObj_1.TestProperty) //Displays "test" alert(Object.getPrototypeOf(newObj_1).TestProperty)// Displays "test" //Create a new Object var objA = { property1 : "Property1", constructor:Array } //assign a new object to UserDefinedFunction.prototype UserDefinedFunction.prototype=objA alert(Object.getPrototypeOf(newObj_1)===UserDefinedFunction.prototype) //Displays false. The object referenced by UserDefinedFunction.prototype has changed //The internal reference does not change alert(newObj_1.constructor) // This shall still Display function UserDefinedFunction alert(newObj_1.TestProperty) //This shall still Display "test" alert(Object.getPrototypeOf(newObj_1).TestProperty) //This shall still Display "test" //Create another object of type UserDefinedFunction var newObj_2= new UserDefinedFunction(); alert(Object.getPrototypeOf(newObj_2)===objA) //Displays true. alert(newObj_2.constructor) //Displays function Array() alert(newObj_2.property1) //Displays "Property1" alert(Object.getPrototypeOf(newObj_2).property1) //Displays "Property1" //Create a new property in objA objA.property2="property2" alert(objA.property2) //Displays "Property2" alert(UserDefinedFunction.prototype.property2) //Displays "Property2" alert(newObj_2.property2) // Displays Property2 alert(Object.getPrototypeOf(newObj_2).property2) //Displays "Property2" 

Цепочка прототипов каждого объекта в конечном счете возвращается к объекту Object.prototype(который сам по себе не имеет прототипа). Следующий код может использоваться для отслеживания цепочки прототипов объекта

 var o=Starting object; do { alert(o + "\n" + Object.getOwnPropertyNames(o)) }while(o=Object.getPrototypeOf(o)) 

Цепочка прототипов для различных объектов работает следующим образом.

  • Каждый объект Function (включая встроенный объект Function) → Function.prototype → Object.prototype → null
  • Простые объекты (созданные новым объектом() или {}, включая встроенный объект Math) → Object.prototype → null
  • Объект, созданный с помощью новой или Object.create → Цепочки прототипов One или More → Object.prototype → null

Для создания объекта без какого-либо прототипа используйте следующее:

 var o=Object.create(null) alert(Object.getPrototypeOf(o)) //Displays null 

Можно подумать, что установка свойства prototype конструктора в null должна создать объект с нулевым прототипом. Однако в таких случаях созданный прототип объекта устанавливается в Object.prototype, и его конструктор настроен на функцию Object. Об этом свидетельствует следующий код

 function UserDefinedFunction(){} UserDefinedFunction.prototype=null// Can be set to any non object value (number,string,undefined etc.) var o=new UserDefinedFunction() alert(Object.getPrototypeOf(o)==Object.prototype) //Displays true alert(o.constructor) //Displays Function Object 

Следуя в резюме этой статьи

  • Существует два типа объектов Типы функций и Нефункциональные типы
  • Только Объекты типа функций могут создавать новый объект с помощью оператора new . Созданные объекты представляют собой объекты Non Function type . Объекты Non Function type не могут создавать объект с помощью оператора new .

  • Все Объекты типа функций по умолчанию имеют свойство "prototype" . Это свойство "prototype" ссылается на объект с конструктором "конструктор , который по умолчанию ссылается на объект Тип объекта .

  • Все объекты ( Тип функции и Тип нефункции ) имеют свойство "конструктор", которое по умолчанию ссылается на созданный им объект Объект функции / Конструктор .

  • Каждый объект, который создается внутри, ссылается на объект, на который ссылается "prototype" свойства создателя, создавшего его. Этот объект известен как созданный прототип объекта (который отличается от свойства объектов типа "prototype", который он ссылается). Таким образом, созданный объект может напрямую обращаться к методам и свойствам, определенным в объекте, на который ссылается свойство Constructor "prototype" (во время создания объекта).

  • Прототип объекта (и, следовательно, его наследуемые имена свойств) можно получить с помощью метода Object.getPrototypeOf() . На самом деле этот метод может использоваться для навигации по всей цепочке прототипов объекта.

  • Цепочка прототипов каждого объекта в конечном счете возвращается к Object.prototype(если объект не создан с использованием Object.create(null), и в этом случае у объекта нет прототипа).

  • typeof (new Array()) === 'object' - это дизайн языка, а не ошибка, указанная Дуглас Крокфорд

  • Установка свойства prototype конструктора в null (или undefined, number, true, false, string) не должна создавать объект с нулевым прототипом. В таких случаях созданный прототип объекта устанавливается в Object.prototype, а его конструктор настроен на функцию Object.

Bu kömək edir.

25
ответ дан Arup Hore 04 нояб. '15 в 17:08 2015-11-04 17:08

Javascript не имеет наследования в обычном смысле, но имеет цепочку прототипов.

цепочка прототипов

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

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

Это также полезно для наследования, потому что цепочка прототипов может состоять из многих других объектов.

24
ответ дан Georg Schölly 21 февр. '09 в 15:41 2009-02-21 15:41

Концепция наследования prototypal является одним из самых сложных для многих разработчиков. Попробуем понять корень проблемы, чтобы лучше понять prototypal inheritance . Начнем с функции plain .

2019

ответ дан Thalaivar 04 июля '16 в 0:44 2016-07-04 00:44

Какова цель этого свойства ".prototype"?

Интерфейс со стандартными классами становится расширяемым. Например, вы используете класс Array , и вам также необходимо добавить собственный сериализатор для всех ваших объектов массива. Вы потратили бы время на кодирование подкласса или использование композиции или... Свойство prototype разрешает это, позволяя пользователям контролировать точный набор членов/методов, доступных для класса.

Подумайте о прототипах в качестве дополнительного vtable-указателя. Когда некоторые члены отсутствуют в исходном классе, прототип просматривается во время выполнения.

20
ответ дан dirkgently 21 февр. '09 в 15:37 2009-02-21 15:37

Это может помочь классифицировать цепи прототипов в две категории.

Рассмотрим конструктор:

  function Person() {} 

Значение Object.getPrototypeOf(Person) является функцией. На самом деле это Function.prototype . Поскольку Person был создан как функция, он разделяет тот же объект-объект прототипа, что и все функции. Это то же самое, что и Person.__proto__ , но это свойство не должно использоваться. Во всяком случае, при Object.getPrototypeOf(Person) вы эффективно поднимаетесь по лестнице так называемой цепи прототипов.

Цепочка в направлении вверх выглядит следующим образом:

PersonFunction.prototypeObject.prototype (конечная точка)

Важно то, что эта цепочка прототипов имеет мало общего с объектами, которые может быть сконструирован Person . Эти построенные объекты имеют свою собственную прототипную цепочку, и эта цепочка потенциально не может иметь близкого предшественника с упомянутым выше.

Возьмем, к примеру, этот объект:

 var p = new Person(); 

p не имеет прямых отношений между прототипом и линией. Их отношения разные. Объект p имеет свою собственную прототипную цепочку. Используя Object.getPrototypeOf , вы найдете цепочку следующим образом:

pPerson.prototypeObject.prototype (конечная точка)

В этой цепочке нет функционального объекта (хотя это может быть).

Итак, Person кажется связанным с двумя типами цепей, которые живут своей жизнью. Чтобы "прыгать" из одной цепи в другую, вы используете:

  • .prototype : перейти от цепочки конструктора к цепочке созданных объектов. Это свойство, таким образом, определяется только для объектов функции (поскольку new может использоваться только для функций).

  • .constructor : перейти от цепочки созданных объектов к цепочке конструкторов.

Здесь представлено визуальное представление двух задействованных цепочек прототипов, представленных в виде столбцов:

2019

Добавление уровней в цепочку прототипов

Хотя объект-прототип создается при создании функции-конструктора, вы можете игнорировать этот объект и назначать другой объект, который должен использоваться в качестве прототипа для любых последующих экземпляров, созданных этим конструктором.

Məsələn:

 function Thief() { } var p = new Person(); Thief.prototype = p; // this determines the prototype for any new Thief objects: var t = new Thief(); 

Теперь цепочка прототипов t на один шаг длиннее, чем у p:

tpPerson.prototypeObject.prototype (конечная точка)

Другая цепочка прототипов не больше: Thief и Person являются братьями и сестрами, разделяющими один и тот же родительский элемент в цепочке прототипов:

Person }
Thief } → Function.prototypeObject.prototype (конечная точка)

Предыдущая представленная графика затем может быть расширена до этого (исходный Thief.prototype не учитывается):

2019

ответ дан trincot 19 марта '17 в 1:06 2017-03-19 01:06

Окончательное руководство по объектно-ориентированному JavaScript - очень краткое и понятное объяснение 30-минутного вопроса по заданному вопросу (тема Prototypal Inheritance начинается с 5:45 , хотя я бы предпочел слушать все видео). Автор этого видео также сделал сайт JavaScript-визуализатора JavaScript http://www.objectplayground.com/ . 2019

ответ дан Bad 18 февр. '16 в 18:17 2016-02-18 18:17

Мне было полезно объяснить "цепочку прототипов" как рекурсивное соглашение, когда ссылается obj_n.prop_X :

если obj_n.prop_X не существует, проверьте obj_n+1.prop_X где obj_n+1 = obj_n.[[prototype]]

Если prop_X наконец-то найден в k-м прототипе объекта, то

obj_1.prop_X = obj_1.[[prototype]].[[prototype]]..(k-times)..[[prototype]].prop_X

Вы можете найти график зависимости объектов Javascript от их свойств здесь:

2019

14
ответ дан BM 21 окт. '13 в 1:46 2013-10-21 01:46

Когда конструктор создает объект, этот объект неявно ссылается на свойство конструкторов "prototype" с целью разрешения ссылок на свойства. Свойство конструкторов "prototype" может ссылаться на конструктор конструктора program.prototype, а свойства, добавленные в прототип объектов, совместно используются через наследование всеми объектами, совместно использующими прототип.

13
ответ дан Tom 05 февр. '10 в 21:42 2010-02-05 21:42

Позвольте мне рассказать вам свое понимание прототипов. Я не собираюсь сравнивать наследование здесь с другими языками. Я хочу, чтобы люди переставали сравнивать языки и просто понимали язык как сам. Понимание прототипов и прототипного наследования настолько просто, как я покажу вам ниже.

Прототип похож на модель, на основе которой вы создаете продукт. Важным моментом для понимания является то, что при создании объекта с использованием другого объекта в качестве прототипа связь между прототипом и продуктом вечна. Məsələn:

 var model = {x:2}; var product = Object.create(model); model.y = 5; product.y =>5 

Каждый объект содержит внутреннее свойство, называемое [[прототипом]], к которому можно получить доступ с помощью функции Object.getPrototypeOf() . Object.create(model) создает новый объект и присваивает ему свойство [[prototype]] для объекта модели . Следовательно, когда вы делаете Object.getPrototypeOf(product) , вы получите объект model .

Свойства в продукте обрабатываются следующим образом:

  • Когда доступ к объекту доступен только для чтения, он просматривается в цепочке областей видимости. Поиск переменной начинается с продукта вверх до прототипа. Если такая переменная найдена в поиске, поиск останавливается прямо там, и значение возвращается. Если такая переменная не может быть найдена в цепочке областей видимости, возвращается undefined.
  • Когда свойство записывается (изменяется), свойство всегда записывается в объект product . Если продукт уже не имеет такого свойства, он неявно создается и записывается.

Такое связывание объектов с использованием свойства prototype называется прототипным наследованием. Там, так просто, согласитесь?

10
ответ дан Aravind 09 нояб. '14 в 18:47 2014-11-09 18:47

Рассмотрим следующий объект keyValueStore :

 var keyValueStore = (function() { var count = 0; var kvs = function() { count++; this.data = {}; this.get = function(key) { return this.data[key]; }; this.set = function(key, value) { this.data[key] = value; }; this.delete = function(key) { delete this.data[key]; }; this.getLength = function() { var l = 0; for (p in this.data) l++; return l; } }; return { // Singleton public properties 'create' : function() { return new kvs(); }, 'count' : function() { return count; } }; })(); 

Я могу создать новый экземпляр этого объекта, выполнив следующее:

 kvs = keyValueStore.create(); 

Каждый экземпляр этого объекта имеет следующие общедоступные свойства:

  • data
  • get
  • set
  • delete
  • getLength

Теперь предположим, что мы создаем 100 экземпляров этого объекта keyValueStore . Даже если get , set , delete , getLength будут делать то же самое для каждого из этих 100 экземпляров, каждый экземпляр имеет свою собственную копию этой функции.

Теперь представьте, можете ли вы иметь только одну копию get , set , delete и getLength , и каждый экземпляр ссылается на эту же функцию. Это будет лучше для производительности и потребует меньше памяти.

То, что происходит в прототипах. Прототип - это "схема" свойств, которые наследуются, но не копируются экземплярами. Таким образом, это означает, что он существует только один раз в памяти для всех экземпляров объекта и разделяется всеми этими экземплярами.

Теперь рассмотрим объект keyValueStore еще раз. Я мог бы переписать его вот так:

 var keyValueStore = (function() { var count = 0; var kvs = function() { count++; this.data = {}; }; kvs.prototype = { 'get' : function(key) { return this.data[key]; }, 'set' : function(key, value) { this.data[key] = value; }, 'delete' : function(key) { delete this.data[key]; }, 'getLength' : function() { var l = 0; for (p in this.data) l++; return l; } }; return { 'create' : function() { return new kvs(); }, 'count' : function() { return count; } }; })(); 

Это ТОЧНО аналогично предыдущей версии объекта keyValueStore , за исключением того, что все его методы теперь помещены в прототип. Это означает, что все 100 экземпляров теперь используют эти четыре метода, а не каждый из них имеет свою собственную копию.

9
ответ дан John Slegers 11 марта '16 в 22:24 2016-03-11 22:24

Здесь есть два разных, но связанных объекта, которые требуют объяснения:

  • Свойство .prototype функций.
  • Свойство [[Prototype]] [1] всех объектов [2] .

Это две разные вещи.

Свойство [[Prototype]] :

Это свойство, которое существует во всех объектах [2] .

Что хранится здесь, это другой объект, который, как сам объект, имеет [[Prototype]] , который указывает на другой объект. У этого другого объекта есть [[Prototype]] . Эта история продолжается до тех пор, пока вы не достигнете прототипа объекта, который предоставляет методы, доступные для всех объектов (например, .toString ).

Свойство [[Prototype]] является частью того, что формирует цепочку [[Prototype]] . Эта цепочка объектов [[Prototype]] - это то, что рассматривается, когда на объект выполняются, например, операции [[Get]] или [[Set]] :

 var obj = {} obj.a // [[Get]] consults prototype chain obj.b = 20 // [[Set]] consults prototype chain 

Свойство .prototype :

Это свойство, которое доступно только для функций. Используя очень простую функцию:

 function Bar(){}; 

Свойство .prototype содержит объект, который будет назначен b.[[Prototype]] , когда вы сделаете var b = new Bar . Вы можете легко изучить это:

 // Both assign Bar.prototype to b1/b2[[Prototype]] var b = new Bar; // Object.getPrototypeOf grabs the objects [[Prototype]] console.log(Object.getPrototypeOf(b) === Bar.prototype) // true 

Одним из наиболее важных .prototype является функции Object . Этот прототип содержит прототипный объект, содержащий все цепочки [[Prototype]] . На нем определены все доступные методы для новых объектов:

 // Get properties that are defined on this object console.log(Object.getOwnPropertyDescriptors(Object.prototype)) 

Теперь, поскольку .prototype является объектом, он имеет свойство [[Prototype]] . Если вы не выполняете никаких присвоений Function.prototype , .prototype [[Prototype]] указывает на прототип объекта ( Object.prototype ). Это автоматически выполняется в любое время при создании новой функции.

Таким образом, всякий раз, когда вы делаете new Bar; цепочка прототипов для вас, вы получаете все, что определено на Bar.prototype , и все, что определено на Object.prototype :

 var b = new Bar; // Get all Bar.prototype properties console.log(b.__proto__ === Bar.prototype) // Get all Object.prototype properties console.log(b.__proto__.__proto__ === Object.prototype) 

Когда вы выполняете присваивания Function.prototype , все, что вы делаете, это расширение цепочки прототипов для включения другого объекта. Это как вставка в односвязном списке.

Это в основном изменяет цепочку [[Prototype]] , позволяющую видеть свойства, определенные для объекта, назначенного Function.prototype , для просмотра любым объектом, созданным функцией.


[1: Это никого не смутит; доступный через свойство __proto__ во многих реализациях.
[2]: Все, кроме null .

9
ответ дан Jim Fasarakis Hilliard 13 дек. '17 в 13:10 2017-12-13 13:10

Еще одна попытка объяснить наследование на основе прототипа JavaScript с лучшими снимками

2019

ответ дан rus1 25 окт. '15 в 0:21 2015-10-25 00:21

Мне всегда нравятся аналоги, когда дело доходит до понимания этого типа вещей. "Прототипическое наследование" довольно запутанно по сравнению с наследованием класса баса, на мой взгляд, хотя прототипы - гораздо более простая парадигма. На самом деле с прототипами действительно нет наследования, поэтому само по себе это вводит в заблуждение, это скорее тип делегирования.

Представьте себе это....

Вы в старшей школе, и вы в классе, и у вас есть опрос, которая должна состояться сегодня, но у вас нет ручки, чтобы заполнить ваши ответы. Doh

Ты сидишь рядом со своим другом Финнисом, у которого может быть ручка. Вы спрашиваете, и он безуспешно оглядывается по столу, но вместо того, чтобы сказать "у меня нет ручки", он хороший друг, которого он проверяет со своим другом другом Дерпом, если у него есть ручка. У Дерпа действительно есть запасное перо и передает его Финниусу, который передает его вам, чтобы завершить викторину. Дерп поручил ручку Finnius, который делегировал вам перо для использования.

Важно то, что Дерп не дает вам ручку, так как у вас нет прямых отношений с ним.

Это упрощенный пример того, как работают прототипы, где дерево данных ищет предмет, который вы ищете.

7
ответ дан Louis Moore 26 мая '17 в 13:24 2017-05-26 13:24

Xülasə:

  • Функции являются объектами в JavaScript и, следовательно, могут иметь свойства
  • (Конструктор) функции всегда имеют свойство прототипа
  • Когда функция используется в качестве конструктора с new ключевым словом, объект получает свойство __proto__
  • Это свойство __proto__ ссылается на свойство prototype функции конструктора.

Məsələn:

 function Person(name) { this.name = name; } let mySelf = new Person('Willem'); console.log(mySelf.__proto__ === Person.prototype); console.log(mySelf.__proto__.__proto__ === Object.prototype); 
4
18 авг. 18 Avqustda cənab Willem van der Veen tərəfindən verilmiş cavab '18 в 13:24 2018-08-18 13:24

другая схема, показывающая __proto__ , отношения между прототипом и конструктором : 2019

ответ дан IvanM 02 авг. '18 в 9:16 2018-08-02 09:16

Просто у вас уже есть объект с Object.new но у вас все еще нет объекта при использовании синтаксиса конструктора.

2
ответ дан shiva kumar 01 февр. '18 в 12:33 2018-02-01 12:33

Важно понимать, что существует различие между прототипом объекта (который доступен через Object.getPrototypeOf(obj) или через устаревшее свойство obj.__proto__ ) и свойством prototype в функциях конструктора. Первый является свойством каждого экземпляра, а второй - свойством конструктора. То есть Object.getPrototypeOf(new Foobar()) ссылается на тот же объект, что и Foobar.prototype .

Ссылка: https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Object_prototypes

0
ответ дан Baraa Al-Tabbaa 21 янв. '19 в 11:45 2019-01-21 11:45

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

0
ответ дан Arif 25 дек. '18 в 10:24 2018-12-25 10:24