Dondurma ve mühür arasındaki fark


164

JavaScript yöntemlerini yeni duydum freezeve sealherhangi bir Nesneyi değişmez hale getirmek için kullanılabilir.

İşte nasıl kullanılacağına dair kısa bir örnek:

var o1 = {}, o2 = {};
Object.freeze(o2);

o1["a"] = "worked";
o2["a"] = "worked";

alert(o1["a"]);   //prints "worked"
alert(o2["a"]);   //prints "undefined"

Arasındaki fark nedir freezeve seal? Performansı artırabilirler mi?


6
Bu soruya bakan herkese sadece bir not, kabul edilen cevap aslında yanlış. @ tungd'un cevabı doğrudur.
Bjorn

2
Başka bir not, orada da Object.preventExtensionsek olarak Object.sealve Object.freeze. Object.preventExtensionsyeni nesnelerin bir nesneye eklenmesini önler. Genişletilebilirliği kapalı olan nesnelerdeki özelliklerin değerlerini silebilir, yapılandırabilir ve değiştirebilirsiniz Object.preventExtensions.
Bjorn

Yanıtlar:


193

Object.seal

  • Kapalı nesneye özellik eklenmesini ve / veya çıkarılmasını önler; kullanmak deleteyanlış döndürür
  • Mevcut her bir özelliği yapılandırılamaz yapar : 'veri tanımlayıcılarından' 'erişim tanımlayıcılarına' dönüştürülemez (ve tersi) ve hiçbir erişim tanımlayıcılarının hiçbir özelliği değiştirilemez (oysa veri tanımlayıcıları writableniteliklerini değiştirebilir ve onların valuenitelik ise writeable) doğrudur.
  • Bir atabilir TypeError(en yaygın olarak sızdırmaz nesnenin kendisi değerini değiştirmek için çalışırken katı modda )

Object.freeze

  • Tam olarak ne işe yarar Object.seal, artı:
  • Bu modifiye engelleyen herhangi bir varolan özellikleri

İkisi de 'derin' / torun nesnelerini etkilemez. Örneğin, objdondurulmuşsa, obj.elyeniden atanamaz, ancak değeri obj.eldeğiştirilebilir, örneğin obj.el.iddeğiştirilebilir.


Verim:

Bir nesneyi mühürlemek veya dondurmak, tarayıcıya bağlı olarak numaralandırma hızını etkileyebilir:

  • Firefox: numaralandırma performansı etkilenmez
  • IE: numaralandırma performansının etkisi ihmal edilebilir
  • Krom: mühürlü veya donmuş nesnelerle numaralandırma performansı daha hızlı
  • Safari: mühürlü veya donmuş nesneler% 92 daha yavaş numaralandırır (2014 itibariyle)

Testler: Mühürlü nesneler , Dondurulmuş nesneler .


2
Neden bu yöntemleri kullandığımızdan bahsedebilir misiniz? Sadece yapabileceğimiz için mi?
Alan Dong

3
Gelecekte bir kütüphane / çerçeve geliştirirken çok fazla kullanılacaklarını (doğru şekilde optimize edilmişlerse) düşünüyorum. Kullanıcının (istemeden bile olsa) kodunuzu kırmasını önlemenize izin verir (ve yanıtta belirtildiği gibi, optimizasyonlar büyük hız geliştirmelerine yol açmalıdır). Ama bu saf spekülasyon :)
Niccolò Campolungo

2
Bu cevabın birçok olgusal hatası var. İlk olarak, sealaynı zamanda mevcut yapar özellikleri olmayan yapılandırılabilir, bkz jsfiddle.net/btipling/6m743whn Numara 2, sen, o mühürlü nesne üzerinde varolan özelliklerin değerlerini değiştirmek hala düzenlemek olduğunu olabilir.
Bjorn

8
FWIW, dondurulmuş ve mühürlü nesneler artık Chrome Canary v43.0.2317.0'daki donmamış ve mühürlenmemiş muadillerinden daha hızlı.
llambda

2
@AlanDong Gelmek için biraz geç, ama işte bir nesneyi kilitlemek istiyoruz. JavaScript'in özelliklerinden biri, istediğiniz zaman bir özellik ekleyebilmenizdir; bunu yanlışlıkla yanlış yazarak da yapabilirsiniz . Öğrencilerimin çoğu bir olay işleyicisi olarak adlandırılan eklemeye çalıştık onClickya onlickve bu işe yaramıyor neden merak etti. JavaScript hata verirse, bu yanlış yapmak için daha az şeydir. İkincisi, bu, bir nesneyi değişiklikleri önleyen sabit özellikler uygulamanızı sağlar. Bu özellikle nesne yöntemlerinde yararlıdır.
Manngo

119

Bu 3 yöntemi karşılaştıran bir test projesi yazdım :

  • Object.freeze()
  • Object.seal()
  • Object.preventExtensions()

Birim testlerim CRUD vakalarını kapsar:

  • [C] yeni mülk ekle
  • [R] mevcut özelliği okudu
  • [U] mevcut özelliği değiştir
  • [D] mevcut mülkü kaldır

Sonuç:

resim açıklamasını buraya girin


2
Bu harika. UPDATE, tanımlayıcı niteliklerinin (örneğin, yapılandırılabilir, numaralandırılabilir, yazılabilir) değiştirilmesini dikkate alıyor mu?
Drenai

Her zaman DOM nesnelerinin mühürlenmesi gerektiğini düşünüyorum (tabii ki çoklu dolgular sonra). Bu yazım hatalarının önlenmesine yardımcı olur.
Manngo

@ Manngo DOM nesnelerinizi mühürleyebilirsiniz. Sadece bir DEBUGMODEdeğişken oluşturun ve bunu ayarlayın true. Sonra yap if (DEBUGMODE) { ... }. Bölümünde, ...tüm DOM nesnelerinin her zaman mühürlendiğinden emin olmak için işlevselliğinizi koyun. Eğer web sayfası komut, değişiklik dağıtmak için hazır olduklarında Sonra DEBUGMODEüzere false, kapatma derleyici aracılığıyla komut dosyasını çalıştırın ve dağıtın. Bu kadar basit.
Jack Giffin

@JackGiffin Yorum için teşekkürler. Sadece bunun her zaman iyi bir fikir olacağını düşündüğümü söylüyordum. Sonunda böyle bir şey yazıp element.onlick=somethingsinirlenmeye çalışan bir sürü öğrencim var, çünkü çalışmıyor, ancak teknik olarak bir hata değil.
Manngo

2
@ Yalnız O zaman CRUD hecelemezdi. RUDE gibi bir yere razı
olmalısın

84

Bunları her zaman MDN'de görebilirsiniz. Kısacası:

  • Dondur : nesneyi değiştirilemez hale getirir, yani nesne olmadıkça tanımlı özellikte izin verilmez.
  • Mühür : özelliklerin eklenmesini önler, ancak tanımlanan özellikler yine de değiştirilebilir.

1
Object.seal()ayrıca prototip özelliklerini donduruyor gibi görünüyor : \
K ..

10

Object.freeze()dondurulmuş bir nesne oluşturur, yani mevcut bir nesneyi alır ve temelde Object.seal()bu nesneyi çağırır , ancak writable:falsedeğerlerinin değiştirilememesi için tüm “veri erişimcisi” özelliklerini olarak işaretler . - Kyle Simpson, JS'yi Bilmiyorsun - This & Object Prototypes


4

ECMAScript 5'te Freeze ve Seal arasındaki farklara bakıyordum ve farklılıkları açıklığa kavuşturmak için bir senaryo oluşturdum. Frozen, veri ve yapıyı içeren değişmez bir nesne yaratır. Mühür, adlandırılan arayüzlerde değişiklik yapılmasını önler - ekleme, silme yok - ancak nesneyi değiştirebilir ve arabiriminin anlamını yeniden tanımlayabilirsiniz.

function run()
{
    var myObject = function() 
    { 
        this.test = "testing"; 
    }

    //***************************SETUP****************************

    var frozenObj = new myObject();
    var sealedObj = new myObject();

    var allFrozen = Object.freeze(frozenObj);
    var allSealed = Object.seal(sealedObj);
    alert("frozenObj of myObject type now frozen - Property test= " + frozenObj.test);
    alert("sealedObj of myObject type now frozen - Property test= " + sealedObj.test);

    //***************************FROZEN****************************

    frozenObj.addedProperty = "added Property"; //ignores add
    alert("Frozen addedProperty= " + frozenObj.addedProperty);
    delete frozenObj.test; //ignores delete
    alert("Frozen so deleted property still exists= " + frozenObj.test);
    frozenObj.test = "Howdy"; //ignores update
    alert("Frozen ignores update to value= " + frozenObj.test);
    frozenObj.test = function() { return "function"; } //ignores
    alert("Frozen so ignores redefinition of value= " + frozenObj.test);

    alert("Is frozen " + Object.isFrozen(frozenObj));
    alert("Is sealed " + Object.isSealed(frozenObj));
    alert("Is extensible " + Object.isExtensible(frozenObj));

    alert("Cannot unfreeze");
    alert("result of freeze same as the original object: " + (frozenObj === allFrozen).toString());

    alert("Date.now = " + Date.now());

    //***************************SEALED****************************

    sealedObj.addedProperty = "added Property"; //ignores add
    alert("Sealed addedProperty= " + sealedObj.addedProperty);
    sealedObj.test = "Howdy"; //allows update
    alert("Sealed allows update to value unlike frozen= " + sealedObj.test);
    sealedObj.test = function() { return "function"; } //allows
    alert("Sealed allows redefinition of value unlike frozen= " + sealedObj.test);
    delete sealedObj.test; //ignores delete
    alert("Sealed so deleted property still exists= " + sealedObj.test);
    alert("Is frozen " + Object.isFrozen(sealedObj));
    alert("Is sealed " + Object.isSealed(sealedObj));
    alert("Is extensible " + Object.isExtensible(sealedObj));

    alert("Cannot unseal");
    alert("result of seal same as the original object: " + (sealedObj === allSealed).toString());

    alert("Date.now = " + Date.now());
}

3

Biraz geç olabileceğimi biliyorum ama

  • Benzerlik: her ikisi de genişletilemeyen nesneler oluşturmak için kullanılır .
  • Fark: Dondurma'da yapılandırılabilir, nesnenin numaralandırılabilir ve yazılabilir nitelikleri olarak ayarlanır false. burada Mühürlü yazılabilir özellik olarak ayarlanır trueve geri kalan özellikler yanlıştır.

6
Bu tamamen doğru değil. Object.getOwnPropertyDescriptor(Object.freeze({ prop: 1 }), 'prop').enumerable=== true.
Leon Adler

2

Artık tüm nesneyi dondurmak yerine tek bir nesne özelliğini dondurulmaya zorlayabilirsiniz. Sen ile bunu başarabilirsiniz Object.definePropertyile writable: falsebir parametre olarak.

var obj = {
    "first": 1,
    "second": 2,
    "third": 3
};
Object.defineProperty(obj, "first", {
    writable: false,
    value: 99
});

Bu örnekte, obj.firstdeğeri 99 olarak kilitlenmiştir.


0

Aşağıdaki işlevleri karşılaştırmak ve bu işlevler arasındaki farkı açıklamak için basit bir tablo oluşturdum.

  • Object.freeze ()
  • Object.seal ()
  • Object.preventExtensions ()

yukarıdaki üç yöntem arasındaki farkı açıklayan tablo

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.