SORU
30 AĞUSTOS 2013, Cuma


nasıl javascript Nesne kullanmak.defineProperty

Etrafında Object.defineProperty yöntemini nasıl aradım, ama hiçbir şey için iyi bir yer bulamadı.

Biri bana this snippet of code verdi:

Object.defineProperty(player, "health", {
    get: function () {
        return 10   ( player.level * 15 );
    }
})

Ama anlamıyorum. Esas olarak, get giremiyorum nedir (cinas tasarlamak). Nasıl çalışır?

CEVAP
1 EYLÜL 2013, Pazar


** 26, hadi al sorduğun için adım adım. Biraz daha uzun ama sen bunu yazarken geçirdim çok daha fazla zaman kazandırabilir:

ÖzellikOOP bir özelliği istemci kod temiz ayrılması için tasarlanmıştır. Bazı örneğin, e-shop bu gibi nesneler olabilir:

function Product(name,price) {
  this.name = name;
  this.price = price;
  this.discount = 0;
}

var sneakers = new Product("Sneakers",20); // {name:"Sneakers",price:20,discount:0}
var tshirt = new Product("T-shirt",10);  // {name:"T-shirt",price:10,discount:0}

Müşteri kodunuzu (e-shop), Ürün için indirimler ekleyebilirsiniz:

function badProduct(obj) { obj.discount = 20; ... }
function generalDiscount(obj) { obj.discount = 10; ... }
function distributorDiscount(obj) { obj.discount = 15; ... }

Daha sonra, e-dükkan sahibi indirim 80'i daha büyük olamaz fark olabilir. Şimdi istemci kodu HER yer bulun ve bir satır eklemek gerekir

if(obj.discount>80) obj.discount = 80;

E-dükkan sahibi daha fazla stratejisini değiştirmek gibi olabilir< . em ^"müşteri satıcı ise, Maksimum indirim 'ı olabilir". Ve birden fazla yerde değiştirmek daha yapman lazım artı strateji değiştirdi zaman bu satırları değiştirmek için hatırlamanız gerekir. Bu kötü bir tasarım. Bu yüzdensarmaOOP temel ilkesidir. Eğer yapıcı böyle olsaydı:

function Product(name,price) {
  var _name=name, _price=price, _discount=0;
  this.getName = function() { return _name; }
  this.setName = function(value) { _name = value; }
  this.getPrice = function() { return _price; }
  this.setPrice = function(value) { _price = value; }
  this.getDiscount = function() { return _discount; }
  this.setDiscount = function(value) { _discount = value; } 
}

O zaman sadece getDiscount değiştirebilirsiniz (erişimcive setDiscount (çevirici) yöntemleri. Sorun üyelerin en yaygın değişkenler gibi, sadece indirim burada özel bir bakıma ihtiyacı vardır davranmaları. Ama iyi bir tasarım kodu genişletilebilir tutmak için her veri üyesi sarma gerektirir. Hiçbir şey yapmayan bir sürü kod eklemem gerekiyor. Bu da kötü tasarım, bir birdemirbaş antipattern. Bazen sadece yöntemleri alanlar daha sonra yeniden edemezsin (eshop kodu fazla büyümesine veya üçüncü taraf kod eski sürümüne bağlı olabilir), demirbaş daha az kötü işte. Ama yine de kötü. Birçok dile getirilmiştir. Orijinal kodu tutmak, get set blokları ile bir mülk haline indirim üyesi dönüştürme:

function Product(name,price) {
  this.name = name;
  this.price = price;
//this.discount = 0; // <- remove this line and refactor with the code below
  var _discount; // private member
  Object.defineProperty(this,"discount",{  // this answers the comment (pun intended)
    get: function() { return _discount; },
    set: function(value) { _discount = value; if(_discount>80) _discount = 80; }
  });
}

// the client code
var sneakers = new Product("Sneakers",20);
sneakers.discount = 50; // 50, setter is called
sneakers.discount = 20; // 70, setter is called
sneakers.discount = 20; // 80, not 90!
alert(sneakers.discount); // getter is called

Not son bir tek çizgi: doğru indirim değeri sorumluluğunu istemci kodundan taşındı (e-shop tanım) ürün tanımı oldu. Ürün veri üyeleri tutarlı tutmak için sorumludur. Eğer kodu düşüncelerimizi aynı şekilde çalışır eğer iyi bir tasarım (kabaca) dedi.

Özellikleri hakkında çok fazla. Ama javascript farklı Nesne yönelimli programlama dili C saf gibi# kodları ve özellikleri farklı:

C#kamu alanları kodunuz separatedly kullanılan olabilir Auto-Implemented Properties olarak kodlanmış olmalı breaking change, derlenmiş bir istemci özelliklerine alanları dönüştürüyor.

Javascriptstandart özellikler (alıcı ve ayarlayıcı ile veri üye yukarıda açıklanan) tarafından tanımlananerişimci tanımlayıcısı(bağlantı Sorunuzun içinde var). Sadece, kullanabilirsinizveri tanımlayıcı(bu kadar mı yani kullanamıyorumdeğerveayarlayınaynı özellik):

  • erişimci tanımlayıcısı= set (örnek yukarıda)
    • olsunbir işlevi olmalı; dönüş özelliği okuma kullanılır; eğer belirtilirse, varsayılantanımsıztanımsız döndüren bir fonksiyon gibi davranır
    • ayarlayınbir işlevi olmalı; parametre özelliği için bir değer atayarak OLUŞTURDUĞU ile doldurulur; eğer belirtilirse, varsayılantanımsızboş bir fonksiyon gibi davranır
  • veri tanımlayıcı= değer yazılabilir (örnek aşağıya bakınız)
    • değervarsayılantanımsız; eğeryazılabilir,yapılandırılabilirvesayısız(aşağıya bakınız) doğruysa, bu özellik, sıradan bir veri alanı gibi davranır
    • yazılabilir- varsayılanyanlışdeğilsedoğruözelliği yalnızca okuma , yazma girişimi hatasız*! göz ardı edilir

Her iki tanımlayıcıları bu üyeler olabilir:

  • yapılandırılabilir- varsayılanyanlış; eğer bu doğru değilse, özellik silinemez; silme girişimi hata* olmadan göz ardı edilir!
  • sayısız- varsayılanyanlış; true ise, for(var i in theObject); false ise, yinelenen olmayacak içinde yinelenen olacak, ama genel olarak hala erişilebilir

bu durumda strict mode - JS sürece * try-catch block yakalanmış değilse eğer data ile yürütme durur

Bu ayarları okumak için kullanın Object.getOwnPropertyDescriptor().

Yaşayarak Öğren:

var o = {};
Object.defineProperty(o,"test",{
  value: "a",
  configurable: true
});
console.log(Object.getOwnPropertyDescriptor(o,"test")); // check the settings    

for(var i in o) console.log(o[i]); // nothing, o.test is not enumerable
console.log(o.test); // "a"
o.test = "b"; // o.test is still "a", (is not writable, no error)
delete(o.test); // bye bye, o.test (was configurable)
o.test = "b"; // o.test is "b"
for(var i in o) console.log(o[i]); // "b", default fields are enumerable

Eğer müşteri bu tür hileler kodu izin isteyen yok eğer doğru değilse, doğumdan üç düzeyleri ile nesne kısıtlayabilirsiniz:

  • Object.preventExtensions(yourObject)yeni özellikler eklenmesini engelleryourObject. KullanınyourObject.() genişletilebilireğer yöntemi nesne üzerinde kullanılıp kullanılmadığını kontrol etmek. Önlenmesishalow(aşağıda okuyun).
  • Object.seal(yourObject)yukarıda özellikleri kaldırılamaz aynı (etkin tüm özelliklere configurable: false ayarlar). KullanınyourObject.() isSealedbu algılamaya nesne üzerinde bulunmaktadır. Mührüshalow(aşağıda okuyun).
  • Object.freeze(yourObject)yukarıda özellikleri ve değiştirilemez olarak aynı (etkin veri tanımlayıcı ile tüm özellikleri writable: false ayarlar). Pasör (varsa) etkilenmez. Dondurmashalow: eğer bu özellik Nesne özellikleri dondurulmuş DEĞİL demektir (Eğer isterseniz, şöyle bir şey yapmalıdır "deep freeze", 34**) benzer. KullanınyourObject.() isFrozenbunu tespit etmek.

Eğer sadece birkaç satır bir eğlence yazarsanız bu konuda rahatsız gerekmez. Ama eğer bir oyun kodu istiyorsan bağlantılı soru da belirttiğim gibi, gerçekten iyi tasarımına dikkat etmelisiniz. Hakkında bir şey google için deneyinantipatternsvekod koku. Senin gibi durumları önlemek için yardımcı olacaktır"Oh, tamamen benim kodu tekrar tekrar yazmak istiyorum!"eğer çok fazla kod isterseniz size umutsuzluk ay kaydedebilirsiniz. İyi şanslar.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Joshua Bane

    Joshua Bane

    24 Temmuz 2007
  • Louis C.K.

    Louis C.K.

    18 HAZİRAN 2006
  • NicoleGrippo

    NicoleGrippo

    14 Kasım 2006