Javascript özelliği tanımsız bir nesneyle ilişkilendirilir. Nesnelerin özellikleri ve yöntemleri. Nesne oluşturma ve kullanma

  • 29.05.2019

JavaScript, basit bir nesne tabanlı paradigma üzerinde tasarlanmıştır. Bir nesne, bir özellikler topluluğudur ve bir özellik, bir ad (veya anahtar) ve bir değer. Bir özelliğin değeri bir işlev olabilir, bu durumda özellik yöntem olarak bilinir. Tarayıcıda önceden tanımlanmış nesnelere ek olarak kendi nesnelerinizi de tanımlayabilirsiniz. Bu bölüm nesnelerin, özelliklerin, işlevlerin nasıl kullanılacağını açıklar. , ve yöntemler ve kendi nesnelerinizi nasıl oluşturacağınız.

Nesnelere genel bakış

JavaScript'teki nesneler, diğer birçok programlama dilinde olduğu gibi, gerçek hayattaki nesnelerle karşılaştırılabilir. JavaScript'teki nesne kavramı, gerçek hayattaki somut nesnelerle anlaşılabilir.

JavaScript'te bir nesne, özellikleri ve türü olan bağımsız bir varlıktır. Örneğin bir bardakla karşılaştırın. Bir fincan, özellikleri olan bir nesnedir. Bir bardağın rengi, tasarımı, ağırlığı, yapıldığı malzeme vb. Aynı şekilde, JavaScript nesneleri de özelliklerini tanımlayan özelliklere sahip olabilir.

Nesneler ve özellikler

Bir JavaScript nesnesi, kendisiyle ilişkilendirilmiş özelliklere sahiptir. Bir nesnenin özelliği, nesneye eklenen bir değişken olarak açıklanabilir. Nesne özellikleri, nesnelere ek dışında, temel olarak sıradan JavaScript değişkenleriyle aynıdır. Bir nesnenin özellikleri, nesnenin özelliklerini tanımlar. Basit bir nokta gösterimi ile bir nesnenin özelliklerine erişirsiniz:

NesneAdı.özellikAdı

Tüm JavaScript değişkenleri gibi, hem nesne adı (normal bir değişken olabilir) hem de özellik adı büyük/küçük harfe duyarlıdır. Bir özelliği, bir değer atayarak tanımlayabilirsiniz. Örneğin, "myCar adında bir nesne oluşturalım ve ona aşağıdaki gibi marka, model ve yıl adındaki özellikleri verelim:

Var myCar = new Object(); myCar.make = "Ford"; myCar.model = "Mustang"; arabam.yıl = 1969; arabam.renk; // Tanımsız

JavaScript nesnelerinin özelliklerine ayrıca bir parantez gösterimi kullanılarak erişilebilir veya ayarlanabilir (daha fazla ayrıntı için özellik erişimcilerine bakın). Nesneler bazen denir ilişkisel diziler, çünkü her özellik, ona erişmek için kullanılabilecek bir dize değeriyle ilişkilendirilir. Örneğin, myCar nesnesinin özelliklerine aşağıdaki gibi erişebilirsiniz:

MyCar ["make"] = "Ford"; myCar ["model"] = "Mustang"; myCar ["yıl"] = 1969;

Bir nesne özelliği adı, herhangi bir geçerli JavaScript dizesi veya boş dize de dahil olmak üzere bir dizeye dönüştürülebilen herhangi bir şey olabilir. Ancak, geçerli bir JavaScript tanımlayıcısı olmayan herhangi bir özellik adına (örneğin, boşluk veya kısa çizgi içeren veya bir sayı ile başlayan bir özellik adı) yalnızca köşeli parantez gösterimi kullanılarak erişilebilir. Bu gösterim, özellik adlarının dinamik olarak belirleneceği durumlarda da (özellik adı çalışma zamanına kadar belirlenmediğinde) çok kullanışlıdır. Örnekler aşağıdaki gibidir:

// tek seferde dört değişken oluşturulur ve atanır, // virgülle ayrılır var myObj = new Object (), str = "myString", Rand = Math.random (), obj = new Object (); myObj.type = "Nokta sözdizimi"; myObj ["oluşturulma tarihi"] = "Boşluklu dize"; myObj = "Dize değeri"; myObj = "Rastgele Sayı"; myObj = "Nesne"; myObj [""] = "Boş bir dize bile"; konsol.log (myObj);

JavaScript nesne özellik adları (anahtarlar) yalnızca dizeler veya Semboller olabileceğinden (bir noktada, sınıf alanları önerisi olarak özel adlar da eklenecektir), çünkü köşeli parantez gösterimindeki tüm anahtarların "Simgeler" olmadıkça dizeye dönüştürüldüğünü unutmayın. ilerler, ancak bunları formla kullanmazsınız). Örneğin, yukarıdaki kodda, anahtar obj myObj öğesine eklendiğinde, JavaScript obj.toString() yöntemini çağırır ve bu sonuç dizesini yeni anahtar olarak kullanır.

Bir değişkende depolanan bir dize değeri kullanarak da özelliklere erişebilirsiniz:

Var propertyName = "yap"; myCar = "Ford"; propertyName = "model"; myCar = "Mustafa";

Bir yapıcı işlevi kullanma

Alternatif olarak, şu iki adımla bir nesne oluşturabilirsiniz:

  1. Bir yapıcı işlevi yazarak nesne türünü tanımlayın. Büyük bir ilk harf kullanmak için iyi bir nedenle güçlü bir kural vardır.
  2. new ile nesnenin bir örneğini oluşturun.

Bir nesne türü tanımlamak için, nesne türü için adını, özelliklerini ve yöntemlerini belirten bir işlev oluşturun. Örneğin, arabalar için bir nesne türü oluşturmak istediğinizi varsayalım. Bu tür bir nesnenin Araba olarak adlandırılmasını ve marka, model ve yıl özelliklerine sahip olmasını istiyorsunuz. Bunu yapmak için aşağıdaki işlevi yazarsınız:

Fonksiyon Araba (marka, model, yıl) (bu.make = marka; bu.model = model; bu.yıl = yıl;)

İşleve iletilen değerlere dayalı olarak nesnenin özelliklerine değer atamak için bunun kullanımına dikkat edin.

Şimdi mycar adlı bir nesneyi aşağıdaki gibi oluşturabilirsiniz:

Var mycar = yeni Araba ("Kartal", "Talon TSi", 1993);

Bu ifade mycar'ı oluşturur ve ona özellikleri için belirtilen değerleri atar. O zaman mycar.make'in değeri "Eagle" dizesidir, mycar.year 1993 tamsayıdır ve bu böyle devam eder.

Yeni çağrılarla istediğiniz sayıda Araba nesnesi oluşturabilirsiniz. Örneğin,

Var kenscar = yeni Araba ("Nissan", "300ZX", 1992); var vpgscar = yeni Araba ("Mazda", "Miata", 1990);

Bir nesne, kendisi başka bir nesne olan bir özelliğe sahip olabilir. Örneğin, kişi adlı bir nesneyi aşağıdaki gibi tanımladığınızı varsayalım:

İşlev Kişi (isim, yaş, cinsiyet) (bu.isim = isim; this.age = yaş; this.sex = cinsiyet;)

ve ardından iki yeni kişi nesnesini aşağıdaki gibi somutlaştırın:

Var rand = yeni Kişi ("Rand McKinnon", 33, "M"); var ken = new Kişi ("Ken Jones", 39, "M");

Ardından, bir kişi nesnesini alan bir sahip özelliği eklemek için Araba tanımını aşağıdaki gibi yeniden yazabilirsiniz:

Fonksiyon Araba (marka, model, yıl, sahip) (bu.marke = marka; bu.model = model; bu.yıl = yıl; bu.sahip = sahip;)

Yeni nesneleri somutlaştırmak için aşağıdakileri kullanırsınız:

Var car1 = new Car ("Kartal", "Talon TSi", 1993, Rand); var car2 = new Car ("Nissan", "300ZX", 1992, ken);

Yeni nesneleri oluştururken bir değişmez dize veya tamsayı değeri iletmek yerine, yukarıdaki ifadelerin sahipler için argümanlar olarak rand ve ken nesnelerini ilettiğine dikkat edin. Daha sonra car2'nin sahibinin adını öğrenmek isterseniz aşağıdaki özelliğe erişebilirsiniz:

araba2.sahibi.adı

Önceden tanımlanmış bir nesneye her zaman bir özellik ekleyebileceğinizi unutmayın. Örneğin, açıklamada

Car1.color = "siyah";

car1'e bir özellik rengi ekler ve ona "siyah" değerini atar. Ancak, bu diğer nesneleri etkilemez. Yeni özelliği aynı türdeki tüm nesnelere eklemek için, özelliği Car nesne türünün tanımına eklemeniz gerekir.

Object.create yöntemini kullanma

Ayrıca bakınız

  • Daha derine inmek için javaScript'in nesne modelinin ayrıntılarını okuyun.
  • ECMAScript 2015 sınıfları (nesne oluşturmanın yeni bir yolu) hakkında bilgi edinmek için JavaScript sınıfları bölümünü okuyun.



Nesneler, JavaScript'teki temel kavramlardan biridir. Onları ilk çalışmaya başladığımda, bana oldukça basit göründüler: teoride tanımlandığı gibi sadece bir çift anahtar ve değer.

Ancak bir süre sonra konunun düşündüğümden çok daha karmaşık olduğunu anlamaya başladım. Sonra çeşitli kaynaklardan gelen bilgileri incelemeye başladım. Bazıları konuyla ilgili güzel bir fikir verdi ama resmin tamamını bir kerede göremedim.

Bu yazıda, JS'de nesnelerle çalışmanın tüm yönlerini, bireysel ayrıntılara fazla girmeden, ayrıca konuyu anlamanıza ve daha fazla keşfettikçe daha güvende hissetmenize yardımcı olacak önemli ayrıntıları kaçırmadan ele almaya çalıştım.

Öyleyse temel bilgilerle başlayalım.

Bir obje

JavaScript'teki bir nesne, her biri bir anahtar/değer çifti olan bir özellikler topluluğudur. Noktayı kullanarak tuşlara başvurabilirsiniz ( obj.a) veya parantez gösterimi ( nesne ["a"]).

Anahtar şuysa parantezlerin kullanılması gerektiğini unutmayın:

  • geçerli bir JavaScript tanımlayıcısı değil (boşluk, tire içerir, sayı ile başlar ...)
  • bir değişkendir.
JS'deki nesnelerin oluşturulduklarında aldıkları özelliklerden biri çağrılır. Prototip ve bu çok önemli bir kavramdır.

Prototip

JavaScript'teki her nesnenin adı verilen dahili bir özelliği vardır. Prototip... Çoğu tarayıcıda, gösterimle buna başvurabilirsiniz. __proto__.

Prototip JavaScript'te özellik devralma sağlamanın bir yoludur. Bu şekilde, bellekte kod kopyalamadan işlevselliği paylaşabilirsiniz. Yöntem, iki nesne arasında bir bağlantı oluşturarak çalışır.

Basitçe söylemek gerekirse, Prototip bir nesneden diğerine bir işaretçi oluşturur.

Prototip zinciri

JS bir nesnede bir özellik aradığında ve onu doğrudan nesnenin kendisinde bulamadığında, prototip nesnesindeki özelliğin varlığını kontrol eder. İçinde özellik yoksa, JS ilgili nesneyi prototipte aramaya devam edecektir. Bu, JS uygun bir özellik bulana veya zincirin sonuna ulaşana kadar devam eder.

Bir örnek verelim:

Var eksileri = fonksiyon () (bu.a = 1; this.b = 2;) var nesne = yeni eksiler (); cons.prototype.b = 3; cons.prototype.c = 4;
Eksileri yapıcıdır (yalnızca operatör kullanılarak çağrılabilen bir işlevdir) yeni).

Beşinci satırda yeni bir nesne oluşturuyoruz - yeni bir kopya Eksileri... Yaratıldıktan hemen sonra nesne prototip özelliğini de alır.

Ve şimdi özellikleri ekliyoruz ( "M.Ö") nesne prototipi Eksileri.
Düşünmek nesne:

obj.a // 1- burada her şey aynı, obj.a hala 1.
obj.c?- NS nesne mülk yok C! Ancak, daha önce belirtildiği gibi, JS şimdi onu prototipte arayacaktır. nesne ve 4 değerini döndürür.

Şimdi anlamını düşünelim obj.b ve kaldırdığımızda nasıl olacak obj.b?

Obj.b eşittir 2. Özelliği atadık B ama bunu prototip için yaptık Eksileri yani kontrol ettiğimizde obj.b, o zaman hala 2 alıyoruz. Ancak, çıkardıktan hemen sonra obj.b JS artık bulamıyor B o'da bj, ve bu nedenle prototipte aramaya devam edecek ve 3 değerini döndürecektir.

nesne oluşturma

Nesne değişmezi: olsun nesne = (a: 1);
Aşağıdaki prototip zincirine sahip bir nesne yarattık: obj ---> Object.prototype ---> null
Tahmin edebileceğiniz gibi, nesne.prototip nesnenin prototipi ve prototip zincirinin sonudur.

Object.create():var newObj = Object.create (obj);
Sahip olmak yeniObj aşağıdaki prototip zinciri olacaktır: yeniObj ---> nesne ---> Nesne.prototip ---> boş

Yapıcı. Yukarıdaki örnekte olduğu gibi, bir yapıcı, operatörden yararlanmamıza izin veren bir JS işlevidir. yeni bunun yeni örneklerini oluşturmak için.

ES6 sınıfları:

Sınıf dikdörtgeni (kurucu (yükseklik, genişlik) (bu.yükseklik = yükseklik; this.width = genişlik;) getArea () (bu.yüksekliği döndür * this.width;)) let square = yeni dikdörtgen (2, 2);
Meydan- yapıcı örneği dikdörtgen ve böylece arayabiliriz square.getArea () // 4, kare.genişlik ve ayrıca devralınan tüm işlevler nesne.prototip.

En iyi yol hangisi? Birden çok örnek oluşturmayı planlıyorsanız, ES6'yı veya yapıcıyı kullanabilirsiniz. Nesneyi bir kez oluşturmayı planlıyorsanız, bu en kolay yol olduğu için bir hazır bilgi belirtmek daha iyidir.

Ve şimdi öğrendiğimize göre prototip ve yeni nesneler yaratmanın tüm yollarını öğrendikten sonra, nesnelerle ilgili en kafa karıştırıcı anlardan birini tartışmaya geçebiliriz.

Nesneleri karşılaştırma ve değiştirme

JavaScript'te nesneler bir referans türündedir

Bir nesne oluşturduğumuzda olsun nesne = (a: 1);, değişken nesne nesnenin bellek adresini alır, ancak değerini almaz! Bu farkı anlamanız zorunludur, aksi takdirde hatalar oluşabilir. Başka bir nesne oluşturduğumuzda newObj = obj olsun, aslında yaratıyoruz Işaretçi belirli bir hafıza alanına nesne tamamen yeni bir nesneden ziyade.

Bunun anlamı, yaparak yeniObj.a = 2, biz aslında değişiyoruz nesne Böylece obj.a 2'ye eşit olur!

Bu yaklaşım kolayca hatalara yol açar, bu nedenle birçok şirket değişmez nesnelerle çalışır. Halihazırda oluşturulmuş bir nesneyi değiştirmek yerine, yeniden yeni bir nesne (orijinalinin bir kopyası) oluşturmanız ve içinde zaten değişiklikler yapmanız gerekecektir. Redux gibi önemli kitaplıklar bu şekilde çalışır ve genel olarak işlevsel programlamanın temel kavramlarından biridir. Bu konuda daha fazlasını okuyabilirsiniz.

eşitlik

Yukarıdakilerden, aynı özelliklere sahip olsalar bile iki nesnenin asla eşit olamayacağı sonucu çıkar. Bunun nedeni, JS'nin aslında bellekteki nesnelerin konumunu karşılaştırması ve iki nesnenin asla aynı bellek konumunda olmamasıdır.

// Aynı özelliklere sahip iki farklı nesne eşit değildir var meyve = (isim: "elma"); var meyve ayısı = (isim: "elma"); meyve === meyve ayısı; // false döndür // burada meyve ve meyve ayısı aynı nesneyi gösteriyor var meyve = (isim: "elma"); var meyve ayısı = meyve; meyve === meyve ayısı; // true döndür
Bu nedenle, büyük olasılıkla, değişmezlik gereksinimleri göz önüne alındığında, nesneleri nasıl karşılaştırabileceğinizi veya nesnelerle çeşitli manipülasyonları nasıl gerçekleştireceğinizi merak etmişsinizdir.

Birkaç olasılığı düşünelim.

Bir nesneyi değiştirme

Diyelim ki nesneleri dostane bir şekilde değiştirmememiz gerektiği açık, bu yüzden ilgili nesnenin bir kopyasını oluşturmak ve özelliklerini değiştirmek istiyoruz. kurtarmaya gelir Nesne.atama ().

Var nesne = (a: 1, b: 2); var newObj = Object.assign ((), obj, (a: 2)) // (a: 2, b: 2)
Özelliğin değerini değiştirmek istersek a nesne nesne, kullanabilirsiniz nesne.atama bir kopya oluşturmak için nesne ve onun değişiklikleri.

Örnekte, önce boş bir nesne oluşturduğumuzu, ardından değerleri kopyaladığımızı görebilirsiniz. nesne ve sonunda yeni ve kullanıma hazır bir nesne elde ederek değişikliklerimizi yapın.

Lütfen bu yöntemin derin kopyalama için çalışmayacağını unutmayın. Derin kopyalamadan bahsettiğimizde, bir veya daha fazla özelliğe sahip bir nesneyi kopyalamanız gerektiğini kastediyoruz.

Sabit nesne = (a: 1, b: (a: 1)); // b özelliği bir nesnedir
Nesne.atama () bir nesnenin özelliklerini kopyalar, bu nedenle özellik değeri bir nesneye yönelik bir işaretçiyse, yalnızca işaretçi kopyalanır.

Derin bir kopya, özyinelemeli bir işlem gerektirir. Burada bir fonksiyon yazabilir veya sadece metodu kullanabilirsiniz. _.cloneDeep Lodash kütüphanesinden.

nesne karşılaştırma

Nesnelerle çalışmak için harika bir numara, dize dönüştürmedir. Aşağıdaki örnekte, her iki nesneyi de dizelere dönüştürüyoruz ve karşılaştırıyoruz:

JSON.stringify (obj1) === JSON.stringify (obj2)
Bu yaklaşım haklıdır, çünkü sonunda bir işaretçiyi temsil eden dizeleri bir değer türüyle karşılaştırıyoruz. Kötü haber şu ki, esas olarak nesnenin özelliklerinin sırası garanti edilmediğinden, her zaman işe yaramaz.

Başka bir iyi çözüm yöntemi kullanmaktır. _.eşittir Lodash'tan derin nesne karşılaştırması yapıyor.

Ve kapatmadan önce, nesneler hakkında sık sorulan bazı soruları gözden geçirelim. Bu, konuya daha derinlemesine dalmaya ve edinilen bilgileri pratikte uygulamaya yardımcı olacaktır.

Cevabı okumadan önce çözümü kendiniz düşünmeye çalışın.

Bir nesnenin uzunluğunu nasıl bilebilirim?

Bir cevap almak için, nesnenin tüm özelliklerini tek tek yinelemeniz ve saymanız gerekir. Bu yinelemeyi gerçekleştirmenin birkaç yolu vardır:
  • için... Bu yöntem, bir nesnenin tüm sayılabilir özelliklerini ve prototip zincirlerini kapsar. Prototipi tanıdık (ve umarım materyali öğrendik), bu nedenle uygulamanın için bir nesnenin özelliklerini almak her zaman doğru olmayacaktır.
  • Object.keys... Bu yöntem, hepsinin anahtarlarını içeren bir dizi döndürür. sahip olmak(belirtilen nesneye ait) saymaözellikler. Bu yaklaşım daha iyidir, çünkü özelliklere atıfta bulunmadan yalnızca nesnenin özellikleri üzerinde çalışıyoruz. prototip... Ancak, bir öznitelik atadığınız durumlar vardır. sayılabilir false için bazı özellikler ve nesne.anahtarları sonuç olarak, onu atlar ve yanlış bir sonuç alırsınız. Bu nadiren olur, ancak bu gibi durumlarda kullanışlı olacaktır. getOwnPropertyNames.
  • getOwnPropertyNames tümünü içeren bir dizi döndürür sahip olmak nesne anahtarları (hem sayılabilir hem de sayılamayan).
Ayrıca bahsetmeye değer:
  • Object.values kendi sayılabilir özellikleri üzerinde yinelenir ve eşleşen bir dizi döndürür değerler.
  • Object.entries kendi sayılabilir özellikleri üzerinde yinelenir ve bir dizi döndürür anahtarlar ve değerleri ile.
Yukarıdaki yöntemlerin çoğunun bir dizi döndürdüğünü fark ettiğinizi düşünüyorum. Bu, dizilerle çalışmak için JavaScript yöntemlerinden tam olarak yararlanmak için bir fırsattır.

Böyle bir yöntem dizi.uzunluk... Sonuç olarak, basitçe yazabiliriz.

ObjLength = Object.getOwnPropertyNames (obj) .length olsun;

Bir nesnenin boş olup olmadığı nasıl kontrol edilir?

  1. JSON.stringify (myObj) === “()”?. Burada bir nesnenin boş olup olmadığını kolayca kontrol etmek için yine dize dönüştürme aracını kullanıyoruz (nesneleri değil dizeleri karşılaştırarak).
  2. ! Object.keys (myobj) .length // true?.? Bahsettiğim gibi, bir nesnenin anahtarlarını bir diziye dönüştürmek çok yardımcı olabilir. Burada uygun özelliği kullanıyoruz uzunluk miras kalan dizi.prototip onunla dizideki tuşların uzunluğunu kontrol etmek. JS'de 0 yanlışa döner, bu yüzden ekleyerek ! gerçeğe çeviriyoruz. Diğer sayılar yanlış olur.

Nihayet

Umarım artık nesneler yaratma ve nesnelerle çalışma konusunda kendinize daha fazla güvenirsiniz. Özetleyelim:
  • Nesnelerin referans türünde olduğunu unutmayın; bu, orijinal nesneleri değiştirmeden onlarla çalışmanın önerildiği anlamına gelir.
  • Mülk ile arkadaş olun prototip ve bir prototip zinciri.
  • Nesne Yardımcısı Araçlarına göz atın. Nesneleri dizelere dönüştürebileceğinizi, anahtarlarıyla bir dizi alabileceğinizi veya aşina olduğumuz yöntemler kümesini kullanarak özelliklerini yineleyebileceğinizi unutmayın.
JavaScript nesnelerini öğrenmede iyi şanslar.

depp 7 Ocak 2009, 23:56

JavaScript'te nesnelerle çalışma: teori ve pratik

  • JavaScript

Bu makalede, JavaScript'te bir nesnenin ne olduğu, yeteneklerinin neler olduğu, nesneler arasında hangi ilişkilerin kurulabileceği ve bundan hangi "yerel" kalıtım yöntemlerinin ortaya çıktığı, bunların nasıl etkilediği hakkında mümkün olduğunca eksiksiz ve tutarlı bir şekilde konuşmak istiyorum. performans ve ne işe yarar :)

Makale, geleneksel sınıf-nesne paradigmasının emülasyonu, sözdizimsel şeker, sarmalayıcılar ve çerçeveler hakkında tek kelime etmeyecek.

Malzemenin karmaşıklığı makalenin başından sonuna kadar artacaktır, bu nedenle profesyoneller için ilk bölümler sıkıcı ve önemsiz görünebilir, ancak dahası çok daha ilginç olacak :)

JavaScript'teki nesneler

Birçok makale "JavaScript'te her şey bir nesnedir" ifadesini içerir. Teknik olarak, bu tamamen doğru değil, ancak yeni başlayanlar üzerinde doğru izlenim bırakıyor :)

Aslında, bir dilde birçok şey bir nesnedir ve bir nesne olmayanın bile bazı yetenekleri olabilir.

Burada "nesne" kelimesinin "belirli bir sınıfın nesnesi" anlamında kullanılmadığını anlamak önemlidir. JavaScript'teki bir nesne, temel olarak, anahtar/değer çiftlerinden oluşan bir özellikler koleksiyonudur (herkes için daha kolaysa, onu ilişkisel bir dizi veya liste olarak adlandırabilirsiniz). Ayrıca, anahtar yalnızca bir dize olabilir (dizi öğeleri için bile), ancak değer aşağıda listelenen herhangi bir veri türü olabilir.

Yani JavaScript'te 6 tane var Temel tipler veriler Tanımsız (değer yok), Null, Boolean (boolean), String (string), Number (sayı) ve Object (nesne) şeklindedir.
Ayrıca ilk 5 ilkel veri türleri, ancak Object değil. Ek olarak, geleneksel olarak Nesne türünün "alt türleri" olduğu varsayılabilir: bir dizi (Array), bir işlev (İşlev), bir normal ifade (RegExp) ve diğerleri.
Bu biraz basitleştirilmiş bir tanımdır, ancak pratikte genellikle yeterlidir.

Ek olarak, String, Number ve Boolean ilkel türleri, sırasıyla Object: String, Number ve Boolean'ın ilkel olmayan "alt türleri" ile bir şekilde ilişkilidir.
Bu, örneğin "Merhaba, dünya" dizesinin hem ilkel bir değer olarak hem de String türünde bir nesne olarak oluşturulabileceği anlamına gelir.
Kısacası bu, programcının ilkel değerlerle nesnelermiş gibi çalışırken yöntem ve özellikleri kullanabilmesi için yapılır. Bununla ilgili daha fazla bilgiyi bu makalenin ilgili bölümünde okuyabilirsiniz.

Referansa göre çalışma

Bağlantı, bir nesneye çeşitli adlar altında erişmenin bir yoludur. Herhangi bir nesneyle çalışma, yalnızca referans olarak gerçekleştirilir.
Bunu bir örnekle gösterelim:
test = function () (uyarı ("Merhaba!")) // Bir fonksiyon oluşturun (alert ("Merhaba!")) (Ve hatırladığımız gibi fonksiyon tam teşekküllü bir nesnedir) ve test değişkenini ona referans yapın
test_link = test; // test_link artık fonksiyonumuza da atıfta bulunuyor
Ölçek (); // Merhaba!
test_link(); // Merhaba!


Gördüğümüz gibi, hem birinci bağlantı hem de ikinci aynı sonucu veriyor.
Test adında herhangi bir fonksiyonumuz olmadığını ve test değişkeninin bir tür "ana" veya "ana" bağlantı olmadığını ve "test_bağlantısının" küçük olduğunu anlamak gerekir.

Fonksiyonumuz, diğer nesneler gibi, sadece bellekte bir alandır ve bu alana yapılan tüm referanslar kesinlikle eşdeğerdir. Ayrıca, nesnenin hiç referansı olmayabilir - bu durumda, ona adsız denir ve yalnızca oluşturulduktan hemen sonra kullanılabilir (örneğin, bir işleve geçirilir), aksi takdirde ona erişmek imkansız olacaktır ve yakında nesneye erişilemez. çöp toplayıcı (çöp toplama) tarafından yok edilir, bu da nesneleri referanssız siler.

Bunu anlamanın neden bu kadar önemli olduğunu görelim:

test = (prop: "Bazı metin") // prop özelliğine sahip bir nesne oluşturun
test_link = test; // Bu nesneye başka bir bağlantı oluştur

Uyarı (test.prop); // Bazı metin

// Nesnenin özelliğini değiştir
test_link.prop = "yeni metin";

Uyarı (test.prop); // yeni metin
uyarı (test_link.prop); // yeni metin
/ * Mülkün şurada burada değiştiği söylenebilir - ama öyle değil.
Nesne birdir. Bu yüzden özellik, içinde bir kez değişti ve bağlantılar, işaret ettikleri yeri işaret etmeye devam ediyor. * /

// Yeni bir özellik ekleyin ve eskisini kaldırın
test.new_prop = "merhaba";
test.prop'u silin;

Uyarı (test_link.prop); // tanımsız - bu özellik artık mevcut değil
uyarı (test_link.new_prop);

// Bağlantıyı kaldır
testi sil;
uyarı (test.new_prop);
/ * Bu noktada, komut dosyası bir hata verecektir, çünkü test artık mevcut değildir ve test.new_prop artık mevcut değildir * /
uyarı (test_link.new_prop); // Merhaba
/ * ama burada her şey yolunda, çünkü nesnenin kendisini silmedik, sadece ona bir bağlantı. Şimdi nesnemiz tek bir bağlantı ile gösteriliyor test_link * /

// Yeni bir nesne oluştur
test = test_link; // Önce test bağlantısını tekrar oluşturun
test_link = (prop: "bir metin") // Ve işte yeni nesne

Uyarı (test_link.prop); // Bazı metin
uyarı (test.prop); // Tanımsız
/ * Yeni bir nesnenin oluşturulması bağlantıyı keser ve şimdi test ve test_link farklı nesnelere işaret eder.
Aslında bu, test_link'i kaldırıp yeniden oluşturmakla aynı şeydir, ancak zaten başka bir nesneye işaret eder * /
uyarı (test.new_prop); // merhaba - şimdi test ilk nesnemize bir bağlantı içeriyor


* Bu kaynak kodu, Kaynak Kodu İşaretleyici ile vurgulanmıştır.

Nesnelerin bu davranışı genellikle acemi geliştiriciler için birçok soru ortaya çıkarır, bu yüzden bu metnin biraz netlik getireceğini umuyorum. Eğer nesnenin gerçekten yeni ve bağımsız bir kopyasını oluşturmak istiyorsak ve bir bağlantı oluşturmak istemiyorsak, bunu yapmanın tek yolu yeni bir nesne oluşturmak ve gerekli özellikleri oraya kopyalamaktır.

Ayrıca, yukarıda belirtilen komik efektlere ek olarak, nesnelerle referans yoluyla çalışmanın, bir nesne programda çeşitli yerlerde yaygın olarak kullanıldığında önemli olan önemli bellek tasarrufu sağladığını da belirtmekte fayda var.

ilkel değerler

Yukarıda bahsettiğim gibi String ve Number veri tipleri hem nesneler hem de ilkel değerler olabilir.
nesne = yeni Dize ("merhaba"); // nesne olarak string yarat
basit = "merhaba"; // İlkel bir değer oluştur

Uyarı (nesne); // Merhaba
uyarı (basit); // merhaba - şimdiye kadar her şey tahmin edilebilir

Uyarı (nesne.uzunluk); // 6 - String türündeki bir nesne, string'in uzunluğunu saklayan bir length özelliğine sahiptir
uyarı (basit.uzunluk); // 6
/ * Simple bir nesne olmasa da, bir String nesnesiyle aynı özelliklere erişebiliriz. Bu oldukça kullanışlı * /

Obj.prop = "metin";
simple.prop = "metin";

Uyarı (obj.prop); // metin - obj sıradan bir nesne olduğundan, ona kolayca bir özellik daha verebiliriz
uyarı (simple.prop); // tanımsız - ancak basit bir nesne değildir ve bu sayı bizim için çalışmayacaktır

* Bu kaynak kodu, Kaynak Kodu İşaretleyici ile vurgulanmıştır.


Aynısı hem Number hem de Boolean için geçerlidir (uzunluk özelliğine sahip olmamalarının yanı sıra, bir dizi başka harika özellik de vardır).
Dizileri ve sayıları nesne olarak kullanmanın pratik bir faydası yoktur. ilkel değerlerle çalışmak daha uygundur, ancak aynı zamanda gerekli tüm işlevleri korur. Ancak, bütünlük adına, bu mekanizmayı anlamak gerekir.

İlkel değerlerin kullanımını değişmezlerin kullanımıyla karıştırmayın - örneğin, bir diziyi "test = new Array()" veya "test =" olarak oluşturup oluşturmadığımızdan bağımsız olarak, sonuç yine aynı nesne olacaktır. . Herhangi bir ilkel değer elde etmeyeceğiz.

Nesne oluşturma ve kullanma

Yani sınıf-nesne paradigmasının uygulandığı dillerden farklı olarak, önce bir sınıf oluşturmamız, ardından sınıfın bir nesnesini oluşturmamız gerekmiyor. Aşağıdaki örnekte yapacağımız gibi hemen bir nesne oluşturabiliriz:
deneme = (
simple_property: "Merhaba",
nesne_özelliği: (
user_1: "Petya",
user_2: "Vasya"
},
function_property: işlev (kullanıcı) (
uyarı (bu .simple_property + "," + bu .object_property);
}
}

Test.function_property ("kullanıcı_1"); // Merhaba Petya.

* Bu kaynak kodu, Kaynak Kodu İşaretleyici ile vurgulanmıştır.


Önümüzde, isimlerinin kendileri için konuştuğunu umduğum 3 özelliği olan test nesnesi var. Bu konuda bizi en çok ilgilendiren, işlevi içeren function_property özelliğidir. Böyle bir fonksiyon, bir nesnenin metodu olarak adlandırılabilir.

İşlevimiz, işlevin çağrıldığı nesneye bir işaretçi (yani bir başvuru) olan this anahtar sözcüğünü iki kez kullanır. Böylece, this.simple_property = test.simple_property = "Merhaba" ve this.object_property = test.object_property = "Peter".

Bunun her zaman işlevin çağrıldığı nesneye atıfta bulunduğu ve ait olduğu nesneye değil, açıkça anlaşılmalıdır. Bunlar bu örnekte aynı nesne olsa da, durum her zaman böyle değildir.

test.function_property ("kullanıcı_1"); // Merhaba Petya.

Test2 = yeni Nesne (); // test2 = () gibi yeni bir nesne yaratmanın başka bir şekli

Test.function_property.call (test2, "user_1"); //hata
/ * Çağrı yöntemi, başka bir nesne adına bir işlevi çağırmanıza olanak tanır. Bu durumda, test nesnesinin function_property yöntemini çağırırız ve bu, artık test nesnesine değil, test2 nesnesine işaret eder. Dan beri object_property özelliğine sahip değil, bu durumda this.object_property'yi almaya çalıştığınızda komut dosyası bir hata verecektir * /

// durumu düzeltmeye çalış
test2.simple_property = "İyi günler";
test2.object_property = test.object_property; // Bu durumda, kodu çoğaltmamak için nesneyi referans olarak belirtmeyi kullanacağız.

Test.function_property.call (test2, "user_1"); // İyi günler Petya.


* Bu kaynak kodu, Kaynak Kodu İşaretleyici ile vurgulanmıştır.

Bir nesneyi oluşturmak ve kullanmak için net adımlar olmadığı da örnekten açıkça anlaşılmalıdır. Nesne herhangi bir zamanda herhangi bir şekilde değiştirilebilir - kullanımdan önce, sonra ve hatta kullanım sırasında. Bu aynı zamanda "geleneksel" OOP'den önemli bir farktır.

yapıcı

Yukarıdaki örnekte, bazı benzerlikleri olan 2 nesne oluşturduk. Hem simple_property hem de object_property özellikleri mevcuttu. Açıkçası, gerçek kod yazarken, genellikle aynı veya sadece benzer nesneler oluşturma görevi ortaya çıkar. Ve elbette, bu tür her nesneyi manuel olarak oluşturmak zorunda değiliz.

Bir inşaatçı yardımımıza gelecek. JavaScript'teki yapıcı bir sınıfın parçası değildir (çünkü sınıf yoktur), ancak yalnızca kendi başına bir işlevdir. En yaygın işlev.

make_me = fonksiyon adı) (
uyarı ("Fırlatıldım");
bu .name = _name;

}


/ * Bakalım burada neler oluyor. Tercüman yeni operatörü görür ve sağında ne olduğunu kontrol eder. Çünkü make_me bir işlevdir ve yapıcı olarak kullanılabilir, ardından bellekte yeni bir nesne oluşturulur ve make_me işlevi yürütülür ve bu, bu yeni nesneye işaret eder. Daha sonra, bu nesneye, _name bağımsız değişkeninden değer atanan name özelliğine ve show_name yöntemine eklenir. Ayrıca (tam olarak hangi anda bilmiyorum ama önemli değil) çocuk değişkeni yeni, henüz doğmuş nesnemizi işaret etmeye başlar * /

Uyarı (alt.adı); // Vasya
child.show_name(); // Vasya


child2.show_name(); //Peter

Child2.show_name = function () (uyarı ( "Adımı söylemeyeceğim");} // Nesnelerimizi istediğimiz zaman değiştirebileceğimizi unutmayın
child2.show_name(); // adımı söylemeyeceğim

Child.show_name(); // Vasya - çocuklar birbirlerini hiçbir şekilde etkilemez


* Bu kaynak kodu, Kaynak Kodu İşaretleyici ile vurgulanmıştır.

Yapıcıyı bir babayla da karşılaştırabilirsiniz - bir çocuğu doğurur, ona belirli nitelikler verir, ancak yaratıldıktan hemen sonra çocuk ebeveynden tamamen bağımsız hale gelir ve kardeşlerinden çok farklı olabilir.
Makalenin başındaki veri türlerinin tanımını hatırlarsak, Nesne ve alt türlerinin (Fonksiyon, Dizi ve diğerleri) aslında oluşturulan nesneye bir işlev, dizi vb. yetenekler veren yapıcılar olduğu anlaşılır.

Yani bu çok daha iyi. Artık belirli bir kalıba göre nesneler yaratma yeteneğine sahibiz. Ancak, her şey yolunda değil. İlk olarak, yarattığımız her nesne ve tüm özellikleri ve yöntemleri, birçok yönden tekrarlanmalarına rağmen bellekte ayrı bir yer tutar. İkincisi, ebeveyn ve çocuk arasındaki bağlantıyı korumak ve tüm alt nesneleri bir kerede değiştirebilmek istiyorsak ne olur? Bir prototip yardımımıza gelecek.

Prototip

Tıpkı her çocuğun (en azından biyolojik olarak) bir babası ve annesi olduğu gibi, JavaScript'teki her nesne de öyle. Ve eğer baba, karar verdiğimiz gibi tasarımcı olarak çalışıyorsa, o zaman anne sadece bir prototiptir. Bunun nasıl olduğunu görelim:
make_me = fonksiyon adı) (
uyarı ("Fırlatıldım");
bu .name = _name;
this .show_name = function() (uyarı (bu .name);)
}
/*
Fonksiyon anahtar sözcüğünü gören yorumlayıcı, bunun sağındaki kodu kontrol eder ve her şey yolunda - hafızada yeni bir nesne yaratır, bu da bizim fonksiyonumuzdur. Ardından, otomatik olarak (programcının katılımı olmadan) bu işlev için boş bir nesneye atıfta bulunan bir prototip özelliği oluşturulur. Manuel olarak yapsaydık make_me.prototype = new Object();

Ardından, verilen nesne (prototip özelliği tarafından işaret edilir) ayrıca işleve geri dönük bir yapıcı özelliği ile otomatik olarak eklenir. Bunun dairesel bir bağlantı olduğu ortaya çıktı.

Şimdi (kurucu: ... burada fonksiyona bir referans ...) olarak tanımlanabilecek bu nesne, fonksiyon prototipidir.
*/

// Nesne gerçekten bir nesnedir
uyarı (typeof make_me.prototype.constructor); // fonksiyon bizim fonksiyonumuzdur
uyarı (make_me.prototype.constructor === make_me); // NS

// make_me işlevinin prototipine yeni bir yöntem ekleyin

Çocuk = new make_me ("Vasya"); // beni fırlattılar
/ * Şimdi, önceki örnekte açıklanan her şeye ek olarak, alt nesnede make_me.prototype ile aynı nesneye işaret eden ek bir gizli özellik [] oluşturulur. Çünkü özellik gizlidir, değerini ne görebiliriz ne de değiştirebiliriz - ancak daha sonraki çalışmalarda önemli bir rol oynar * /

Uyarı (alt.adı); // Vasya
child.show_name(); // Vasya

Child.set_name ("Kolya");
/ * İlk olarak, yorumlayıcı alt nesne üzerinde set_name yöntemini arar. Orada olmadığı için çocuğu aramaya devam eder.[] Mülk, onu orada bulur ve çalıştırır. * /
child.show_name(); // Kolya - şimdi Vasya'nın adı Kolya :)

Make_me.prototype.show_name2 = function () (uyarı ("Merhaba," + bu .name;) //T.k. prototip sıradan bir nesnedir, onu anında da değiştirebiliriz

Child2 = new make_me ("Petya");
child2.show_name2(); // Merhaba Petya
child.show_name2 (); // Merhaba Kolya - prototipteki değişiklikler sadece yeni oluşturulan nesneleri değil, tüm eskileri de etkiler

Child2.show_name2 = işlev () (uyarı ( "Adımı söylemeyeceğim");} // Bu nesnedeki (ve yalnızca içindeki) yeni show_name2 yöntemi, olduğu gibi, prototipteki eski yöntemin "üzerine yazarken" nesnenin kendisini hala değiştirebiliriz
child2.show_name2(); // Adımı söylemeyeceğim - çünkü şimdi kendi show_name2 yöntemimiz var, sonra çağrılır ve prototipte arama yapılmaz

Child.show_name2 (); // Merhaba Kolya - her şey hala burada

Make_me.prototype = (prop: "merhaba") // Prototipi yeniden yaratmayı deneyelim

Uyarı (child.prop); // Tanımsız
child.show_name2 (); //Merhaba Kolya
/ * Referansla çalışmanın ne olduğunu hatırlarsanız, her şey açıktır. Prototipin yeniden oluşturulması bağlantıyı keser ve şimdi alt ve alt2 nesnelerinin [] özelliği bir nesneye (ki bu make_me işlevinin prototipiydi) ve make_me.prototype özelliği yeni nesne olan başka bir nesneye işaret eder. make_me işlevinin prototipi * /

Child3 = new make_me ("Oleg");
uyarı (child3.prop); // merhaba - beklendiği gibi


* Bu kaynak kodu, Kaynak Kodu İşaretleyici ile vurgulanmıştır.

Örnekten de anlaşılacağı gibi, baba anneye sadık kalırken (yani işlevin prototipi aynı kalırken), tüm çocuklar anneye bağımlıdır ve annedeki tüm değişikliklere duyarlıdır. Bununla birlikte, ebeveynler boşanır boşanmaz (tasarımcı prototipi diğerine değiştirir), çocuklar hemen kiminle ve onlarla artık hiçbir bağlantısının olmadığını dağıtır.

Terminoloji hakkında biraz
Yapıcı ile prototip arasındaki birincil bağlantı kopana kadar aşağıdaki resmi görebiliriz:

make_me = fonksiyon adı) (
uyarı ("Fırlatıldım");
bu .name = _name;
this .show_name = function() (uyarı (bu .name);)
}

Make_me.prototype.set_name = fonksiyon (_name) (bu .name = _name;)
çocuk = yeni make_me ("Vasya");

Uyarı (typeof make_me.prototype); // nesne - işlevin bir prototip özelliği var
uyarı (typeof child.prototype); // tanımsız - oluşturulan nesnenin prototip özelliği YOK
uyarı (child.constructor.prototype === make_me.prototype); // true - ancak nesnenin make_me yapıcı işlevine işaret eden bir yapıcı özelliği vardır, bu da sırayla bir prototip özelliğine sahiptir


* Bu kaynak kodu, Kaynak Kodu İşaretleyici ile vurgulanmıştır.

Bu konuyla ilgili çok sayıda forum okuduktan sonra fark ettiğim gibi, insanların bir fonksiyonun prototip özelliği ile o fonksiyonla oluşturulan bir nesnenin gizli [] özelliğini karıştırdıklarında karşılaştıkları temel problemler.
Bu özelliklerin her ikisi de aynı nesneye referanslardır (prototip ile yapıcı arasındaki birincil bağlantı kopmadığı sürece), ancak yine de farklı adlara sahip farklı özelliklerdir, bunlardan biri programcı tarafından kullanılabilir ve diğer değildir.

Bir yapıcının prototipinden bahsediyorsak, bunun her zaman prototip özelliği olduğunu ve oluşturulan nesnenin prototipi hakkındaysa, bunun gizli bir özellik olduğunu her zaman açıkça anlamak gerekir [].

Miras

Artık her nesnenin gizli bir prototip referansı olduğunu ve her prototipin normal bir nesne olduğunu biliyoruz.
En anlayışlı okuyucular zaten özyinelemenin kokusunu aldı :)
Nitekim, beri bir prototip sıradan bir nesnedir, o zaman sırayla onun prototipiyle bir bağlantısı vardır, vb. Prototip hiyerarşisi bu şekilde uygulanır.
kuş = işlev () () // Bu kuş yapıcısıdır
bird.prototype.cry = işlev () (uyarı ("Cree!");) // Kuş çığlık atabilir
bird.prototype.fly = function () (uyarı ("Uçuyorum!");) // ve uç

Ördek = fonksiyon () ()
ördek.prototip = yeni kuş ();
duck.prototype.cry = function() (uyarı ("Quack şarlatan!");) // Ördek farklı şekilde çığlık atıyor
ördek.prototype.constructor = ördek; // Prototip.constructor özelliğini ördek olarak ayarlanmaya zorlayın, çünkü aksi takdirde kuşa atıfta bulunacaktır

Billy = yeni ördek (); // Billy bizim ördeğimiz
billy.fly(); //Uçuyorum! - Billy uçabilir çünkü o bir kuş
billy.cry(); // vak vak! - Billy ördek olduğu için vak diye bağırıyor


* Bu kaynak kodu, Kaynak Kodu İşaretleyici ile vurgulanmıştır.

Bu şekilde, herhangi bir yuvalama düzeyinde bir hiyerarşi uygulayabilirsiniz.

yıldız sorunu

Şimdi, tüm bunlar hakkında çok şey bildiğimize göre, bu üç satırda ne kadar olduğunu anlamaya çalışalım.
make_me = işlev () ()
çocuk = yeni make_me();
uyarı (child.toString()); // çıktılar

* Bu kaynak kodu, Kaynak Kodu İşaretleyici ile vurgulanmıştır.

İlk satırda yeni bir fonksiyon ve bu fonksiyona işaret eden make_me değişkeni oluşturuyoruz. Bu, make_me'ye işaret eden bir yapıcı özelliği içeren make_me.prototype işlevi için bir prototip oluşturur.
Ama hepsi bu değil :)
Çünkü make_me işlevi de bir nesnedir, o zaman sırayla bir babası ve bir annesi vardır, yani. yapıcı ve prototip. Yapıcısı, Function () dilinin yerel bir işlevidir ve prototipi, call, application vb. yöntemlerini içeren bir nesnedir. - bu prototip sayesinde bu yöntemleri herhangi bir fonksiyonda kullanabiliriz. Bu, make_me işlevine Function.prototype'a işaret eden bir [] özelliği verir.

Buna karşılık, Function yapıcısının prototipi de, yapıcısı (sürpriz!) Object (yani Function.prototype. []. Constructor === Nesne) olan bir nesnedir ve prototip, standart özellikleri içeren bir nesnedir. ve toString, hasOwnProperty ve diğerleri gibi nesnenin yöntemleri (diğer bir deyişle - Function.prototype. [] ["hasOwnProperty"] - bu, tüm türetilmiş nesnelerde kullanabileceğimiz yöntemle tamamen aynıdır - ve bu tam olarak bu nesnenin kendi yöntemidir ve miras alınmaz). Bu şekilde ilginç bir şekilde her türlü nesnenin Object'ten türetildiğini öğreniyoruz.

Daha fazla devam edebilir miyiz? Değil çıkıyor. Object.prototype, kendi prototipine sahip olmadığı için tam olarak bir nesnenin temel özelliklerini içerir. Object.prototype.[] = Null; Bu noktada, bir özellik veya yöntem bulmak için prototip zincirindeki yolculuk durur.

Bir başka ilginç gerçek, Object'in yapıcısının Function olmasıdır. Onlar. Nesne [].Yapıcı === İşlev.
Başka bir döngüsel başvuru var - Object yapıcısı Function'dır ve Function.prototype yapıcısı Object'tir.

Örneğimize geri dönelim. Fonksiyonun nasıl oluşturulduğunu zaten anladık, şimdi ikinci satıra geçelim. Burada yapıcısı make_me işlevi ve prototipi make_me.prototype olan bir alt nesne yaratıyoruz.

Üçüncü satırda yorumlayıcının çocuktan çocuğa zincirde nasıl yukarı çıktığını görüyoruz [] (Aka make_me.prototype), sonra çocuğa. yürütme için başlatılan toString yöntemi.

safsızlıklar

JavaScript'in mümkün olmasının tek yolu prototipler yoluyla kalıtım gibi görünebilir. Bu doğru değil.
Kurallardan çok olasılıklar sağlayan çok esnek bir dille uğraşıyoruz.

Örneğin, istersek prototipleri hiç kullanamayız, ancak mixins kavramını kullanarak programlayabiliriz. Bunun için eski güzel dostlarımız - inşaatçılar bize faydalı olacaktır.

// Bu bir insan yapıcıdır
adam = fonksiyon () (
bu .live = function () (uyarı ("yaşıyorum");) // Bir kişi nasıl yaşayacağını bilir
bu .walk = function () (uyarı ("yürüyorum");) // Bir kişi yürüyebilir
}

// Bu, şairin kurucusudur
şair = işlev () (
bu .kill = işlev () (uyarı ( "Şair bir adamı öldürdü");} // Bir şair bir insanı öldürebilir
bu .live = function () (uyarı ("Öldüm");) // Bu kişinin ölmesine neden olur
}

Vladimir = yeni adam (); // Vladimir bir erkek
vladimir.live(); // yaşıyorum - o yaşıyor
vladimir.yürüyüş (); // ben yürüyorum - o yürüyor

Şair.çağrı (vladimir); // vladimir nesnesi için şair yapıcısını yürütün
vladimir.kill(); // Şair adamı öldürdü
vladimir.live(); //Ben ölüyüm

// Ve şimdi odak
man.call (vladimir);
vladimir.live(); //Yaşıyorum


* Bu kaynak kodu, Kaynak Kodu İşaretleyici ile vurgulanmıştır.

Bu örnekte ne görüyoruz? Birincisi, aynı hiyerarşide olmayan birden çok nesneden miras alma yeteneğidir. Örnekte 2 tane var ama istediğiniz kadar olabilir.
İkincisi, bu herhangi bir hiyerarşinin olmamasıdır. Geçersiz kılma özellikleri ve yöntemleri, yalnızca kurucuların çağrıldığı sıraya göre belirlenir.
Üçüncüsü, bu, bir nesneyi daha dinamik bir şekilde değiştirme yeteneğidir ve prototipi değiştirirken olduğu gibi tüm torunları değil, ayrı bir nesnedir.

Upd: Kapanışlar ve Özel Mülkler

Zaten oldukça büyük olan bu makaleyi şişirmemek için, bu konuda ayrıntılı olarak yazıldığı yazıya bir bağlantı veriyorum.

Bütün bunlarla şimdi ne yapmalı

Yukarıda söylediğim gibi, tek tek nesnelerin keyfi modifikasyonu, yapıcıların ve karışımların kullanımı ve prototiplerin esnekliği sadece araçlardır, bir programcının her açıdan hem korkunç hem de güzel kod oluşturmasına izin veren fırsatlardır. Sadece hangi görevleri, hangi yollarla çözdüğümüzü, hangi hedeflere ulaştığımızı ve bunun için ne kadar ödediğimizi anlamak önemlidir.

Ayrıca, özellikle Internet Explorer 6 ve 7 sürümleri için geliştirme hakkında konuşuyorsak, fiyat sorunu oldukça önemsizdir.
1. Hafıza - burada her şey basit. Tüm tarayıcılarda, prototipler üzerindeki kalıtım, yapıcılar aracılığıyla yöntemler oluşturmaya kıyasla birkaç kat daha az bellek alır. Ayrıca, ne kadar çok yöntem ve özelliğe sahip olursak, fark o kadar büyük olur. Bununla birlikte, bin özdeş nesnemiz yoksa, yalnızca bir tane varsa, o zaman her durumda bellek tüketiminin küçük olacağını hatırlamakta fayda var, çünkü burada dikkate alınması gereken başka faktörler de var.
2. İşlemci süresi - burada ana incelikler Microsoft'un tarayıcılarıyla bağlantılıdır.
Bir yandan, bir yapıcı aracılığıyla yöntemlerin ve özelliklerin oluşturulduğu nesneler, bir prototip aracılığıyla olduğundan çok daha yavaş (bazı durumlarda onlarca veya yüzlerce kez) oluşturulabilir. Ne kadar çok yöntem, o kadar yavaş. Bu nedenle, betiğin başlatılması sırasında IE'niz birkaç saniye donarsa - bu yönde kazmak için bir neden vardır.

Öte yandan, bir nesnenin kendi yöntemleri (bir kurucu aracılığıyla oluşturulan), prototip haline getirilmiş olanlardan biraz daha hızlı çalışabilir. Bu tarayıcıda bir yöntemin yürütülmesini umutsuzca hızlandırmanız gerekiyorsa, bunu hesaba katmanız gerekir. Hızlandırılanın yürütme değil, yöntem çağrısı (yani nesnede arama) olduğunu unutmayın. Bu nedenle, yöntemin kendisi bir saniye çalışırsa, performansta özel bir artış görmezsiniz.

Diğer tarayıcılarda, nesne oluşturma ve yöntemlerini çağırma zamanının her iki yaklaşım için yaklaşık olarak aynı olduğu benzer sorunlar gözlemlenir.

not Genellikle, bu tür makalelerde yazar, ya prototipe dayalı sınıf-nesne kalıtımını uygulamaya çalışan bir çeşit sarmalayıcı ya da prototip kalıtım için sadece sözdizimsel şeker sunar. Bunu bilerek yapmıyorum çünkü Bence bu yazının anlamını anlayan bir kişi kendisi için herhangi bir sarmalayıcı ve daha birçok ilginç şey yazabilir :)

Etiketler:

  • ayy
  • miras
  • javascript
Etiket ekle

Bir web kaynağına yapılan ziyaret, tarayıcının adres çubuğundaki belirli bir URI'dir. Ziyaretçi, sayfanın adresini belirtir ve tarayıcı tarafından DOM ağacının - Belge Nesne Modeli öğelerine ayrıştırılır. Bu sayfadaki herhangi bir bağlantı, tarayıcıya başka bir sayfayı ayrıştırmasını ve başka bir nesne ağacı oluşturmasını söyler.

Tarayıcı, ziyaretçinin mevcut oturumda zaten görüntülenmiş olan bir sayfa zincirinde geriye veya ileriye gitmesine izin verir.

Aslında, kullanıcı eylemleri, sayfaları ziyaret etme sürecinde oluşturulan nesne sistemleri arasında hareket etmektedir. Her sayfa kendi DOM ağacıdır ve ayrıca JavaScript nesneleri "s, dilin sözdiziminin ve özel açıklamaların nesneleridir.

DOM: yükleme, güncelleme ve değiştirme

Hem DOM düzeyinde hem de değişken oluşturmak için yapıları gerçekleştiren JavaScript dilinin kendisinde ve geliştirici tarafından yapılan açıklamalara dayalı olarak web kaynak sayfasının nesnelerini oluşturan üç ana seçenek vardır:

  • yükleniyor - ziyaretçi site sayfasına geldi;
  • güncelleme - ziyaretçi (tarayıcı düğmesi veya Ctrl-F5);
  • örneğin bir sayfa öğesini değiştirmek (AJAX, komut dosyası, olay, ...).

Her üç süreç de temelde farklıdır, ancak ilk ikisinin özelliklerini ayırt etmek özellikle önemlidir. Bir ziyaretçinin sayfayı yenilemesini engellemek zordur - bu, bir geliştiricinin akılda tutması gereken, yok edilemez bir ziyaretçi bağımlılığıdır.

Sayfada ve ötesinde gezinme, tarayıcı ziyaretlerinin geçmişinde ve düğmelerinin işlevlerinde değil, yalnızca sayfanın kendi işlevselliğinde yatmalıdır. Birçok site bu önemli şartı ilan eder, ancak ziyaretçiler geleneksel olarak bunu ihlal eder.

Sayfayı, tek tek öğesi (örneğin, AJAX) düzeyinde yeniden yüklemeden değiştirmek, dinamik sayfalar için yaygın bir çözümdür. Kural olarak, bu, sayfanın öğeleri arasında gezinmek, nesnelerini değiştirmek, ziyaretçiyle diyaloğu kontrol etmek için kullanılır.

Temel JavaScript Nesneleri

JavaScript nesne tabanlıdır. Hemen hemen tüm dil değişkenleri nesnelerdir. Geliştirici, çeşitli sözdizimlerini kullanarak kendi nesne tanımlarını formüle edebilir.

"Dize", "sayı", doğru, yanlış, boş veya tanımsız olmayan her şey bir nesnedir. Dilin sözdizimi çerçevesinde, nesneler tarafından yalnızca DOM öğelerini ve JavaScript Nesnesinin kendi açıklamalarını anlayarak bu göz ardı edilebilir.Dilin temel yapısının çoğu durumda geliştirici için önemli bir pratik değeri yoktur.

Örneğin, matematik işlevleri Math nesnesi tarafından temsil edilir. Bu, dil kavramı çerçevesinde uygundur, ancak geliştirici için sadece gerekli matematiksel işlem cephaneliğini kullanmak için uygun bir sözdizimidir.

DOM ile doğru şekilde çalışmak ve kendi nesnelerinizi doğru bir şekilde tanımlamak önemlidir. JavaScript nesne işlevlerinin sözdizimi ve bunları uygulamak için ifadeler, gerekli algoritmanın mantığını yazmanın bir şeklidir.

Dizeler, Diziler ve Nesneler

Tüm JavaScript nesneleri, "özellik" = "değer" kuralına ve bir ilişkisel dizi kavramına dayanır. En basit haliyle, nesne JavaScript, bir özellik = değer çiftleri topluluğudur. Bu durumda, "değer" her zaman bir sayı olamaz ve özellik her zaman tırnak işaretleri olmadan yazılmaz.

Özellik adlandırma aşırı kullanılmamalıdır. İdeal olarak, özellik adları yalnızca Latin karakterlerini içerdiğinde, değişkenleri adlandırma gereksinimlerini karşılayın ve dilin anahtar (ayrılmış dahil) kelimeleri değildir.

Özellik sıralaması beklenmez, ancak bir ilişkisel dizi oluştururken veya başlatırken, öğelerinin nasıl düzenlendiğini bilmek kesinlikle kabul edilebilir. Bu durumun kullanılması tavsiye edilmez, ancak akılda tutulması mümkündür.

Bir dizi özelliği başlatmak aynı zamanda şu anlama gelir:

  • bir dizi oluşturmak;
  • nesne oluşturma.

Belirli bir uygulama bağlamında, bir JavaScript nesnesini - ilişkisel bir dizi olarak ve algoritmanın başka bir yerinde - bir nesne olarak düşünebilirsiniz, ona gerekli yöntemleri atayın, öğelerinin değerlerini değiştirin.

Özellik adları ve değerleri oluşturulurken veya değiştirilirken dize biçiminde belirtilmesi gerektiğinden küçük harf gösterimi ve tırnak işaretleri kullanmanız önerilir.

Nesne özelliklerine erişme

Object.keys yapısı ile nesne özelliklerinin değerlerini alabilir ve değiştirebilirsiniz: JavaScript, tüm nesne özelliklerinin bir dizisini oluşturur. Nesneler dinamik olarak oluşturulduğunda, bu yapı çok uygundur çünkü nesnedeki tüm özelliklerin bir listesini otomatik olarak oluşturur.

Bu örnekte, iki dizinin açıklaması farklı bir şekilde yapılmıştır. Kullanımda, her iki dizi de eşdeğerdir, çünkü aynı ismin özelliklerini ve değerlerini içerirler. Döngü, ikinci dizinin tüm özelliklerini yineler ve tüm değerlerin bir dizesini oluşturur.

Nokta gösterimi veya köşeli ayraç gösterimi ile benzer bir etki elde edilebilir:

  • x1_Obj .AdSoyadı;
  • x1_Obj ["İlk Ad"].

Her iki yapı da geçerlidir ve istenen sonucu verir. Verilen örnekte, küme parantezleri "()" ile bir dizi belirtilirken, numaralandırmanın sonunda "," sembolü şeklinde bir hata yapılabilir (örnekte kırmızı daire ile işaretlenmiştir). Tarayıcılar genellikle numaralandırmadaki fazladan karakteri yok sayar, ancak yapmamak en iyisidir.

Nesne özelliklerini kaldırma

Bir nesne bir ilişkisel dizi olduğundan, işlem JavaScript silme nesnesi, geçerli nesne düzeyinde yürütülür (kalıtımla - önemlidir) ve bu nesnenin özelliklerinin koleksiyonunda görüntülenir.

Verilen örnek bağlamında aşağıdaki yapıları kullanabilirsiniz:

  • x1_Obj .NameLast'ı silin;
  • x2_Obj ["İlk Ad"] silin;

İlk yapı, birinci nesnenin ikinci öğesini kaldırır, ikinci yapı, ikinci nesnenin ilk öğesini kaldırır. Silme operatörü, prototip özellikleri üzerinde çalışmaz ve özellik silinemezse false döndürür.

Nesne özellikleri ve yöntemleri

JavaScript nesne özelliklerinin ve işlevlerinin (yöntemler) sözdizimi, dilin genel sözdizimi ve anlambilim kurallarına benzer. Aslında, bunun tersi doğrudur.

Nesne özellikleri ve yöntemleri, nesne yönelimli JavaScript paradigması aracılığıyla izin verilen bilgileri ve eylemleri açıklamanın bir çeşididir.

Bu örnek, yalnızca iki özelliği olan x3_Obj nesnesini açıklar: item ve pos. Daha sonra bir fonksiyon olarak merhaba () yöntemi eklendi. Sonuç olarak, bu açıklamanın özellik değerleri bağlamında yorumlanması, JavaScript nesne değerleri sonuç penceresinde gösterildiği gibi yapacak, yani işlevin gövdesini (1) bir değer olarak yerleştirecektir.

Hello() özelliği doğrudan çağrıldığında bir yöntem (fonksiyon) olarak yorumlanır ve sonuç (2) bu yöntemin kodunun yürütülmesi olacaktır.

Bir nesnede this anahtar sözcüğü

Bir nesnenin özellik alanında yönlendirmek için, geliştirici this anahtar sözcüğünü kullanabilir ve değerlerini almak veya değiştirmek için bu anahtar sözcüğü kullanarak tanımladığı özelliklere başvurabilir.

Bu, yalnızca kurucu gövdeli bir nesneyi tanımlamanın yalnızca başlangıcıdır. Bu örnek, bir tanımlama bilgisi nesnesini açıklar. Nesne, sayfa yapı ile yüklendiğinde başlatılır:

  • var oCookie = new scCookies (cOwnerCode);
  • oÇerez .Init();

Bu örnekte, cOwnerCode benzersiz bir ziyaretçi kimliğidir. Değilse, oCookie nesnesinin yapıcısında yeni kod oluşturulacaktır. Bu nesnenin geliştiricisinin ziyaretçinin yetkilendirmesiyle ne anlama geldiği önemli değildir, bu anahtar kelimenin burada nesnenin yöntemlerini tanımlamak ve bunları nesnenin diğer yöntemlerinden çağırmak için nasıl kullanıldığı önemlidir:

  • bu .GetCookie = fonksiyon (cName) (...);
  • bu .SetCookie = fonksiyon (cName, cValue) (...).

Nesnenin bir tanımlama bilgisini adına göre okuma ve belirli bir adla tanımlama bilgisinin değerini yazma yöntemleri bu şekilde açıklanır.

  • bu .GetCookie ("cOwner");
  • bu .SetCookie ("cOwner", cOwner);

Yani kullanılırlar, eğer ilk inşaat sonucunda değer sunulmayacaksa, ikinci inşaat onu ayarlar.

Bir çerez nesnesi örneği

Nesneler ve bir tarayıcı ortamında çalışan bir dilin nesne yönelimli paradigması tartışılabilir.Bu ilginçtir, ancak gerçeklik teori değil pratiktir.Bir sayfanın DOM'sine hizmet etmek, nesneleri işlemek ve nesne sistemlerinde gezinmek için bir araç takımı sağlamak, güçlü bir nokta JavaScript.

Nesne yönelimli uygulamada başka bir şey önemlidir. Hemen hemen tüm web kaynaklarında tanımlama bilgileriyle çalışmak, bazı şeylerin sırasına göredir. Bunu bir nesne biçiminde uygulamak harika bir fikir. Bu bağlamda, nesnenin başlatılması sayfanın açıldığı anda gerçekleşir: sayfa yüklenir = tanımlama bilgisi nesnesi var ve her şeyi okudu ve neyin yaratılmadığını okudu.

Sayfa ile çalışma sürecinde ziyaretçi belirli eylemleri gerçekleştirir ve tarayıcının çerezleri değiştirmesi veya oluşturması gerekir. Bunu yapan (yukarıda özetlenen) iki nesne yöntemi vardır.

Aslında, tanımlama bilgisi nesnesi, tarayıcı DOM'u oluşturduktan ve JavaScript nesne sistemine yeni işlevler ekledikten hemen sonra gerçekleşir: tanımlama bilgisini okuyun ve oluşturun (değiştirin).

Bu basit örnekte, yalnızca kendi özelliklerine ve işlevlerine (yöntemlere) sahip gerçek nesneler oluşturma prosedürü olarak kabul edilir. Her nesne işini yapar ve genel algoritmaya katılmaz, diğer nesnelerin verilerini veya genel ad alanını değiştirmez.

Bu yaklaşımla geliştirici, çözülmekte olan sorunu tanımlamak ve sürdürmek için yeterli benzersiz nesnelerden oluşan bir sistemin oluşturulmasını sağlar.

Sayfa ve Nesne Olayları

DOM ve JavaScript'in işleyişinin önemli bir unsuru: nesne olayı "s - işleyicisindeki bir olay hakkında bilgi almanızı sağlar. Sayfanın hemen hemen her öğesine bir veya daha fazla olay için kendi işleyicisi atanabilir.

Aslında, bir JavaScript geliştiricisi büyük bir kod "parçası" oluşturmaz, ancak birçok işlev, nesne, veri yapısı açıklaması oluşturur ve belirli sayfa öğelerine olay işleyicileri atar.

Nesne olayı, işleyiciye neden olan olay ve bu işleyicinin bu olaya yeterli bir yanıt verme yeteneği hakkındaki bilgilerdir. Her olay sadece isim ve meydana geldiği yerde değil, aynı zamanda diğer birçok parametrede de farklılık gösterir.

Özellikle, klavye olayları bir parametre setidir, fare olayları tamamen farklı bir veri aralığıdır ve AJAX aracılığıyla sunucu yanıtı tamamen geliştiricinin kendisi tarafından planlanır.

Her özel durumda, sayfada meydana gelebilecek olayların resmi, dahil edilen bir dizi işleyiciye dönüştürülür; belirli bir dizi olayı işlemek için öngörülen seçeneklerin dışında, sayfa herhangi bir işlem yapmaz.

Nesne oluşturma ve çalıştırma

Tarayıcı, ziyaretçi tarafından belirtilen web kaynağının adresi olan URI'yi, bu web kaynağının sayfa nesneleri sistemi olan bir DOM ağacına "dönüştürür". Ziyaretçi sayfadaki bağlantılar arasında hareket ettiğinde, tarayıcı diğer sayfaların karşılık gelen ağaçlarına gider.

Bu durum, geliştiricinin, ziyaretçinin davranışına yeterince yanıt veren bir web kaynağının temeli olarak kendi nesne sistemini oluşturmasına olanak tanır. Genel işlevselliği seçersek, örneğin:

  • çerezlerle çalışın;
  • veri alma / iletme (AJAX);
  • açılır ipuçları;
  • dahili mesajlar (site sohbeti);
  • diğer görevler;

bir kez oluşturulduktan sonra, nesne sistemleri diğer siteleri geliştirmek için kullanılabilir. Bu, nesne yaklaşımının, sayfanın işleyişini ve olaylara tepkiyi sağlayan tarayıcı dili olarak JavaScript'in olağan kullanımına göre önemli bir avantajıdır.

Nesneler, ayrı dosyalar olarak biçimlendirilebilen ve daha sonra kullanılabilen eksiksiz bileşenlerdir. Bu yaklaşımın karakteristik bir özelliği, güncellenmiş, geliştirilmiş bir nesne önceki bir geliştirmede kullanılabildiğinde, siteyi değiştirmeden işlevselliğini otomatik olarak güncelleyerek geri bildirim olasılığıdır.

JavaScript nesneleri

önceki JavaScript dersleri String, Date, Array ve diğerleri gibi birkaç yerleşik nesne olduğunu gördünüz. Bu yerleşik nesnelere ek olarak, kendinizinkini de oluşturabilirsiniz.

Bir nesne, bir dizi özellik ve yönteme sahip özel bir veri türüdür.

Bunu bir örnekle açıklayalım: Kişi bir nesnedir. Özellikler, bir nesneyle ilişkili değerlerdir. Kişilik özellikleri arasında isim, boy, kilo, yaş, ten rengi, göz rengi vb. Tüm kişiler bu özelliklere sahiptir ancak bu özelliklerin değerleri kişiden kişiye farklılık gösterecektir. Nesnelerin de yöntemleri vardır. Metotlar, nesneler üzerinde gerçekleştirilebilen eylemlerdir. Kişinin yöntemleri arasında yemek yemek () yemek, uyumak () uyumak, çalışmak () çalışmak, oynamak () oynamak vb. sayılabilir.

Özellikler

Bir nesnenin özelliğine erişmek için sözdizimi şöyledir:

Yukarıdaki kod aşağıdaki çıktıyı üretecektir:

Yorum Yap: Yönteme iletilen parametreler kıvrık parantezler içine alınır.

Bir personObj nesnesinin uyku () yöntemini çağırmaya bir örnek:

alternatif sözdizimi (nesne değişmezlerini kullanarak):

2. Bir nesne oluşturucu oluşturma

Nesneleri başlatan bir fonksiyon oluşturalım:

işlev kişi (ad, soyad, yaş, göz rengi)
{
this.ad = ad;
this.lastname = soyad;
this.age = yaş;
this.eyecolor = göz rengi;
}

Fonksiyonun içinde, this.PropertyName yapısını kullanarak özelliklere değerler atamanız gerekir. Bu sözdiziminin nedeni, aynı anda bir nesnenin (kişinin) birden fazla örneğini kullanacak olmanızdır (ve hangi nesneyle uğraştığınızın açık olması gerekir). Bu nedenle, "bu" kelimesi, özelliklerini yapıcıda başlattığınız belirli bir geçerli nesneyi ifade eder.

Nesnenin yapıcısını yazdıktan sonra, nesnenin yeni örneklerini oluşturabilirsiniz, örneğin:

Yöntemlerin yalnızca nesnelere bağlı işlevler olduğunu unutmayın. Ardından, newlastname() fonksiyonunun gövdesini yazmalıyız.