JavaScript’teki kalıplar ve en iyi uygulamalar: tür kontrolleri



  1. JavaScript’teki kalıplar ve en iyi uygulamalar: tür kontrolleri

Son blog yazılarımdan birinde, JavaScript’te tip denetiminin sorunsuz olmadığından bahsetmiştim. arasındaki fark neydi? biraz Ve örneği? Ve her iki operatör de gerçekten düşündüğünüz gibi çalışıyor mu? JavaScript geliştiricilerinin er ya da geç dikkate alması gereken sorular. Bugün yarından daha iyi.


JavaScript, örneğin Java’da olduğu gibi herhangi bir katı yazmayı bilmez, yani veri türü, değişken bildiriminde veya nesne işlevlerinin veya yöntemlerinin imzasında açıkça belirtilmez. Prensip olarak, herhangi bir değer (herhangi bir veri türünden) herhangi bir değişkene atanabilir ve herhangi bir argüman (herhangi bir veri türünden) herhangi bir işleve iletilebilir. Bu kamu malı olmalıdır.

Beklenenden daha az


Bazen bir değişkenin türünü belirleyebilmek istersiniz. En yakın seçenek eski gibi görünüyor biraz– en azından adına inanıyorsanız – bir değişkenin türünü belirleyen operatör. Ancak aklınızda bulundurmanız gereken şey: JavaScript pek çok farklı türü bilmez, toplamda yedi tane vardır: Boolean, Number, String, Null, Undefined, Symbol ve Object. Bu kadar.

Bu yüzden şaşırtıcı değil birazOperatör, diziler için olduğu kadar veri nesneleri veya düzenli ifadeler için de “nesne” döndürür. Ancak biraz daha garip olan şey: “null” değeri için operatör aynı zamanda “object” değerini de döndürür. İkinci düzensizlik: işlevler için (bunlar JavaScript’te de nesnelerdir), operatör “işlev” değerini döndürür.

console.log(typeof {}); // object
console.log(typeof function () {}); // function
console.log(typeof []); // object
console.log(typeof 2); // number
console.log(typeof ''); // string
console.log(typeof true); // boolean
console.log(typeof new Date()); // object
console.log(typeof /tests/i); // object
console.log(typeof null); // object
console.log(typeof undefined); // undefined
console.log(typeof Symbol('B')); // symbol

Özet olarak, bu nedenle ifade edilebilir ki, biraz-operator yalnızca ilkel veri türleri, genel olarak nesneler ve genel olarak işlevler arasında ayrım yapmak istiyorsanız uygundur. Öte yandan, bir değişkenin ne tür bir nesneye sahip olduğunu bilmek istiyorsanız, yani bir nesne örneğinin yaratıldığı sınıfı veya yapıcı işlevi belirlemek istiyorsanız uygun değildir.

Örnek şey



Bir değişkenin ne tür bir nesne olduğunu daha kesin olarak ayırt etmek için, biraz– Operatör artık yok. İşte vaatler örneği-Operatör çözüm.

'use strict';
class Person {
constructor(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
}
class Employee extends Person {
constructor(firstName, lastName, id) {
super(firstName, lastName);
this.id = id;
}
}
let max = new Person('Max', 'Mustermann');
console.log(max instanceof Person); // true
console.log(max instanceof Employee); // false
let moritz = new Employee('Moritz', 'Mustermann', 4711);
console.log(moritz instanceof Person); // true
console.log(moritz instanceof Employee); // true

Ama neyi kontrol ediyor? örneği– operatör tam olarak? Bunu anlamak için şunları hatırlamak gerekir:

  1. JavaScript’te her nesne özelliktedir inşaatçı nesnenin oluşturulduğu işlev (yapıcı).
  2. the prototipBu yapıcı işlevin özelliği, sırayla prototipi, yani yeni nesne örneklerinin oluşturulduğu temel nesneyi içerir.
  3. Her nesnenin bir prototipi vardır (temel nesne hariç) nesneler ve prototipi açıkça referans verilen nesneler sıfır Kuruldu). Bu sözde prototip zinciri ile sonuçlanır.
the örneğiOperatör şimdi dosyadaki prototipin olup olmadığını kontrol eder. prototipYapıcı işlevin özelliği, prototip zincirinde saklanır:

console.log(moritz.constructor); // (1) [Function: Employee]
console.log(moritz.constructor.prototype); // (2) Employee {}
console.log(moritz.__proto__); // (3) Employee {}
console.log(moritz.__proto__.__proto__); // (3) Person {}
console.log(moritz instanceof Person); // true

Burada dikkat edilmesi gereken küçük bir engel: örneği-operatör, ilkel veri türleriyle çalışmaz veya yalnızca koşullu olarak çalışır (örn. sıfır Ve Tanımsız), aşağıdaki listede gösterildiği gibi:

console.log(4711 instanceof Number); // false, nicht richtig
console.log(true instanceof Boolean); // false, nicht richtig
console.log("Max" instanceof String); // false, nicht richtig
console.log(null instanceof String); // false, richtig
console.log(undefined instanceof String); // false, richtig

Bunun dışında şu soru ortaya çıkıyor: Bunu yapabilir misin? örneği– Operatör dikkatsizce bir değişkenin (nesnenin) türünü belirlemek için mi? Ne yazık ki cevap hayır, çünkü az önce gösterilen küçük tökezlemeye ek olarak oldukça büyük bir engel var. Ve eğer yaparsan örneği-farklı bağlamlarla ilgili operatör, örn. tarayıcı içinde farklı çerçevelerde veya – daha yakın zamanda – Node.js’deki modülleri kullanırken.

Node.js ile kullanırken dikkatli olun


Sorunu anlamak için, önce Node.js veya NPM paket yöneticisinin modülleri (veya paketleri) nasıl ele aldığının farkına varılmalıdır. Prensip olarak, npm ile başlangıçta modülleri global veya yerel olarak kurmak mümkündür.

İlki, modüller ilgili sistemdeki diğer birçok modül tarafından kullanılıyorsa özellikle yararlıdır (klasik bir örnek, mocha test çerçevesi olabilir). İkincisi, yani yerel kurulum, esas olarak bir modülün belirli bağımlılıklarını bu modülde yerel olarak bir araya getirmek ve bu şekilde diğer modüllerle sürüm çakışmalarını önlemek için yapılır. Varsayılan olarak, modüller klasörde saklanır. düğüm_modülleri saklanır, bu nedenle mevcut modülün bağlı olduğu modüller de elbette bağımlılıklara vb. sahip olabilir.

Genel olarak, bu, dizin yapısına yansıyan bir bağımlılık ağacıyla sonuçlanır:

example-package // Hauptmodul
--> node_modules
--> package-a // Abhängigkeit des Hauptmoduls
--> package-a2 // Abhängigkeit des Submoduls package-a
--> package-b // Abhängigkeit des Hauptmoduls
--> package-b2 // Abhängigkeit des Submoduls package-b

Sorunlu – en azından örneği-Operator: Bir modül, temeldeki modül gibi bu ağaç yapısında birden çok kez göründüğünde hepsi olur. b paketi:

example-package // Hauptmodul
--> node_modules
--> package-a
--> package-b // package-b als Abhängigkeit von package-a ...
--> package-b // ... und als Abhängigkeit des Hauptmoduls.
--> package-c

Bunun neden sorunlu olduğunu anlamanın en iyi yolu, aşağıdaki şekilde yapılandırılmış basit bir örnek kullanmaktır:

example
--> node_modules
--> module-functions
--> index.js
--> package.json
--> module-persons
--> index.js
--> package.json
--> index.js

the index.jsform için dosya insan modülü Şuna benziyor:

'use strict';
module.exports = class Person {
constructor(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
}


modül modül fonksiyonları Bu forma şu şekilde erişin:

'use strict';
const Person = require('module-persons');
module.exports = function isPerson(value) {
console.log('Instanz von Person: ' + value instanceof Person);
}


Son olarak, içeriği index.js-Arşiv misalönceki iki modülü kullanan modül:

'use strict';
const Person = require('module-persons');
const isPerson = require('module-functions');
let max = new Person('Max', 'Mustermann');
isPerson(max);


Bu nedenle yapı nispeten basittir: dosya index.js (şeklinde misal) dosyayı içe aktar kişisınıf ve isPerson()işlevinin bir örneğini oluşturun kişi ve işleve iletir. Bu işlev içinde sırasıyla (yukarıya bakın) örneği– Emlak incelemesi. modül misal her ikisi de insan modülü yanı sıra modül fonksiyonları çalışan formu modül fonksiyonları dönüş insan modülü.

Programı çalıştırırsanız (komut aracılığıyla nodeindex.js) yürütüldüğünde, tam olarak beklediğiniz gibi “Instance of Person: true” çıktısını alırsınız. Ancak, formu kullanırsanız durum farklıdır. insan modülü içinde düğüm_modüllerimodülün altındaki dizin modül fonksiyonları kopyalandı (ve bu nedenle neredeyse npm kurulumu dosyadaki bağımlılıkları da içeren simüle düğüm_modülleriilgili modülün dizini).

example
--> node_modules
--> module-functions
--> node_modules
--> module-persons
--> index.js
--> package.json
--> module-persons
--> index.js
--> package.json
--> index.js

Programı yeniden başlatırsanız program çıktısı “Instance of Person: false” olur. nedeni: kişiörneği oluşturmak için kullanılan sınıf (ve dolayısıyla temel prototipler) Maksimum kullanılanın, formda dahili olarak kullanılandan farklı olması modül fonksiyonları (ve böylece fonksiyonun içinde isPerson()) kullanıldı. Prototip karşılaştırması ancak başarısız olabilir.

Şimdi bunun anlamı örneği– operatör düzgün çalışmıyor mu? Hayır, bu, örneğin dahili olarak, yapısal olarak farklı olan iki farklı nesne hiyerarşisinin kullanıldığı anlamına gelmez. ayrıca onlar ama değil aynı nesne hiyerarşisini temsil eder. Bu anlamda yapar örneği-operatör zaten ne yapması gerektiğini. instanceof operatörü, bir nesnenin bir sınıfın örneği olup olmadığını belirlemenin güvenilir bir yolu mudur? Bir bağlam içinde (veya Node.js durumunda: bir modül), evet, ancak ilgili sınıfı birden çok bağlamda kullandığınız anda, örneği– Operatör mümkün olduğunca kaçının.

Devam ediyor…


Bir nesnenin bir sınıfın örneği olup olmadığını öğrenmek için hangi alternatifler vardır? örneği-operatör bunu her zaman yapamaz mı? Cevap bu serinin bir sonraki makalesinde.


()



Haberin Sonu
 
Üst