Objects and Inheritance

Kategori: Javascript , 05 Kasım 2019 , JanFranco


Javascript'te bu yazımla katman katman ilerleyerek object oriented (nesneye yönelik) programlamanın tüm temellerini göreceğiz:

Katman 1: Objeler

Javascript'te hemen hemen tüm objeler sözlüktür. Map de diyebiliriz. Anahtar - değer entry'si objelerdeki özelliklerdir (property). Bir özelliğin key değeri her zaman string'dir. Bir özelliğin değeri ise herhangi bir değer olabilir, fonksiyonlar da dahil olmak üzere. Eğer bir değer fonksiyonsa, o değere artık method diyeceğiz. Bir örnek yapalım:


var jane = {
    name: 'Jane',
    describe: function() {
	return 'Person named ' + this.name;
    },
};
jane adında bir obje ürettik. Bu objenin property'leri name ve describe'dır. describe bir methoddur. Bu property'leri kullanalım:


jane.name
>>
'Jane'

jane.describe
>>
[Function]

jane.unknownProperty
>>
undefined

jane.describe()
>>
'Person named Jane'
Objelere özellik (property) ekleyebiliriz, var olan bir özelliği değiştirebiliriz:


jane.name = 'Jan';
jane.describe()
>>
'Person named Jan'

jane.surname = 'Franco';

*** Özellikleri silebiliriz:

delete jane.surname
>>
true

jane.surname
>>
undefined
delete statement'ı ile sadece objenin kendi özelliklerini silebiliriz. Kalıtım ile alınan özellikler silinemez. Eğer bir özellik objenin kendi özelliği ise ve yine de silinemiyorsa false return değeri alırız:


var obj = {};

Object.defineProperty(obj, 'canBeDeleted', {
    value: 123,
    configurable: true
});

Object.defineProperty(obj, 'cannotBeDeleted', {
    value: 456,
    configurable: false
});

delete obj.cannotBeDeleted
>>
false

delete obj.doesNotExist
>>
true

delete obj.canBeDeleted
>>
true
Köşeli parantezler ile key belirterek değerlere ulaşabiliriz:


var obj = { someProperty: 'abc' };

obj['someProperty']
>>
'abc'

var obj = { myMethod: function () { return true } };
obj['myMethod']()
>>
true
Katman 2: Objeler Arası Protoype İlişkisi

Katman 2 kısaca kalıtımdan ibaret. Bir obje, başka bir objeyi miras alarak o objenin tüm özelliklerine sahip olabilir. Bunu [[Prototype]] ifadesi ile gerçekleştirelim:


var proto = {
    describe: function() {
	return 'name: ' + this.name;
    }
};

var obj = {
    [[Prototyppe]]: proto,
    name: 'obj'
};

obj.describe()
>>
'name: obj'
obj objesinde describe fonksiyonunu tanımlamadığımız halde kalıtım özelliği sayesinde bu özelliği kullanabildik. Kalıtım ile aldığımız bir özelliği, yeniden tanımlayabiliriz. Bu olaya overriding diyeceğiz. Örnek görelim:


obj.describe = function() { return 'overriden' };
obj.describe()
>>
'overriden'
obj objesinde describe() fonksiyonu kalıtım ile alınmıştı. Yani obj objesinde bu fonksiyon artık mevcuttu. Biz burada fonksiyonu yeniden tanımlayarak, fonksiyonu override ettik. Daha sonra kullandığımızda override ettiğimiz fonksiyonun çalıştığını gördük. Object.create() methodu ile prototip kullanarak obje oluşturabiliriz:


var PersonProto = {
    describe: function() {
	return 'Person named' + this.name;
    }
};

var jane = Object.create(PersonProto, {
    name: { value: 'Jane', writable: true }
});

jane.describe()
>>
'Person named Jane'
getPrototypeOf() methodu ile bir objenin, hangi objeyi miras aldığını görebiliriz. isProtoypeOf methodu ile de bir objenin herhangi bir objeden miras alıp almadığını kontrol edebiliriz:


Object.getPrototypeOf(jane) === PersonProto
>>
true

var A = {};
var B = Object.create(A);
var C = Object.create(C);

A.isProtoypeOf(C)
>>
true

C.isProtoypeOf(A)
>>
false
__proto__ özelliği ile de kalıtım yapabiliriz:


var obj = {};
obj.__proto__ = Array.prototype
Object.getPrototypeOf(obj) === Array.prototype
>>
true
Bir objenin özelliklerini listelemek için aşağıdaki for-in döngüsünü veya fonksiyonu kullanabiliriz. for-in döngüsünde numaralandırılabilir tüm özellikleri görürürüz. Fonksiyonda ise tüm özellikleri alırız:


for (<<variable>> in <<onbject>>)
    <<statement>>

function getAllPropertyNames(obj) {
    var result = [];
    while (obj) {
	Array.protoype.push.apply(result, Object.getOwnPropertyNames(obj));
	obj = Object.getPrototypeOf(obj);
    }
}
Bir özelliğin bir objede bulunup bulunmadığını kontrol edelim:


propKey in obj
>>
<<true or false>>

*** Javascript'te getter - setter methodlar aşağıdaki şekilde tanımlanır:

var obj = {
    get foo() {
	return 'getter';
    }
    set foo(value) {
	console.log('setter: ' + value);
    }
}

obj.foo = 'bla';
>>
'setter: bla';

obj.foo
>>
'getter'
Getter - setter methodlar ile bu şekilde özelliklerin değerini atayabilir veya çekebiliriz. Objeleri korumanın 3 yolu vardır: preventExtensions() methodu, seal() methodu ve freeze() methodu. prevenetExtension() methodu ile başlayalım:


var obj = { foo: 'a' };
Object.preventExtensions(obj);

obj.bar = 'b';
obj.bar
>>
undefined

delete obj.foo
>>
true
Bu method ile objeyi korumuş olduk. Koruma sayesinde yeni özellik eklenemiyor. Ancak var olan özellikler silinebiliyor. seal() methodu ile yine özellik eklemeyi kısıtlayabiliyoruz ve bunun yanında bir özelliğin configurable ayarını false yapabiliyoruz:


var obj = { foo: 'a' };

Object.getOwnPropertyDescriptor(obj, 'foo')
>>
{ value: 'a',
  writable: true,
  enumerable: true,
  enumerable: true,
  configurable: true }

Object.seal(obj)

Object.getOwnPropertyDescriptor(obj, 'foo')
>>
{ value: 'a',
  writable: true,
  enumerable: true,
  enumerable: true,
  configurable: false }
configurable false olduğunda, bir özelliğin ayarlarını artık değiştiremeyiz demektir. freeze() methodu ile tüm özelliklerin writable özelliği ve configurable özelliği false olur ve ayrıca objeye artık yeni bir özellik eklenemez:


var point = { x: 17, y: -5 };
Object.freeze(point);

point.x = 2;
point.x
>>
17

point.z = 123;
point
>>
{ x: 17, y: -5 }
Katman 3: Constructors

Constructorlar obje üretiminde görevli yapılardır. Constructor fonksiyonlar oluşturarak seri obje üretimi yapabiliriz. Öncelikle constructor kullanmadan obje üretmeyi deneyelim:


var PersonProto = {
    describe: function () {
	return 'Person named '+this.name;
    }
};

var jane = {
    [[Prototype]]: PersonProto,
    name: 'Jane'
};

var tarzan = {
    [[Prototype]]: PersonProto,
    name: 'Tarzan'
};
Şimdi Constructor fonksiyonlar ile obje üretelim:


function Person(name) {
    this.name = name;
}

Person.prototype.describe = function () {
    return 'Person named ' + this.name;
}

var jane = new Person('Jane');
jane.describe()
>>
'Person named Jane'
instanceOf operatörü ile bir objenin belirli bir Constructor'dan oluşturulup olmadığını kontrol edebiliriz:


value instanceOf Constr

{} instanceOf Object
>>
true


Sonraki Yazı: Arrays in Javascript
Yorumlar

Henüz bir yorum bulunmuyor.
Yorum bırakın