Bir obyekti JavaScript obyektindən necə çıxarmaq olar?

Gəlin bu kimi bir obyekt yaradın:

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

regex mülkiyyətini aradan qaldırılması üçün ən yaxşı yol nədir, bu kimi yeni bir myObject ilə sona çatmaq üçün:

 var myObject = { "ircEvent": "PRIVMSG", "method": "newURI" }; 
5276
16 окт. johnstok 16 oct qurmaq . 2008-10-16 13:57 '08 at 13:57 2008-10-16 13:57
@ 37 cavab
  • 1
  • 2

Burada:

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

Demo

blogda silinmə anlayışı haqqında delete haqqında bəyanat haqqında inanılmaz ətraflı blog yazısı yazdı.  Tövsiyə olun. 

7292
16 окт. Cavab 16 oktyabr ləqəbi verilir . 2008-10-16 13:58 '08 at 13:58 pm 2008-10-16 13:58

operator delete gözlənilmədən susdurur!

Benchmark baxın.

Sil heç bir qalıq olmadığı halda obyektin xüsusiyyətlərini aradan qaldırmaq üçün yeganə əmin yoludur, ancaq "alternativ" tənzimləyici object[key] = undefined nisbətən ~ 100 dəfə daha yavaş işləyir object[key] = undefined .

Bu alternativ bu suala düzgün cavab vermir! Ancaq diqqətlə istifadə etsəniz, bir sıra alqoritmləri sürətləndirə bilərsiniz. Döngələrdə silinmə istifadə edərsə və performans problemləri varsa, ətraflı izahat oxuyun.

delete lazım olan zaman və müəyyən dəyəri nə vaxt müəyyən edilməlidir?

Bir obyekt əsas dəyər cütü kimi qəbul edilə bilər. Mən "dəyər" adlandırdığım bu ibtidai və ya "əsas" ilə əlaqəli başqa bir obyektə istinad edir.

Nəticə obyektini nəzarət etmədiyiniz kodda (və ya komandanıza və ya özünüzə əmin olmadığı halda) delete istifadə edin .

Anahtarı hash kartından çıxarır .

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

Performansdan əmin deyilsinizsə , undefined variantdan istifadə edin . Bu kodunuzu ciddi şəkildə təsir edə bilər.

Açar hashmapda öz yerində saxlanılır , yalnız dəyəri undefined . Bu dövr üçün hələ də bu for..in anlayın.

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

Bu metoddan istifadə edərək , mövcud əmlakın müəyyənləşdirilməsinin bütün üsulları gözlənildiyi kimi işləməyəcəkdir.

Ancaq bu kod:

object.field === undefined

hər iki metod üçün bərabər davranacaq.

testlər

Bir əmlakın varlığının müəyyənləşdirilməsi yolları və for..in Loop for..in .

border=0
  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\ 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. *'); 

Yaddaş sızıntısından çəkinin!

obj[prop] = undefined delete obj[prop] daha sürətli olsa da, başqa bir vacib məsələ o deməkdir ki, obj[prop] = undefined həmişə uyğun olmaya bilər. delete obj[prop] obj'den prop obj ve bellekten obj , obj[prop] = undefined basitçe prop değeri obj ve bellekte hala obj[prop] = undefined . Buna görə də, yaradılmış və silinən bir çox açarın olduğu obyektlərdə, obj[prop] = undefined istifadə edərək bahalı yaddaş tutarlılığına (səhifənin dondurulmasına səbəb ola bilər) və potensial olaraq yaddaşdan çıxan bir səhv gətirə bilər. Aşağıdakı kodu yoxlayın.

 "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 ); }); 

Yuxarıda göstərilən nodeRecords[i][lastTime] = undefined; , yalnız nodeRecords[i][lastTime] = undefined; animasiya hər bir çərçivə görə kütləvi yaddaş sızması ilə nəticələnəcək. Hər bir çərçivə, 65536 DOM-un bütün elementləri başqa 65.536 fərdi yuva alacaq, lakin əvvəlki slot 65.536 yalnız müəyyənləşdirilməyəcək, bu isə onları yaddaşda asılı olaraq qoyur. Gedin, yuxarıda göstərilən kodu konsolda sınayın və özünüz baxın. Zorunlu yaddaş hatasından sonra, delete operatorunu istifadə edən kodun növbəti versiyası istisna olmaqla, onu yenidən çalıştırmağa çalışın.

 "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 ); }); 

Yuxarıda göstərilən kod snippetindən göründüyü kimi, delete operatoru üçün bir sıra nadir istifadələr mövcuddur. Ancaq bu problemdən çox narahat olmayın. Bu, yalnız uzun ömürlü obyektlər ilə problem yaranacaq ki, bu daima onlara yeni açar əlavə edir. Hər hansı bir halda (bu, real proqramlaşdırma demək olar ki, hər bir halda), obj[prop] = undefined istifadə etmək ən məqsədəuyğundur. Bu bölmənin əsas məqsədi, nadir hallarda kodunuzda problem olduğuna diqqətinizi cəlb etməkdir. Ona görə problemi asanlıqla başa düşə bilərsiniz və bu səbəbdən bu problemi tapmaq və anlamaq üçün kodunuzu analiz edən vaxt sərf etmirsiniz.

Həmişə müəyyən undefined

Hesab etmək lazımdır ki, Javascript bir aspekti polimorfizmdir. Polimorfizm aşağıda göstərildiyi kimi müxtəlif növ obyektlərdə eyni dəyişənlərin / slotların təyin edilməsidir.

 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 belə, polimorfik seriallardan istifadə edərkən aradan qaldırıla bilməyən iki əsas problem var:

  1. Onlar yavaş və təsirsizdir. Belirli bir dizine erişirken, bir dizi üçün basit bir qlobal növü almanın yerine, brauzerin yerine, hər bir endeksin türünün metadatasını saxlayan bir endekse dayanan bir növü olmalıdır.
  2. Polimorfikdən sonra həmişə polimorfikdir. Bir sıra polimorfik hala gətirildikdə, Webkit brauzerlərində polimorfizm ləğv edilə bilməz. Beləliklə, bir polimorfik diziyi qeyri-polimorfik olaraq bərpa etsəniz, brauzer tərəfindən hələ polimorfik bir sıra kimi saxlanılacaq.

Siz narkotik maddə asılılığının polimorfizmini bənzə bilərsiniz. İlk baxışdan inanılmaz dərəcədə sərfəli görünür: gözəl, çox tüklü bir kod. Enkoder daha sonra polimorfizm dərmanına daxil olur. Dərhal polimorfik bir matris daha az təsirli olur və anesteziya olduğu üçün heç vaxt əvvəlki kimi təsirli ola bilməz. Bu vəziyyəti real həyatla əlaqələndirmək üçün, kokaindən birinin hətta sadə bir qapı tutamağını idarə edə bilməməsi, daha az Pİ nömrələrini hesablamaq mümkün deyildir. Eyni şəkildə, bir polimorfizm hazırlığında bir sıra monomorfik bir sıra kimi təsirli ola bilməz.

Amma narkotik analogiyasını delete əməliyyatı necədir? Cavab yuxarıda göstərilən parçada sonuncu kod satırını ehtiva edir. Beləliklə, bu dəfə bir twist ilə düzəliş edək.

 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 

Diqqət edin. bar[1] = "" polimorfizmi yaramır, bar[1] = undefined edir. Buna görə də mümkün olduqda, təsadüfən polimorfizmə yol verməmək məqsədilə, obyektləriniz üçün uyğun tipdən istifadə etmək lazımdır. Belə bir şəxs, onları əldə etmək üçün ümumi siyahı kimi aşağıdakı siyahıdan istifadə edə bilər. Lakin, aşağıdakı fikirləri istifadə etməyin. Bunun əvəzinə kodunuz üçün yaxşı olan hər şeyi istifadə edin.

  • Boolean ibtidai bir sətri / dəyişən istifadə edərkən, boş dəyəri və ya boş bir dəyər kimi istifadə dəyəri istifadə edin. Lazımsız polimorfizmdən qaçınmaq yaxşı olarsa, bütün kodunuzu yenidən işıqlandırmaq üçün kodunuzu yenidən yazmalısınız, bu da pis işləməyə səbəb ola bilər. Səsdən qərar istifadə edin!
  • Bir ədədi ibtidai olaraq daxil edilmiş bir sıra / dəyişən istifadə edərkən, boş dəyəri kimi 0 istifadə edin. İçəridə iki növ ədəd var: sürətli tam ədəd (2147483647-dən -2147483648-a qədər) və yavaş ikiqat üzən nöqtələr ( NaNInfinity dən başqa hər şey). Bir tam ədəd cütə düşəndə ​​tamsayı olaraq təsnif edilə bilməz.
  • Bir ibrətəli simli bir sıra / dəyişən istifadə edərkən boş dəyər kimi "" istifadə edin.
  • Symbol istifadə edərkən, gözləyin, niyə Symbol istifadə edirsiniz?!?! Performans üçün bad juju simvol. Istifadə etmək üçün proqramlaşdırılmış olan bütün Karakterlər daha sürətli kodsuz kod ilə nəticələnən simvolları istifadə etmək üçün yenidən programlana bilər. Rəmzlər həqiqətən təsirsiz bir meta şəkərdir.
  • Başqa bir şey istifadə edərkən null istifadə edin.

Lakin diqqətli olun! Bu, mövcud kodları pozmaq və / və ya qəribə səhvlər təqdim etmək ehtimalı olduğu üçün bütün mövcud kodu ilə bunu etməyə başlamayın. Əksinə, belə səmərəli təcrübə ən başından həyata keçirilməlidir və mövcud kodları konvertasiya edərkən, bu yeni tətbiqə köhnə kodu yeniləmək cəhdi faydalı olduğu kimi riskli ola bilər ki, bununla bağlı bütün xətlərin ikili, üçlü, dördlü yoxlanılması məsləhət görülür. .

770
12 февр. Cavab Dan 12 Feb 2014-02-12 20:48 '14 saat 20:48 2014-02-12 20:48

215
16 окт. cavab 16 oct . redsquare tərəfindən verilir . 2008-10-16 14:03 '08 saat 02:03 'da 2008-10-16 14:03

2018-07-21 yeniləmə: Uzun müddət mən bu cavabı xəcalətli hiss etdim, buna görə bir qədər toxunduğumu düşünürəm. Bu cavabın lazımsız uzun və çaşqın hissələrinin oxunmasını sürətləndirmək üçün bir az şərh, aydınlıq və formatlaşdırma.


KISA VERSİYA

Suala faktiki cavab

Başqalarının dediyinə görə delete .

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

Massiv bərabərdir

Serialdan delete . Bu istifadə Array.prototype.splice .

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

Uzun versiya

JavaScript bir OOP dilidir, buna görə hər şey bir sıra, diziler də daxil olmaqla. Beləliklə, mən xüsusi bir xəbərdarlığı qeyd etmək lazım olduğunu düşünürəm.

Seriallarda, sadə köhnə obyektlərdən fərqli olaraq, delete istifadəsi nizam şəklində zibil qutusunu yaradır və dizidəki "boşluq" yaradır.

 var array = [1, 2, 3, 4]; delete array[2];  

Gördüyünüz kimi, delete həmişə gözlənildiyi kimi işləmir. Qiymət yazılır, ancaq yaddaş yenidən bölüşdürülmür. Başqa sözlə, array[4] array[3] üçün hərəkət etmir. Array.prototype.unshift dan fərqli olaraq, bir elementin bir sıra daxilində yerləşdirir və hər şeyi dəyişir ( array[0] array[1] olur və s.),

Dürüstlük, undefined və qeyri- undefined yanaşı, bu tamamilə qəribədir - bu davranış təəccüblü olmamalıdır, çünki delete typeof sərt şəkildə bükülmüş növüdür və istifadə olunan obyektin növünə diqqət typeof , Array , Object alt sinifidir, xüsusilə dizilerle işləmək üçün nəzərdə tutulmuş üsullarla. Buna görə serialın təkrar yerləşdirilməsinə hazırlanan xüsusi bir işin olması üçün heç bir səbəb yoxdur, çünki bu işi sadəcə lazımsız işlərlə yavaşlatacaqdır. Geri baxarkən, mənim gözləntilərim qeyri-real idi.

Əlbəttə ki, məni təəccübləndirdi. Çünki "sıfır çöp" ə saldığım üçün salehliyimə haqq qazandırmaq üçün yazdım:

null və boş yerə xas olan təhlükələri və problemləri nəzərə almadan, serialın dəqiq olması lazımdırsa bu problemli ola bilər.

null silmək üçün dəhşətli bir bəhanədir - null yalnız yanlış istifadə olunduqda və "dəqiqlik" ilə heç bir əlaqəsi olmayan təhlükəlidir. Serialdan silinməməyin əsl səbəbi, ətrafdakı zibil dolu və çirkli məlumat strukturlarının tərk edilməsidir, çünki səhvən və çirkli olur.

Aşağıda olduqca uzun sürən bir skript yazısıdır, isterseniz "Həll" bölməsinə gedə bilərsiniz. Bu bölməni tərk etdiyim tək səbəbi budur ki, bəzi insanlar, ehtimal ki, gülməli olur və "komik" cavabı göndərən və sonra onu salıb "oğlan" olmaq istəmirəm. bütün "komik",

... Bu axmaq, bilirəm.

Kəskin və uzun müddətli ssenari PDP-11

Məsələn, JSON serialization istifadə edən bir webapp yaradın ki, dizideki sekmeler üçün istifadə olunan localStorage saxlaya bilərsiniz (bu halda localStorage ). Onlara da kodda ekranda çəkərkən onları "adlandırmaq" üçün serialın elementlərinin sayısal göstəricilərindən istifadə edirlər. Niyə bunu edirsiniz və "başlığı" saxlamırsınız? Çünki ... səbəblər.

Xahiş edirəm ki, 1960-cı ildən, UNIX-in fəaliyyət göstərən PDP-11 minicomputerini işləyən bir istifadəçinin tələbi ilə yaddaşı yadda saxlamağa çalışırsınız və JavaScript-nin brauzer dəstəyi ilə öz JavaScript-uyğun interfeysini yazdınız, çünki X11 sualdan çıxdı.

Göstərilən sətirdə delete marjinal skriptin getdikcə axmaq bir skripti serialın çirklənməsini aradan qaldıracaq və tətbiqdə daha sonra səhvlərə yol aça bilər. null yoxsa, avtomatik olaraq nömrələri atlayacaqsınız, nəticədə nümayiş sekmeleri [1] [2] [4] [5]...

 if (array[index] == null) continue; else title = (index + 1).toString();  

Bəli, bu, mütləq istədiyiniz şey deyil.

İndi faktiki dəyərlər dizidən oxunduqda artım üçün ikinci iteratorı, məsələn, j saxlaya bilərsiniz. Ancaq bu, null problemi həll etmir və hələ də bu Troll PDP-11 istifadəçisini sevirsiniz. Alas, kompüterində sadəcə bu son tamsayı nömrəsini saxlamaq üçün kifayət qədər yaddaşa malik deyil (dəyişkən genişlikli bir sıra idarə etmək üçün necə idarə etdiyini soruşma) .

Buna görə qəzəblə bir məktub göndərir.

 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 

İndi sonuncunuz. Bu adam davamlı ərizə ilə şikayət etdi və onu bağlamaq və ən yaxşı kompüterə getmək istədiyini söyləmisiniz.

Həll yolu: Array.prototype.splice

Xoşbəxtlikdən, dizilər indeksləri aradan qaldırmaq və yaddaşı Array.prototype.splice() üçün xüsusi bir üsula malikdir: Array.prototype.splice() . Bu kimi bir şey yaza bilərsiniz:

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

Və buna bənzər olaraq, Cənab PDP-11-dan razısınız. Hooray! (Hələ də ona xəbər verərdim ...)

Array.prototype.splice vs Array.prototype.slice

Mən bu iki oxşar funksiyalar arasındakı fərqi qeyd etmək vacibdir, çünki onlar həm də çox faydalıdır.

Array.prototype.splice (start, n)

.splice() bir sıra .splice() və uzaq göstəriciləri qaytarır. Dizidən indeksdən başlayaraq, startn elementləri kəsilir. Əgər n göstərilməyibsə, n = array.length - start ( n = array.length - start ) n = array.length - start sonra bütün array.

 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şlanğıc, bitmə)

.slice() qeyri-dağıdıcıdır və start end müəyyən göstəriciləri olan yeni bir sıra qaytarır. .splice() dəqiqləşdirilmədiyi halda, davranış .splice() ( end = array.length ) ilə eyni olacaq. Davranış bir az mürəkkəbdir, çünki səbəbsiz endekslər 0 əvəzinə 1 başlanır. Bu niyə baş verdiyini bilmirəm, amma bu. Əlavə olaraq, end <= start , nəticə boş bir sıra.

 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] 

Əslində bu, baş verən deyil, ancaq bu barədə düşünmək daha asandır. MDN məlumatlarına görə, əslində belə olur:

 // 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 

end göstərilən indeks sadəcə dilimdən çıxarılır. Qovluq içindəki göstəricilər dilimləndiyini göstərir. Hər halda, davranış intuitiv deyil və bu səhvlərin ədalətli payını "bir-birindən sonra" meydana .splice() , buna görə də sarmal funksiyasını .splice() davranışının .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]  function is_nan(num){ return typeof num === "number"  num !== num; } function is_number(num){ return !is_nan(num)  typeof num === "number"  isFinite(num); } 

Qeyd edək ki, sarğı funksiyası çox güclü tiplər üçündir və bir şey aradan qaldıqda null qaytarır. Bu, "3" tipli bir simli daxildir. Proqramçının onun növləri üzrə çalışqan olması qalır. Bu, yaxşı proqramlaşdırma praktikasına kömək etməlidir.

is_array() ilə bağlı yeniləmə

Bu (bu silinmiş) parçaya aiddir:

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

Belə ki, çıxdı ki, həqiqətən, bir dizinin həqiqətən bir sıra olub olmadığını müəyyən etmək üçün daxili bir yol var və bu ECMAScript 5 (dekabr 2009-cu ildə) təqdim olunan Array.isArray() ). Я нашел это, глядя на вопрос, есть ли вопрос о том, чтобы сообщать массивы с объектов, чтобы увидеть, было ли лучшее решение, чем мое, или добавить мое, если их не было. Итак, если вы используете версию JavaScript, которая раньше ECMA 5, там ваш полипол. Тем не менее, я настоятельно рекомендую не использовать is_array() , так как продолжение поддержки старых версий JavaScript означает продолжение поддержки старых браузеров, которые их реализуют, что означает поощрение использования небезопасного программного обеспечения и помещение пользователей под угрозу для вредоносного ПО. Поэтому, пожалуйста, используйте Array.isArray() . Используйте let и const . Используйте новые функции, которые добавляются в язык. Не используйте префиксы поставщиков. Удалите это полисплощадку IE с вашего сайта. Удалите этот XHTML <!CDATA[[... crap, тоже - мы переместились в HTML5 еще в 2014 году.). Чем раньше все откажутся от поддержки этих старых/эзотерических браузеров, тем скорее поставщики браузеров будут действительно следовать веб-стандарту и охватывают новые технологии, и чем скорее мы сможем перейти к более безопасной сети.

164
ответ дан Braden Best 18 сент. '12 в 3:56 2012-09-18 03:56

Старый вопрос, современный ответ. Используя деструктурирование объектов, ECMAScript 6 , это так же просто, как:

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

Или с образцом вопросов:

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

Вы можете увидеть его в действии в редакторе Babel try-out.


Edit:

Чтобы переназначить одну и ту же переменную, используйте let :

 let myObject = {"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"}; ({ regex, ...myObject } = myObject); console.log(myObject); 
126
ответ дан Koen. 08 нояб. '16 в 21:02 2016-11-08 21:02

Другой альтернативой является использование библиотеки Underscore.js .

Обратите внимание, что _.pick() и _.omit() возвращают копию объекта и не изменяют напрямую оригинальный объект. Присвоение результата исходному объекту должно выполнить трюк (не показан).

Ссылка: ссылка _.pick (объект, * ключи)

Вернуть копию объекта, отфильтровать, чтобы иметь только значения для белых ключей (или массива действительных ключей).

 var myJSONObject = {"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"}; _.pick(myJSONObject, "ircEvent", "method"); => {"ircEvent": "PRIVMSG", "method": "newURI"}; 

Ссылка: ссылка _.omit (объект, * ключи)

Верните копию объекта, отфильтрованную, чтобы опустить вложенные в черный список ключи (или массив ключей).

 var myJSONObject = {"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"}; _.omit(myJSONObject, "regex"); => {"ircEvent": "PRIVMSG", "method": "newURI"}; 

Для массивов, _.filter() и _.reject() могут использоваться аналогичным образом.

80
ответ дан Thaddeus Albers 24 мая '14 в 21:53 2014-05-24 21:53

Термин, который вы использовали в заголовке вопроса Remove a property from a JavaScript object , может быть интерпретирован несколькими способами. Один из них заключается в том, чтобы удалить его для всей памяти, а список объектных ключей или другой - просто удалить его из вашего объекта. Как уже упоминалось в некоторых других ответах, ключевое слово delete является основной частью. Скажем, у вас есть свой объект:

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

Если вы выполните:

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

результатом будет:

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

Вы можете удалить этот конкретный ключ из ваших объектных клавиш, например:

 delete myJSONObject["regex"]; 

Тогда ключ ваших объектов с помощью Object.keys(myJSONObject) будет выглядеть следующим образом:

 ["ircEvent", "method"] 

Но дело в том, что если вы заботитесь о памяти и хотите, чтобы весь объект удалялся из памяти, рекомендуется установить его значение null до удаления ключа:

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

Другим важным моментом здесь является осторожность в отношении других ссылок на один и тот же объект. Например, если вы создаете переменную типа:

 var regex = myJSONObject["regex"]; 

Или добавьте его как новый указатель на другой объект, например:

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

Тогда даже если вы удалите его из своего объекта myJSONObject , этот конкретный объект не будет удален из памяти, так как переменная regex и myOtherObject["regex"] все еще имеют свои значения. Тогда как мы могли бы точно удалить объект из памяти?

Ответ будет удалить все ссылки, которые у вас есть в вашем коде, указал на тот самый объект , а также не использовать var для создания новых ссылок на этот объект . Этот последний пункт в отношении операторов var является одной из наиболее важных проблем, с которыми мы обычно сталкиваемся, поскольку использование операторов var предотвратит удаление объекта, созданного.

Это означает, что в этом случае вы не сможете удалить этот объект, потому что вы создали переменную regex с помощью инструкции var , и если вы это сделаете:

 delete regex; //False 

Результат будет false , что означает, что ваш оператор удаления не был выполнен, как вы ожидали. Но если вы еще не создали эту переменную, и у вас была только myOtherObject["regex"] как ваша последняя существующая ссылка, вы могли бы сделать это, просто удалив ее, как:

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

Другими словами, объект JavaScript будет убит, как только в коде не будет указана ссылка на этот объект.


Update: Благодаря @AgentME:

Установка свойства null перед удалением не выполняется ничего (если объект не был закрыт объектом Object.seal и удаление не выполняется. Это обычно не так, если вы специально попробовать).

Чтобы получить дополнительную информацию по Object.seal : Object.seal()

42
ответ дан Mehran Hatami 12 февр. '14 в 9:29 2014-02-12 09:29

Предположим, что у вас есть объект, который выглядит так:

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

Удаление свойства объекта

Если вы хотите использовать весь массив staff , правильный способ сделать это:

 delete Hogwarts.staff; 

В качестве альтернативы вы также можете сделать это:

 delete Hogwarts['staff']; 

Аналогично, удаление всего массива студентов будет выполняться путем вызова delete Hogwarts.students; или delete Hogwarts['students']; .

Удаление индекса массива

Теперь, если вы хотите удалить одного сотрудника или ученика, процедура немного отличается, потому что оба свойства сами являются массивами.

Если вы знаете индекс своего сотрудника, вы можете просто сделать это:

 Hogwarts.staff.splice(3, 1); 

Если вы не знаете индекс, вам также нужно будет выполнить поиск по индексу:

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

Qeyd

Хотя вы технически можете использовать delete для массива, использование его приведет к получению неверных результатов при вызове, например, Hogwarts.staff.length позже. Другими словами, delete удалит элемент, но он не обновит значение свойства length . Использование delete также испортило бы вашу индексацию.

Таким образом, при удалении значений из объекта всегда сначала учитывайте, имеете ли вы дело с объектами или имеете дело с значениями массива и выбираете на основе соответствующей стратегии.

Если вы хотите поэкспериментировать с этим, вы можете использовать этот скрипт в качестве отправной точки.

33
21 февр. John Slegers tərəfindən verilmiş cavab 21 Feb. '16 в 21:09 2016-02-21 21:09

ECMAScript 2015 (или ES6) поставляется со встроенным Reflect объектом. Свойства объекта можно удалить, вызвав функцию Reflect.deleteProperty() с целевым объектом и ключом свойства в качестве параметров:

 Reflect.deleteProperty(myJSONObject, 'regex'); 

buna bərabərdir:

 delete myJSONObject['regex']; 

Но если свойство объекта не настраивается, оно не может быть удалено ни с помощью функции deleteProperty, ни при удалении оператора:

 let obj = Object.freeze({ prop: "value" }); let success = Reflect.deleteProperty(obj, "prop"); console.log(success); // false console.log(obj.prop); // value 

Object.freeze() делает все свойства объекта не настраиваемыми (помимо прочего). Функция deleteProperty (а также удалить оператор ) возвращает false при попытке удалить любые ее свойства. Если свойство настраивается, оно возвращает true , даже если свойство не существует.

Разница между delete и deleteProperty заключается в использовании строгого режима:

 "use strict"; let obj = Object.freeze({ prop: "value" }); Reflect.deleteProperty(obj, "prop"); // false delete obj["prop"]; // TypeError: property "prop" is non-configurable and can't be deleted 
32
ответ дан madox2 10 янв. '16 в 19:36 2016-01-10 19:36

Синтаксис распространения (ES6)

Для тех, кто нуждается в этом...

Чтобы завершить ответ @Koen в этой теме, на случай, если вы захотите удалить динамическую переменную, используя синтаксис распространения, вы можете сделать это так:

 const key = 'a'; const { [key]: foo, ...rest } = { a: 1, b: 2, c: 3 }; console.log(rest); // { b: 2, c: 3 } 

* foo будет новой переменной со значением a (которое равно 1).


ОБНОВЛЕНИЕ :
Существует несколько распространенных способов удаления свойства из объекта.
У каждого есть свои плюсы и минусы ( проверьте это сравнение производительности ):

Оператор удаления
Удобный для чтения и краткий, однако он может быть не лучшим выбором, если вы работаете с большим количеством объектов, поскольку его производительность не оптимизирована.

 delete obj[key]; 


Перераспределение
Более чем в 2 раза быстрее, чем delete , однако свойство не удаляется и может быть повторено.

 obj[key] = null; obj[key] = false; obj[key] = undefined; 


Оператор распространения
Этот оператор ES6 позволяет нам возвращать новый объект, исключая любые свойства, без изменения существующего объекта. Недостатком является то, что он имеет худшую производительность из вышеперечисленных и не рекомендуется использовать, когда вам нужно удалить много свойств одновременно.

 { [key]: val, ...rest } = obj; 
29
ответ дан Lior Elrom 12 сент. '18 в 21:39 2018-09-12 21:39

удалить оператор - лучший способ сделать это.

Живой пример для показа:

 var foo = {bar: 'bar'}; delete foo.bar; console.log('bar' in foo); // Logs false, because bar was deleted from foo. 
25
ответ дан Tarun Nagpal 28 апр. '15 в 8:14 2015-04-28 08:14

Я лично использую Underscore.js или Lodash для манипулирования объектами и массивами:

 myObject = _.omit(myObject, 'regex'); 
22
ответ дан emil 22 янв. '16 в 5:29 2016-01-22 05:29

Использование метода удаления - лучший способ сделать это, согласно описанию MDN, оператор delete удаляет свойство из объекта. Поэтому вы можете просто написать:

 delete myObject.regex; // OR delete myObject['regex']; 

Оператор delete удаляет заданное свойство из объекта. При успешном удалении оно вернет true, иначе будет возвращено false. Однако важно учитывать следующие сценарии:

  • Если свойство, которое вы пытаетесь удалить, не существует, delete не будет иметь никакого эффекта и вернет true

  • Если свойство с тем же именем существует в цепочке прототипов объекта, то после удаления объект будет использовать свойство из цепи прототипа (другими словами, удаление влияет только на собственные свойства).

  • Любое свойство, объявленное с помощью var, не может быть удалено из глобальной области или из области действия.

  • Таким образом, delete не может удалить какие-либо функции в глобальной области (независимо от того, является ли это частью определения функции или функции (выражение).

  • Функции, которые являются частью объекта (кроме
    глобальная область действия) можно удалить с помощью удаления.

  • Любое свойство, объявленное с let или const, не может быть удалено из области действия, в которой они были определены. Неконфигурируемые свойства не могут быть удалены. Сюда входят свойства встроенных объектов, таких как Math, Array, Object и свойства, которые создаются как неконфигурируемые с помощью методов Object.defineProperty().

Следующий фрагмент дает еще один простой пример:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/delete 

18
ответ дан Alireza 07 апр. '17 в 19:16 2017-04-07 19:16

Другое решение, использующее Array#reduce .

 const myObject = { ircEvent: 'PRIVMSG', method: 'newURI', regex: '^http://.*', }; const myNewObject = Object.keys(myObject).reduce((obj, key) => { key !== 'regex' ? obj[key] = myObject[key] : null; return obj; }, {}); console.log(myNewObject); 
18
ответ дан kind user 26 марта '17 в 18:19 2017-03-26 18:19

Эта статья очень старая, и я считаю ее очень полезной, поэтому я решил поделиться функцией unset, которую я написал, в случае, если кто-то еще увидит это сообщение и подумает, почему это не так просто, как в функции отмены PHP.

Причиной написания этой новой функции unset является сохранение индекса всех других переменных в этой hash_map. Посмотрите на следующий пример и посмотрите, как индекс "test2" не изменился после удаления значения из hash_map.

 function unset(unsetKey, unsetArr, resort){ var tempArr = unsetArr; var unsetArr = {}; delete tempArr[unsetKey]; if(resort){ j = -1; } for(i in tempArr){ if(typeof(tempArr[i]) !== 'undefined'){ if(resort){ j++; }else{ j = i; } unsetArr[j] = tempArr[i]; } } return unsetArr; } var unsetArr = ['test','deletedString','test2']; console.log(unset('1',unsetArr,true)); // output Object {0: "test", 1: "test2"} console.log(unset('1',unsetArr,false)); // output Object {0: "test", 2: "test2"} 
17
ответ дан talsibony 01 дек. '14 в 10:33 2014-12-01 10:33

Здесь есть много хороших @, но я просто хочу услышать, что при использовании delete для удаления свойства в JavaScript часто бывает полезно сначала проверить, существует ли это свойство для предотвращения ошибок.

məsələn

 var obj = {"property":"value", "property2":"value"}; if (obj  obj.hasOwnProperty("property2")) { delete obj.property2; } else { //error handling } 

Из-за динамического характера JavaScript часто бывают случаи, когда вы просто не знаете, существует ли свойство или нет. Проверка существования obj до также гарантирует, что вы не выкидываете ошибку из-за вызова функции hasOwnProperty() объекта undefined.

Извините, если это не добавило вашего конкретного варианта использования, но я считаю, что это хороший дизайн для адаптации при управлении объектами и их свойствами.

16
ответ дан Willem 15 сент. '14 в 3:48 2014-09-15 03:48

Используя ramda # dissoc , вы получите новый объект без атрибута regex :

 const newObject = R.dissoc('regex', myObject); // newObject !== myObject 

Вы также можете использовать другие функции для достижения того же эффекта - опустить, выбрать,...

12
ответ дан zatziky 28 нояб. '16 в 18:14 2016-11-28 18:14

Попробуйте использовать следующий метод. Назначьте значение свойства Object undefined . Затем stringify объект и parse .

11
ответ дан Mohammed Safeer 06 июля '16 в 17:51 2016-07-06 17:51

Если вы хотите удалить свойство, глубоко вложенное в объект, вы можете использовать следующую рекурсивную функцию с указанием пути к свойству в качестве второго аргумента:

 var deepObjectRemove = function(obj, path_to_key){ if(path_to_key.length === 1){ delete obj[path_to_key[0]]; return true; }else{ if(obj[path_to_key[0]]) return deepObjectRemove(obj[path_to_key[0]], path_to_key.slice(1)); else return false; } }; 

Məsələn:

 var a = { level1:{ level2:{ level3: { level4: "yolo" } } } }; deepObjectRemove(a, ["level1", "level2", "level3"]); console.log(a); //Prints {level1: {level2: {}}} 
11
ответ дан ayushgp 23 июня '16 в 12:38 2016-06-23 12:38

Использование ES6:

(Оператор Destructuring + Spread)

  const myObject = { regex: "^http://.*", b: 2, c: 3 }; const { regex, ...noRegex } = myObject; console.log(noRegex); // => { b: 2, c: 3 } 
8
ответ дан Srinivas 23 июля '18 в 18:52 2018-07-23 18:52

Вы можете просто удалить любое свойство объекта, используя ключевое слово delete .

Məsələn:

 var obj = {key1:"val1",key2:"val2",key3:"val3"} 

Чтобы удалить любое свойство, например key1 , используйте ключевое слово delete следующим образом:

 delete obj.key1 

Или вы также можете использовать массивную нотацию:

 delete obj[key1] 

Ссылка: MDN .

7
ответ дан Kalpesh Patel 07 апр. '16 в 8:46 2016-04-07 08:46

Рассмотрите возможность создания нового объекта без свойства "regex" , поскольку исходный объект всегда может ссылаться на другие части вашей программы. Таким образом, вам следует избегать манипулирования им.

6
ответ дан ideaboxer 23 окт. '17 в 13:06 2017-10-23 13:06

Утверждение Дэна о том, что "удаление" происходит очень медленно, и поставленный в нем тест был усомнился. Поэтому я сам проверил тест в Chrome 59. Кажется, что "delete" примерно в 30 раз медленнее:

 var iterationsTotal = 10000000; // 10 million var o; var t1 = Date.now(),t2; for (let i=0; i<iterationsTotal; i++) { o = {a:1,b:2,c:3,d:4,e:5}; delete oa; delete ob; delete oc; delete od; delete oe; } console.log ((t2=Date.now())-t1); // 6135 for (let i=0; i<iterationsTotal; i++) { o = {a:1,b:2,c:3,d:4,e:5}; oa = ob = oc = od = oe = undefined; } console.log (Date.now()-t2); // 205 

Обратите внимание, что я специально выполнял несколько операций "удалить" в одном цикле цикла, чтобы минимизировать эффект, вызванный другими операциями.

6
ответ дан Chong Lip Phang 26 июля '17 в 10:19 2017-07-26 10:19

Object.assign() и Object.keys() и Array.map()

6
ответ дан xgqfrms-gildata 19 сент. '17 в 11:37 2017-09-19 11:37

5
ответ дан xiang 06 февр. '18 в 7:28 2018-02-06 07:28

Попробуйте это

 delete myObject['key']; 
5
ответ дан codemirror 26 мая '17 в 9:58 2017-05-26 09:58

Здравствуйте, Вы можете попробовать этот простой вид

 var obj = []; obj.key1 = {name: "John", room: 1234}; obj.key2 = {name: "Jim", room: 1234}; delete(obj.key1); 
5
ответ дан Dhaval Gohel 26 мая '17 в 12:28 2017-05-26 12:28

Удаление имущества в JavaScript

На этой странице представлено множество различных вариантов, а не потому, что большинство вариантов неверны, или потому, что ответы являются дубликатами, а потому, что соответствующий метод зависит от ситуации, в которой вы находитесь, и целей задач, которые вы и/или вы команда пытается выполнить. Чтобы ответить на ваш вопрос однозначно, нужно знать:

  1. Версия ECMAScript, на которую вы нацеливаетесь
  2. Диапазон типов объектов, которые вы хотите удалить, и типы имен свойств, которые вам нужно упускать (только строки) Символы? Слабые ссылки, сопоставленные с произвольными объектами? Все это были типы указателей свойств в JavaScript уже много лет )
  3. Этимы/шаблоны программирования, которые вы и ваша команда используете. Поддерживаете ли вы функциональные подходы, а мутация - в вашей команде, или вы используете дикие западные мутативные объектно-ориентированные методы?
  4. Вы хотите добиться этого в чистом JavaScript или хотите ли вы использовать стороннюю библиотеку?

После ответа на эти четыре вопроса в JavaScript есть по существу четыре категории "удаление собственности" на JavaScript, чтобы соответствовать вашим целям. Они есть:

Удаление мутативного объекта, небезопасное

Эта категория предназначена для работы с объектными литералами или экземплярами объектов, когда вы хотите сохранить/продолжить использовать исходную ссылку и не используете в своем коде функциональные принципы без состояния. Пример синтаксиса в этой категории:

 'use strict' const iLikeMutatingStuffDontI = { myNameIs: 'KIDDDDD!', [Symbol.for('amICool')]: true } delete iLikeMutatingStuffDontI[Symbol.for('amICool')] // true Object.defineProperty({ myNameIs: 'KIDDDDD!', 'amICool', { value: true, configurable: false }) delete iLikeMutatingStuffDontI['amICool'] // throws 

Эта категория является самой старой, самой простой и наиболее широко распространенной категорией удаления собственности. Он поддерживает индексы Symbol array в дополнение к строкам и работает в каждой версии JavaScript, за исключением самой первой версии. Однако это мутация, которая нарушает некоторые принципы программирования и имеет последствия для производительности. Это также может привести к неперехваченным исключениям при использовании в неконфигурируемых свойствах в строгом режиме .

Исключение свойств строки на основе Rest

Эта категория предназначена для работы с экземплярами простого объекта или массива в новых вариантах ECMAScript, когда требуется не-мутирующий подход, и вам не нужно учитывать ключи Symbol:

 const foo = { name: 'KIDDDDD!', [Symbol.for('isCool')]: true } const { name, ...coolio } = foo // coolio doesn't have "name" const { isCool, ...coolio2 } = foo // coolio2 has everything from 'foo' because 'isCool' doesn't account for Symbols :( 

Удаление мутативного объекта, безопасное

Эта категория предназначена для работы с объектными литералами или экземплярами объектов, когда вы хотите сохранить/продолжать использовать исходную ссылку, защищая от исключений, возникающих при неконфигурируемых свойствах:

 'use strict' const iLikeMutatingStuffDontI = { myNameIs: 'KIDDDDD!', [Symbol.for('amICool')]: true } Reflect.deleteProperty(iLikeMutatingStuffDontI, Symbol.for('amICool')) // true Object.defineProperty({ myNameIs: 'KIDDDDD!', 'amICool', { value: true, configurable: false }) Reflect.deleteProperty(iLikeMutatingStuffDontI, 'amICool') // false 

Кроме того, в то время как мутация объектов на месте не является апатридом, вы можете использовать функциональный характер Reflect.deleteProperty для частичного приложения и других функциональных методов, которые невозможны с инструкциями delete .

Бездействие на основе синтаксиса

Эта категория предназначена для работы с экземплярами простого объекта или массива в новых вариантах ECMAScript, когда требуется не-мутирующий подход, и вам не нужно учитывать ключи Symbol:

 const foo = { name: 'KIDDDDD!', [Symbol.for('isCool')]: true } const { name, ...coolio } = foo // coolio doesn't have "name" const { isCool, ...coolio2 } = foo // coolio2 has everything from 'foo' because 'isCool' doesn't account for Symbols :( 

Исключение имущества на базе библиотеки

Эта категория, как правило, обеспечивает большую функциональную гибкость, включая учет символов и исключение более одного свойства в одном заявлении:

 const o = require("lodash.omit") const foo = { [Symbol.for('a')]: 'abc', b: 'b', c: 'c' } const bar = o(foo, 'a') // "'a' undefined" const baz = o(foo, [ Symbol.for('a'), 'b' ]) // Symbol supported, more than one prop at a time, "Symbol.for('a') undefined" 
4
ответ дан james_womack 14 дек. '17 в 5:35 2017-12-14 05:35

Использование lodash

 import omit from 'lodash/omit'; const prevObject = {test: false, test2: true}; // Removes test2 key from previous object const nextObject = omit(prevObject, 'test2'); 

Использование Ramda

 R.omit(['a', 'd'], {a: 1, b: 2, c: 3, d: 4}); //=> {b: 2, c: 3} 
4
ответ дан johndavedecano 14 сент. '17 в 17:14 2017-09-14 17:14

@johnstock , мы также можем использовать концепцию прототипирования JavaScript, чтобы добавить метод к объектам для удаления любого переданного ключа, доступного в вызывающем объекте.

Выше ответы приветствуются.

 var myObject = { "ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*" }; // 1st and direct way delete myObject.regex; // delete myObject["regex"] console.log(myObject); // { ircEvent: 'PRIVMSG', method: 'newURI' } // 2 way - by using the concept of JavaScript prototyping concept Object.prototype.removeFromObjectByKey = function(key) { // If key exists, remove it and return true if(this[key] !== undefined) { delete this[key] return true; } // Else return false return false; } var isRemoved = myObject.removeFromObjectByKey('method') console.log(myObject) // { ircEvent: 'PRIVMSG' } // More examples var obj = { a: 45, b: 56, c: 67} console.log(obj) // { a: 45, b: 56, c: 67 } // Remove key 'a' from obj isRemoved = obj.removeFromObjectByKey('a') console.log(isRemoved); //true console.log(obj); // { b: 56, c: 67 } // Remove key 'd' from obj which doesn't exist var isRemoved = obj.removeFromObjectByKey('d') console.log(isRemoved); // false console.log(obj); // { b: 56, c: 67 } 
3
ответ дан hygull 24 мая '18 в 21:42 2018-05-24 21:42
  • 1
  • 2

Другие вопросы по меткам или Задайте вопрос