Soru Bir özelliği bir JavaScript nesnesinden nasıl kaldırabilirim?


Bir nesneyi aşağıdaki gibi oluşturduğumu varsayalım:

var myObject = {
    "ircEvent": "PRIVMSG",
    "method": "newURI",
    "regex": "^http://.*"
};

Mülkün kaldırılmasının en iyi yolu nedir? regex yeni ile sonuçlanmak myObject aşağıdaki gibi?

var myObject = {
    "ircEvent": "PRIVMSG",
    "method": "newURI"
};

4910
2017-10-16 10:57


Menşei


Burada "silme" ile "undefined" ve "null" karşılaştırması yapan bir karşılaştırma ölçütü bulun jsben.ch/#/BWMiw - EscapeNetscape
developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/... - titusfx


Cevaplar:


Bunun gibi:

delete myObject.regex;
// or,
delete myObject['regex'];
// or,
var prop = "regex";
delete myObject[prop];

gösteri

var myObject = {
    "ircEvent": "PRIVMSG",
    "method": "newURI",
    "regex": "^http://.*"
};
delete myObject.regex;

console.log(myObject);

Bu konuda daha fazla okumak isteyen herkes için Yığın Taşımı kullanıcısı kangax hakkında derinlemesine bir blog yazısı yazdı delete kendi blogunda ifade, Anlamayı anlama. Şiddetle tavsiye edilir.


6839
2017-10-16 10:58



İşaretli, ayrıca "myJSONObject ['regex'];" ile çalışır; " Görmek: developer.mozilla.org/en/Core_JavaScript_1.5_Reference/... - johnstok
Yukarıdaki "anlaşmayı anlama" bağlantısındaki gözlemlerden bir tanesi, bir değişkeni zorunlu olarak silemezsiniz, ancak sadece nesne özelliklerini silmemenizdir, bu nedenle bir nesne özelliğini "referans olarak" silemezsiniz - var değer = obj [ ] prop '; değeri sil // çalışmıyor - George Jempty
Yani aslında onu silmiyor? Sadece tanımsız hale geliyor, ama anahtar hala var mı? Bir şey mi eksik? - Doug Molineux
@Pete hayır, onu kaldırır. Verilen: var x = {a : 'A', b : 'B'}; Karşılaştırmak: delete x.a; typeof x.a; /* "undefined" */ x.hasOwnProperty('a'); /* false */ için x.b = undefined; typeof x.b; /* "undefined" */; x.hasOwnProperty('b'); /* true */ - nickf
@ChristopherPfohl benim için çalışıyor. Dediğim gibi, aslında oldukça derin bir şey, bu yüzden özetlemek biraz zor. Yukarıdaki cevabın temel cevabı hemen hemen tüm vakalar için yeterlidir; blog, daha fazla sayıda davaya girer ve bu davaların nedenleri vardır. - nickf


Şebeke delete beklenmedik şekilde yavaş!

Bak kıyaslama.

Sil, nesnenin özelliklerini herhangi bir kalıntı olmadan kaldırmak için tek gerçek yoldur, ancak çalışır ~ 100 kat daha yavaş, "alternatif" ile karşılaştırıldığında, ayar object[key] = undefined.

Bu alternatif, bu sorunun doğru cevabı değildir! Ancak, bunu dikkatle kullanırsanız, bazı algoritmaları hızlandırabilirsiniz. Eğer kullanıyorsanız delete döngüler halinde ve performansla ilgili problemleriniz var, ayrıntılı açıklamaları okuyun.

Ne zaman kullanmalı delete ve değeri ayarlandığında undefined ?

Bir nesne bir anahtar-değer çiftleri kümesi olarak görülebilir. 'Değer' olarak adlandırdığım şey, 'anahtar' ile bağlantılı olan bir ilkel veya başka bir nesneye yapılan bir başvurudır.

kullanım delete, Sonuç nesnesini, kontrolünüzün olmadığı (veya ekibiniz veya kendiniz hakkında emin olmadığınız durumlarda) koda geçirdiğinizde.

O anahtarı hashmap'tan siler.

 var obj = {
     field: 1     
 };
 delete obj.field;

Ayarını kullan undefined, Performansı önemsediğinizde. Kodunuza ciddi bir destek verebilir.

anahtar hashmap içindeki yerine kalır, sadece değer ile değiştirilir undefined. Anlaşıldı for..in döngü hala bu tuşun üzerinde yinelenecek.

 var obj = {
     field: 1     
 };
 obj.field = undefined;

Bu yöntemi kullanarak, hepsini değil mülkiyet varlığını belirleme yolları beklendiği gibi çalışacaktır.

Ancak, bu kod:

object.field === undefined

Her iki yöntemde de eşit davranacaktır.

Testler

Özetlemek gerekirse, farklılıkların tümü mülkiyet varlığını belirleme yolları hakkındadır ve for..in döngü.

 console.log('* -> "Takes prototype inheritance into consideration, that means it lookups all over prototype chain too."');

 console.log(obj.field === undefined, 'obj.field === undefined', 'You get "undefined" value when querying for "field" in object-hashmap. *');

 console.log(obj["field"] === undefined, 'obj["field"] === undefined', 'Just another way to query (equivalent). *');

 console.log(typeof obj.field === "undefined", 'typeof obj.field === "undefined"', 'Get the value attached to "field" key, and check it\'s type is "undefined". *');

 console.log("field" in obj, '"field" in obj', 'This statement returns true if "field" key exists in the hashmap. False otherwise. *');

 console.log(obj.hasOwnProperty("field"), 'obj.hasOwnProperty("field")', 'This statement returns true if \'field\' key exists in the hashmap. The ONLY way NOT to lookup for property in the prototype chain!');
 //Object.keys().indexOf() is an overkill that runs much slower :)

 var counter = 0,
     key;
 for (key in obj) {
     counter++;
 }
 console.assert(counter === 0, 'counter === 0', '"field" is not iterated using "for .. in" loop. *');

Bellek sızıntısı dikkat!

Kullanırken obj[prop] = undefined yapmaktan daha hızlı delete obj[prop]bir başka önemli husus, obj[prop] = undefined her zaman uygun olmayabilir. delete obj[prop] kaldırır prop itibaren obj ve onu hafızadan siler obj[prop] = undefined sadece değerini ayarlar prop için undefined hangi bırakır prop hala hafızada. Bu nedenle, oluşturulan ve silinen birçok anahtarın bulunduğu durumlarda, obj[prop] = undefined pahalı bellek mutabakatını zorlayabilir (sayfanın donmasına neden olabilir) ve potansiyel olarak bellek yetersizliği hatasına neden olabilir. Aşağıdaki kodu inceleyin.

"use strict";
var theNodeList=[], i, current, numberOfNodes=65536, body=document.body, nodeRecords=[];
for (i = 0; i !== numberOfNodes; i++) {
    nodeRecords[i] = [];
    current = theNodeList[i] = document.createElement("div");
    current.textContent = i;
    document.body.appendChild( current );
}
var lastTime = -1;
requestAnimationFrame(function recordUpdates(){
    var currentTime = Math.round( performance.now()*1000 )
    for (i = 0; i !== numberOfNodes; i++) {
        if (lastTime !== -1) {
            // the previously collected data is no longer in use
            /*************************************************/
            /****/ nodeRecords[i][lastTime] = undefined; /****/
            /*************************************************/
        }
        nodeRecords[i][currentTime] = theNodeList[i].outerHTML;
    }
    lastTime = currentTime;
    requestAnimationFrame( recordUpdates );
});

Yukarıdaki kodda, sadece nodeRecords[i][lastTime] = undefined; Her bir animasyon karesi nedeniyle büyük bir bellek sızıntısına neden olur. Her bir çerçeve, tüm 65536 DOM elemanlarının başka bir 65536 ayrı yuva alacaktır, ancak önceki 65536 yuvaları yalnızca onları bellekte asılı bırakan undefined olarak ayarlanacaktır. Devam edin, yukarıdaki kodu konsolda çalıştırmayı deneyin ve kendiniz görün. Yetersiz bellek hatasını zorladıktan sonra, aşağıdaki kodu kullanan aşağıdaki kodun dışında yeniden çalıştırmayı deneyin. deleteyerine operatör.

"use strict";
var theNodeList=[], i, current, numberOfNodes=65536, body=document.body, nodeRecords=[];
for (i = 0; i !== numberOfNodes; i++) {
    nodeRecords[i] = [];
    current = theNodeList[i] = document.createElement("div");
    current.textContent = i;
    document.body.appendChild( current );
}
var lastTime = -1;
requestAnimationFrame(function recordUpdates(){
    var currentTime = Math.round( performance.now()*1000 )
    for (i = 0; i !== numberOfNodes; i++) {
        if (lastTime !== -1) {
            // the previously collected data is no longer in use
            /********************************************/
            /****/ delete nodeRecords[i][lastTime]; /****/
            /********************************************/
        }
        nodeRecords[i][currentTime] = theNodeList[i].outerHTML;
    }
    lastTime = currentTime;
    requestAnimationFrame( recordUpdates );
});

Yukarıdaki kod snippet'inde görüldüğü gibi, bazı nadir uygun kullanım durumları vardır. delete Şebeke. Ancak, bu sorun hakkında çok fazla endişelenmeyin. Bu, sürekli olarak eklenen yeni anahtarları alan uzun ömürlü nesnelerle ilgili bir sorun olacaktır. Başka bir durumda (gerçek dünya programlamasında neredeyse her durum böyle), kullanılması en uygun olanıdır. obj[prop] = undefined. Bu bölümün ana amacı sadece dikkatinizi bu konuya getirmektir ki bu nadiren de olsa sizin kodunuzda bir sorun haline gelebilir, o zaman problemi daha kolay anlayabilirsiniz ve böylece kodunuzu bulmak için zaman ayırmanız gerekmez. ve bu sorunu anlayın.

Her Zaman Ayarlanmıyor undefined

Göz önünde bulundurulması gereken Javascript'in bir yönü polimorfizmdir. Polymorphism, aşağıda görüldüğü gibi aynı değişken / slot-in-a-object farklı tiplerini atamaktır.

var foo = "str";
foo = 100;          // variable foo is now labeled polymorphic by the browser
var bar = ["Some", "example"];
bar[2] = "text";    // bar is a monomorphic array here because all its entries have the
                    // same type: string primitive
bar[1] = undefined; // bar is now a polymorphic array

Bununla birlikte, polimorfik dizilerle iki ana çözülemez problem vardır:

  1. Onlar yavaş ve hafıza verimsizdir. Belirli bir dizine erişilirken, yalnızca dizinin global türünü almak yerine, tarayıcı, her bir dizinin türünün ek meta verilerini sakladığı biçimde, dizin başına başına bir tür alması gerekir.
  2. Polimorfik bir zaman, her zaman polimorfik. Bir dizi polimorfik yapıldığında, polimorfizm Webkit tarayıcılarında geri alınamaz. Bu nedenle, polimorfik bir diziyi polimorfik olmayan bir hale geri döndürseniz bile, tarayıcı tarafından hala bir polimorfik dizi olarak saklanır.

Bir kişi polimorfizmi bir uyuşturucu bağımlılığına benzetebilir. İlk bakışta, çok karlı görünüyor: güzel oldukça kabarık kod. Sonra, kodlayıcı dizilerini polimorfizm ilacına sokar. Anında, polimorfik dizi daha az etkili hale gelir ve bu, uyuşturulduktan sonra daha önce olduğu kadar verimli olamaz. Bu durumu gerçek yaşamla ilişkilendirmek için, kokain üzerindeki bir kişi basit bir kapı tutamaçını çalıştıramayabilir, PI rakamlarını çok daha az hesaplayabilir. Aynı şekilde, polimorfizm ilacı üzerindeki bir dizi, bir monomorfik dizi kadar verimli olamaz.

Ancak, bir uyuşturucu gezi benzetimi ile nasıl ilgilidir delete operasyon? Yanıt, yukarıdaki kod parçasındaki son kod satırını miras alır. Böylece, bu kez bir twist ile yeniden ele alın.

var bar = ["Some", "example"];
bar[2] = "text";    // bar is not a polymorphic array here because all its entries have the
                    // same type: string primitive
bar[1] = "";        // bar is still a monomorphic array
bar[1] = undefined; // bar is now a polymorphic array

Gözlemek. bar[1] = "" polimorfizmi zorlamazken bar[1] = undefined yapar. Bu nedenle, her zaman, mümkün olduğunda, polimorfizme tesadüfen neden olmamak için, karşılık gelen tipi nesneler için kullanmalıdır. Böyle bir kişi, aşağıdaki listeyi devam ettirmek için genel referans olarak kullanabilir. Ancak, lütfen aşağıdaki fikirleri açıkça kullanmayın. Bunun yerine, kodunuz için uygun olan her şeyi kullanın.

  • Boolean ilkeline yazılan bir dizi / değişken kullanırken, ya false veya undefined boş değer olarak. Gereksiz polimorfizmden kaçınmak iyi olsa da, tüm kodlarınızı açıkça yasaklamak için yeniden yazmanız, muhtemelen performansta düşüşe neden olacaktır. Ortak yargı kullanın!
  • Sayıya ilkel olarak yazılan bir dizi / değişken kullanırken 0 boş değer olarak. Dahili olarak, iki tür sayının olduğunu unutmayın: hızlı tamsayılar (2147483647 - -2147483648 dahil) ve yavaş kayan nokta ikilileri (dahil olanlar hariç) NaN ve Infinity). Bir tam sayı ikiye indirildiğinde, tekrar tam sayıya yükseltilemez.
  • String ilkeline yazılan bir dizi / değişken kullanırken "" boş değer olarak.
  • Bir Sembolü kullanırken, bekle, neden bir Sembol kullanıyorsunuz?!?! Semboller performans için kötü bir juju. Semboller kullanmak için programlanan her şey, Semboller kullanılmadan yeniden programlanıp, Semboller olmadan daha hızlı bir kodla sonuçlanabilir. Semboller gerçekten sadece süper verimsiz meta şekerdir.
  • Başka bir şey kullanırken, kullanın null.

Ancak dikkatli ol! Bunu önceden varolan tüm kodunuzla yapmaya başlamayın, çünkü bu tür önceden varolan kodu bozabilir ve / veya garip hatalar ekleyebilir. Bunun yerine, bu tür verimli bir uygulama başlangıçtan itibaren uygulanmalıdır ve önceden varolan kodu dönüştürürken, bu yeni uygulamaya yükseltmek için eski kodu yükseltmeye çalışmakla ilgili tüm satırları çift, üçlü, dörtlü olarak kontrol etmeniz önerilir. Ödüllendirici olduğu için riskli.


705
2018-02-12 17:48



undefined için bir özellik atanan bir nesnenin bir özelliğidir, bu nedenle son paragrafınızı yanlış okumadığı sürece GC tarafından kaldırılmaz. - Lance
GC'nin temasına dokunmak yanlış oldu. Her iki yöntem de GC için aynı sonuca sahiptir: anahtarla bağlantılı değeri kaldırırlar. Bu değer, başka bir nesnenin son referansı olsaydı, bu nesne temizlenirdi. - Dan
undefined için bir özellik atanmış bir nesnenin bir özelliğidir, bu nedenle GC tarafından kaldırılmayacaktır GC, mülkler hakkında hiçbir şey yönetmiyor. Değerleri toplar ve kaldırır. Artık hiçbir şey bir değere (bir nesne, dize vb.) Referans vermediği sürece, GC bunu bellekten kaldırır. - meandre
BTW, bir özellik Javascript nesnesinde olup olmadığını kontrol etmek için ikili bir sorundur. kullanma içinde Operatör güvenilir ama yavaş. Mülkün olmadığını kontrol edin Tanımsız "doğru cevap değil" ama bu daha hızlı bir yoldur. Kontrol - rdllopes
Bu cevap hala geçerli mi? jsperf şu anda çalışmıyor, ama bu kriter hız farkının sadece% 25 olduğunu gösteriyor, ki bu hiçbir yer değil kapat göre "~ 100 kere daha yavaş" bu cevapta. - Cerbrus


var myObject = {"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"};
    
delete myObject.regex;

console.log ( myObject.regex); // logs: undefined

Bu, Firefox ve Internet Explorer'da çalışır ve bence tüm diğerlerinde çalışır.


193
2017-10-16 11:03



Tek bir ifadeyi kullanarak aynı diziden birden çok özelliği silmenin bir yolu var mı - Aakriti.G
Aynı anda birden fazla mülkü silmeye çalışırken, yeni bir nesneyi yeniden eşlemek daha iyi olmaz mı? - jasonscript


2018-07-21'i güncelleyin: Uzun zamandır bu cevaptan utanmış hissettim, sanırım ona biraz dokunma zamanı geldi. Bu cevabın gereksiz uzun ve kıvrımlı kısımlarının okunmasını hızlandırmaya yardımcı olacak küçük bir yorum, açıklama ve biçimlendirme.


KISA VERSİYON

Soruya gerçek cevap

Diğerleri söylediler, kullanabilirsiniz delete.

obj // {"foo": "bar"}
delete obj["foo"]
obj // {}
obj["foo"] // undefined

Dizi karşılığı

Yapma delete bir diziden. kullanım Array.prototype.splice yerine.

arr // [1,2,3,4,5]
arr.splice(3,1); // 4
arr // [1,2,3,5]

UZUN VERSİYON

JavaScript bir OOP Dili, yani her şey bir diziler. Bu nedenle, belirli bir uyarıya işaret etmenin gerekli olduğunu hissediyorum.

Dizilerde, düz eski nesnelerden farklı olarak, delete şeklinde çöpün arkasında bırakır nulldizide bir "delik" oluşturmak.

var array = [1, 2, 3, 4];
delete array[2];
/* Expected result --> [1, 2, 4]
 * Actual result   --> [1, 2, null, 4]
 */

Gördüğün gibi, delete Her zaman beklendiği gibi çalışmıyor. Değerin üzerine yazılır, ancak bellek yeniden tahsis edilmemiştir. Demek ki, array[4] taşınmamış array[3]. Bunun aksine Array.prototype.unshiftdizinin başlangıcına bir eleman ekler ve her şeyi yukarı kaydırır (array[0] olur array[1], vb.)

Dürüst olmak gerekirse, null ziyade undefined- yasal olarak tuhaf - bu davranış olmamalı Şaşırtıcı olmak delete tek bir operatör gibi typeofBu, dilin içine kaynatılmış ve umurumda değil tip nesnenin üzerinde kullanılıyor, oysa Array bir alt sınıfıdır Object yöntemlerle özellikle için tasarlanmış dizilerle çalışmak. Yani bunun için iyi bir sebep yok deletedizinin yeniden kaydırılması için pişirilen özel bir durumun olması, gereksiz şeylerle sadece işleri yavaşlatır. Geçmişe baktığımızda beklentilerim gerçekçi değildi.

Tabiki did şaşırt beni. Çünkü bunu "boş çöplüğe" karşı haçlı selamımı haklı çıkarmak için yazdım:

İçindeki tehlikeleri ve sorunları göz ardı etmek nullve boşa harcanan alan, dizinin kesin olması gerekiyorsa bu sorun yaratabilir.

Hangi kurtulmak için korkunç bir gerekçe nulls-null sadece yanlış kullanıldığında tehlikelidir ve "hassas" ile ilgisi yoktur. Yapmamanın asıl nedeni delete bir diziden, çöp dolu ve dağınık veri yapılarının etrafından ayrılmasının özensiz ve hataya eğilimli olmasıdır.

Sonrasında, oldukça uzun soluklu hale gelen, tartışmalı bir senaryoya göre, bu bölüme geçebilirsiniz. Çözüm, Eğer istersen. Bu bölümden ayrılmamın tek nedeni, bazı insanların muhtemelen komik olduğunu düşündüğünden ve "komik" bir yanıt gönderen ve daha sonra ondan "komik" olan "o adam" olmak istemediğimden kaynaklanmaktadır. .

... aptal, biliyorum.

Gümrüklü ve uzun soluklu PDP-11 senaryosu

Örneğin, bir dizede 'sekmeler' için kullanılan bir diziyi saklamak için JSON serileştirmesini kullanan bir webapp oluşturduğunuzu varsayalım (bu durumda, localStorage). Ayrıca, kodun, dizinin üyelerine ait sayısal indisleri, ekrana çizilirken "başlık" yapmak için kullandığını da söyleyelim. Neden "başlık" da saklamaktan ziyade bunu yapıyorsun? Çünkü... nedenleri.

Tamam, sadece bunun için hafızayı kurtarmaya çalıştığınızı söyleyelim bir 1960’da çalışan UNIX’den bir PDP-11 mini bilgisayar çalıştıran kullanıcı, X11’den dolayı kendi Elinks tabanlı, JavaScript uyumlu, yazıcı-yazıcı dostu bir tarayıcı yazdı. Sorunun dışında.

Son derece aptal durum senaryosu bir yana, kullanarak delete sözü edilen dizi üzerinde sonuçlanacak null diziyi kirletiyor ve muhtemelen daha sonra uygulamada hatalara neden oluyor. Ve eğer kontrol ederseniz null, düz bir şekilde gösterildiği gibi sekmelerle sonuçlanan sayıları atlar [1] [2] [4] [5] ....

if (array[index] == null)
    continue;
else
    title = (index + 1).toString();
/* 0 -> "1"
 * 1 -> "2"
 * 2 -> (nothing)
 * 3 -> "4"
 */

Evet, kesinlikle istediğin bu değildi.

Şimdi sen could ikinci bir yineleyici tutmak jYalnızca geçerli değerler diziden okunduğunda artış yapmak için. Ama bu tam olarak çözemez null sorun, ve hala bunu lütfen trol PDP-11 kullanıcısı. Ne yazık ki, onun bilgisayarı sadece değil Son tamsayıyı tutmak için yeterli belleğe sahip (değişken genişlikte bir diziyi nasıl idare edeceğini sorma ...).

Yani, size öfkeyle bir e-posta gönderir:

Hey, your webapp broke my browser! I checked my localStorage database after your stupid code made my browser segfault, and this is what I found:

>"tabs:['Hello World', 'foo bar baz', null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, ... ]"

After clearing my precious data, it segfaulted again, and I did a backtrace, and what do I find? WHAT DO I FIND!? YOU USE TOO MANY VARIABLES!

>var i = index;
>var j = 1;

Grr, I am angry now.
-Troll Davidson

Şimdilik, senin aklının ucundasın. Bu adam uygulamanız hakkında durmaktan şikayet ediyor ve ona susmasını ve daha iyi bir bilgisayar almasını söylemek istiyorsun.

Çözüm: Array.prototype.splice

Neyse ki, diziler yap Endeksleri silmek ve belleği yeniden ayırmak için özel bir yönteme sahip olmak: Array.prototype.splice(). Böyle bir şey yazabilirsin:

Array.prototype.remove = function(index){
  this.splice(index,1);
}
...
array = [1, 2, 3, 4];
array.remove(2);
// Result -> [1, 2, 4]

Ve aynen öyle, Bay PDP-11'i memnun ettiniz. Yaşasın! (Yine de ona söyleyeyim, ama ...)

Array.prototype.splice vs Array.prototype.slice

Her ikisi de çok faydalı oldukları için, benzer olarak adlandırılan bu iki işlev arasındaki farkı belirtmek önemli.

Array.prototype.splice (başlangıç, n)

.splice() diziyi değiştirir ve kaldırılan endeksleri döndürür. Dizi dizinden başlayarak dilimlenmiş, start, ve n elemanlar dilimlenir. N belirtilmemişse, dizinin tamamı start dilimlenmiş (n = array.length - start).

let a = [5,4,3,2,1];
let chunk = a.splice(2,2);

// a     [5,4,3,2,1]
// start  0 1 2 - -
// n      - - 1 2 -

chunk; // [3,2]
a;     // [5,4,1]

Array.prototype.slice (başlangıç, bitiş)

.slice() tahribatsızdır ve belirtilen endeksleri içeren yeni bir dizi döndürür start için end. Eğer end belirsiz bırakılır, davranış aynıdır .splice() (end = array.length). Davranış, bir sebepten dolayı biraz zor end 0 yerine 1'den dizinler. Bunu neden yaptığını bilmiyorum, ama işte böyle. Ayrıca eğer end <= start, sonuç boş bir dizidir.

let a = [5,4,3,2,1];
let chunks = [
    a.slice(2,0),
    a.slice(2,2),
    a.slice(2,3),
    a.slice(2,5) ];

// a             [5,4,3,2,1]
// start          0 1 2 - -
// end, for...    - - - - -
//   chunks[0]  0 - - - - -   
//   chunks[1]    1 2 - - -
//   chunks[2]    1 2 3 - -
//   chunks[3]    1 2 3 4 5

chunks; // [ [], [], [3], [3,2,1] ]
a;      // [5,4,3,2,1]

Bu aslında olan şey değil, ama bu şekilde düşünmek daha kolay. MDN'ye göre, aslında neler oluyor:

// a             [5,4,3,2,1]
// start          0 1 2 - - -
// end, for...    - - - - - -
//   chunks[0]    0 - - - - -
//   chunks[1]    0 1 2 - - -
//   chunks[2]    0 1(2)3 - -
//   chunks[3]    0 1(2 3 4)5

Tarafından belirtilen dizin end sadece dilimden hariç tutulur. Parçalı indeksler neyin dilimlendiğini gösterir. Her iki durumda da, davranış sezgisel değildir ve birebir hataların adil bir şekilde paylaşılmasına neden olur, bu yüzden davranışını daha yakın bir şekilde taklit etmek için bir sarıcı işlevi yapmak yararlı olabilir. .splice():

function ez_slice(array, start = 0, n = null){
    if(!Array.isArray(array) || !is_number(start))
        return null;

    if(is_number(n))
        return array.slice(start, start + n);

    if(n === null)
        return array.slice(start);

    return null;
}

ez_slice([5,4,3,2,1], 2, 1) // [3]
ez_slice([5,4,3,2,1], 2)    // [3,2,1]

/* Fun fact: isNaN is unreliable.
 * [NaN, [], {}, 0, 1, Infinity, undefined, null, "Hi"].filter(isNaN)
 * [NaN, {}, undefined, "Hi"]
 *
 * What we want is...
 *
 * [NaN, [], {}, 0, 1, Infinity, undefined, null, "Hi"].filter(is_nan)
 * [NaN]
 */
function is_nan(num){
    return typeof num === "number"
        && num !== num;
}

function is_number(num){
    return !is_nan(num)
        && typeof num === "number"
        && isFinite(num);
}

Sarma işlevinin türler hakkında çok sıkı olacak şekilde tasarlandığını ve geri döneceğini unutmayın. null eğer bir şey kapalıysa. Bu gibi bir dize koyarak içerir "3". Türleri konusunda çalışkan olmak için programcıya bırakılır. Bu, iyi programlama uygulamasını teşvik etmektir.

İle ilgili güncelleme is_array()

Bu, şu (kaldırılmış) snippet ile ilgilidir:

function is_array(array){
    return array !== null
        && typeof array === "object"
        && typeof array.length !== "undefined"
        && array.__proto__ === Array.prototype;
}

Sonuç olarak, aslında bir dizinin gerçekten bir dizi olup olmadığını anlamaya yönelik yerleşik bir yol var. Array.isArray(), ECMAScript 5'te tanıtıldı (Aralık 2009). Bunu, nesneleri dizilerden anlatmak, benimkilerden daha iyi bir çözüm olup olmadığını görmek ya da hiç değilse benimkini eklemek hakkında bir soru olup olmadığını görmek için bakarken buldum. Dolayısıyla, ECMA 5'ten daha eski bir JavaScript sürümünü kullanıyorsanız, çokdüzenli dolgunuz var. Ancak, kullanmamaya şiddetle tavsiye ederim. is_array() JavaScript'in eski sürümlerini desteklemeye devam etme işlevi, onları uygulayan eski tarayıcıları desteklemeye devam etmek anlamına gelir; bu da, güvenli olmayan yazılım kullanımını teşvik etmek ve kullanıcıları kötü amaçlı yazılım için risk altına sokmak anlamına gelir. Lütfen kullanın Array.isArray(). kullanım let ve const. Dile eklenen yeni özellikleri kullanın. Yapma satıcı öneklerini kullanın. silmek IE polyfill web sitenizden cızırdadı. Bu XHTML'yi sil <!CDATA[[... saçmalamak - biz 2014 yılında HTML5'e geri döndük. Daha eski herkes bu eski / ezoterik tarayıcıları destekliyor, tarayıcı satıcıları aslında web standardını takip edecek ve yeni teknolojiyi benimseyeceklerdi ve ne kadar çabuk devam edeceğiz? daha güvenli bir web.


134
2017-09-18 00:56



Bu delete Ancak, anahtar kelime çok daha uygun, lol - Braden Best
Bu yaklaşım, başka bir yerde hala başvurulan orijinal nesneyi değiştirmez. Bu, nasıl kullanıldığına bağlı olarak bir sorun olabilir veya olmayabilir, ancak akılda tutulması gereken bir şeydir. - Tamas Czinege
@ B1KMusic Bir ögeden bir ögeyi silmenin yolu: ek yeri - wulftone
@wulftone nope, diziyi böler ve bir değeri silmek için hiçbir şey yapmaz. Gerçekten, silinmesi gereken belirli değerlerin bir diziden silinmesinin en iyi yolunun kullanmak olduğunu düşünüyorum. delete ve temizlemek için bir Çöp Toplama işlevi yapmak. - Braden Best
Ben görmüyorum splice düzenlemenizde remove olmalı Array.prototype.remove = function(index) { this.splice(index, 1); }; - Ry-♦


Eski soru, modern cevap. Nesne yıkımını kullanarak, bir ECMAScript 6 özelliği, bu kadar basit:

const { a, ...rest } = { a: 1, b: 2, c: 3 };

Veya soru örnekleriyle:

const myObject = {"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"};
const { regex, ...newObject } = myObject;
console.log(newObject);

Babel try-out editöründe bunu görüyorsunuz.


Düzenle:

Aynı değişkeni yeniden atamak için let:

let myObject = {"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"};
({ regex, ...myObject } = myObject);
console.log(myObject);

92
2017-11-08 18:02



Belki de amaç, bir nesneyi bir nesneyi kaldırmak, mülk olmaksızın yeni bir tane yaratmak değil ... ... çünkü çözümün benim favorimdir, ... ... değişmez yolu tercih ettiğimden. - Vingt_centimes
Sorulan soru "ile sonuçlanmak yeni myObject". - Koen.
Göre kangax.github.io/compat-table/esnext, nesne bekleme özellikleri ES6 için sonlandırılmamış, sıfır tarayıcı uygulamaları vardır ve yalnızca Babel destek sağlar. - Justin C
Bu aslında istenmeyen sahne olmadan yeni nesne ataması için tatlı bir astardır ve zaten Node.js 8 ile desteklenmektedir. * / 9. * ile --harmony: node.green/... - Damaged Organic
Bu 2018'de kabul edilen cevap olmalı :) - Yulian


Başka bir alternatif kullanmaktır Underscore.js kütüphane.

Bunu not et _.pick() ve _.omit() her ikisi de nesnenin bir kopyasını döndürür ve orijinal nesneyi doğrudan değiştirmez. Sonucu asıl nesneye atamak hileyi (gösterilmiyor) yapmalıdır.

Referans: bağlantı  _.pick (nesne, * tuş)

Nesnenin bir kopyasını döndürür, yalnızca beyaz listeye alınmış tuşlar (veya geçerli anahtar dizisi).

var myJSONObject = 
{"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"};

_.pick(myJSONObject, "ircEvent", "method");
=> {"ircEvent": "PRIVMSG", "method": "newURI"};

Referans: bağlantı  _.omit (nesne, * tuşlar)

Nesnenin bir kopyasını döndürerek, atlamak için filtreleyin kara listeye alınmış anahtarlar (veya tuş dizisi).

var myJSONObject = 
{"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"};

_.omit(myJSONObject, "regex");
=> {"ircEvent": "PRIVMSG", "method": "newURI"};

Diziler için _.filter() ve _.reject() benzer bir şekilde kullanılabilir.


67
2018-05-24 18:53



Nesnenin anahtarları sayılarsa, ihtiyacınız olabilir. _.omit(collection, key.toString()) - Jordan Arseno
Neden Vikipedi'ye bağlandınız, değil underscorejs.org? - E730
@ E730 İyi soru. Editörlerden birinin neden wikipedia.org/wiki/Underscore.js'ye yönlendirdiğini bilmiyorum. Onu underscorejs.org olarak değiştirdim. - Thaddeus Albers
Hmmmmm .... Underscore ~ ​​100x daha yavaş delete obj[prop] ~ 100x daha yavaş obj[prop] = undefined. - Jack Giffin


Soru başlığında kullandığınız terim Remove a property from a JavaScript object, bazı farklı şekillerde yorumlanabilir. Biri, tüm bellek ve nesne anahtarlarının listesi için çıkartmak ya da diğeri onu nesnenizden kaldırmaktır. Bazı diğer cevaplarda da belirtildiği gibi, delete anahtar kelime ana bölümdür. Diyelim ki nesneyiniz şöyle:

myJSONObject = {"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"};

Yaparsan:

console.log(Object.keys(myJSONObject));

sonuç şöyle olurdu:

["ircEvent", "method", "regex"]

Bu belirli anahtarı, aşağıdaki gibi nesne anahtarlarınızdan silebilirsiniz:

delete myJSONObject["regex"];

Sonra nesnelerinizi kullanarak anahtar Object.keys(myJSONObject) olabilir:

["ircEvent", "method"]

Ancak önemli olan, belleği önemsiyorsanız ve nesnenin belleğinden kaldırılmasını istiyorsanız, anahtarı silmeden önce null olarak ayarlamanız önerilir:

myJSONObject["regex"] = null;
delete myJSONObject["regex"];

Buradaki diğer önemli nokta, aynı nesneye yapılan diğer referanslarınıza dikkat etmektir. Örneğin, aşağıdaki gibi bir değişken oluşturursanız:

var regex = myJSONObject["regex"];

Ya da başka bir nesneye yeni bir işaretçi olarak ekleyin:

var myOtherObject = {};
myOtherObject["regex"] = myJSONObject["regex"];

Daha sonra onu nesnenizden kaldırsanız bile myJSONObject, o belirli nesne bellekten silinmez, çünkü regex değişken ve myOtherObject["regex"] hala kendi değerlerine sahipler. Öyleyse nesneyi bellekten nasıl kaldırabiliriz?

Cevap olurdu Kodunuzda bulunan tüm referansları siliniz, o nesneye işaret ediniz ve ayrıca kullanmaz var Bu nesneye yeni referanslar oluşturma ifadeleri. İle ilgili son nokta var ifadeleri, genellikle karşılaştığımız en önemli konulardan biridir, çünkü var ifadeler, oluşturulan nesnenin kaldırılmasını engeller.

Bu durumda, bu nesneyi regex bir değişken var ifade ve eğer yaparsanız:

delete regex; //False

Sonuç olurdu falseBu, silme ifadenizin beklediğiniz gibi yürütülmediği anlamına gelir. Ama daha önce bu değişkeni yaratmamış olsaydın, ve sadece myOtherObject["regex"] Son mevcut referansınız olarak, bunu aşağıdaki gibi kaldırarak yapabilirsiniz:

myOtherObject["regex"] = null;
delete myOtherObject["regex"];

Başka bir deyişle, kodunuzda o nesneye işaret edilen bir referans kalmaz, bir JavaScript nesnesi öldürülür.


Güncelleştirme: @AgentME'ye teşekkürler:

Bir mülkü silme işleminden önce null olarak ayarlamak tamamlanmadı   nesne (Object.seal ve   silme başarısız. Bu, özellikle siz istemediğiniz sürece geçerli değildir.   Deneyin).

Hakkında daha fazla bilgi almak için Object.seal: Object.seal ()


34
2018-02-12 06:29



Yanılıyorsunuz - yalnızca JavaScript’te referans olarak gönderilen nesneler myJSONObject.regexdeğeri bir dizedir ve onu başka bir nesneye atarsınız, diğer nesnenin de bu değerin bir kopyası vardır. - Michał Perłakowski
Haklısınız ve bu bir alıntıdır: "Aynı nesneye diğer referanslarınız hakkında dikkatli olmak için." - Mehran Hatami


Şuna benzeyen bir nesneye sahip olduğunuzu varsayalım:

var Hogwarts = {
    staff : [
        'Argus Filch',
        'Filius Flitwick',
        'Gilderoy Lockhart',
        'Minerva McGonagall',
        'Poppy Pomfrey',
        ...
    ],
    students : [
        'Hannah Abbott',
        'Katie Bell',
        'Susan Bones',
        'Terry Boot',
        'Lavender Brown',
        ...
    ]
};

Bir nesne özelliğini silme

Tüm kullanmak istiyorsanız staff dizi, bunu yapmak için doğru yolu, bunu yapmak olacaktır:

delete Hogwarts.staff;

Alternatif olarak, bunu da yapabilirsiniz:

delete Hogwarts['staff'];

Benzer şekilde, tüm öğrenci dizisini kaldırmak, arayarak yapılacaktır. delete Hogwarts.students; veya delete Hogwarts['students'];.

Dizi dizini siliniyor

Şimdi, tek bir personel veya öğrenciyi kaldırmak istiyorsanız, prosedür biraz farklıdır, çünkü her iki özellik de dizilerin kendileridir.

Çalışan elemanınızın endeksini biliyorsanız, bunu basitçe yapabilirsiniz:

Hogwarts.staff.splice(3, 1);

Dizini bilmiyorsanız, bir dizin araması da yapmanız gerekir:

Hogwarts.staff.splice(Hogwarts.staff.indexOf('Minerva McGonnagall') - 1, 1);

Not

Teknik olarak kullanabilirsiniz delete bir dizi için, örneğin çağırırken yanlış sonuçlar elde edilmesine neden olur Hogwarts.staff.length daha sonra. Diğer bir deyişle, delete öğeyi kaldıracaktı, ancak değerini güncellemedi length özelliği. kullanma delete ayrıca indekslemenizi de bozar.

Dolayısıyla, bir nesneden değerler silerken, her zaman öncelikle nesne özellikleriyle mi uğraştığınızı veya dizi değerleriyle uğraştığınızı düşünün ve buna göre uygun stratejiyi seçin.

Bununla denemek istiyorsanız, kullanabilirsiniz bu Fiddle başlangıç ​​noktası olarak.


30
2018-02-21 18:09



Her zaman kullanman gerektiğini düşünürdüm splice yerine bir dizide delete. - Joel Trauger
@JoelTrauger: Ben de söylüyorum ;-) - John Slegers
Evet. Benim yorumum şu ki delete bir şey olmamalı. Onun splice OP'nin aradığı şey. - Joel Trauger
@JoelTrauger: Açıklamaya çalıştığım gibi, delete nesne özellikleri için kullanılmalı ve splice dizi elemanları için. - John Slegers
Ekleme gerçekten yavaştır. Yerine kullanılmalıdır delete diziler üzerinde, etrafında merkezli kod oluşturmamak akıllıca olurdu. - Jack Giffin