Paano alisin ang isang ari-arian mula sa isang JavaScript na bagay?

Sabihin nating lumikha ako ng isang bagay tulad nito:

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

Ano ang pinakamahusay na paraan upang alisin ang property ng regex , upang makumpleto ang isang bagong myObject tulad nito:

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

Narito ito:

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

Demo

kangax wrote isang hindi kapani-paniwa>delete pahayag sa kanyang blog, Understanding Deletion .  Lubos na inirerekomenda. 

7292
16 окт. ang sagot ay binibigyan ng nickf 16 oct. 2008-10-16 13:58 '08 at 1:58 pm 2008-10-16 13:58

Ang operator ay nag- delete inaasahang pagbabawas!

Tingnan ang benchmark .

Tanggalin ay ang tanging sigurado na paraan upang alisin ang mga katangian ng isang bagay nang wa>~ 100 beses na mas mabagal kumpara sa "alternatibong" setting ng object[key] = undefined .

Ang alternatibong ito ay hindi ang tamang sagot sa tanong na ito! Ngunit, kung gagamitin mo ito nang may pag-aalaga, maaari mong makabuluhang mapabilis ang i>delete sa mga loop, at mayroon kang mga problema sa pagganap, basahin ang detalyadong paliwanag.

Kailan dapat delete ang gagamitin at kailan ang tinukoy na halaga ay hindi undefined ?

Ang isang bagay ay maaaring isaa>

Gumamit ng delete kapag nagpasa ka ng object na resulta sa isang code kung saan wala kang kontrol (o kapag hindi ka tiwala sa iyong koponan o sa iyong sarili).

Inaalis nito ang susi mula sa hash card .

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

Kung hindi ka sigurado tungkol sa pagganap, gamitin ang di- undefined opsyon . Maaari itong sineseryoso nakakaapekto sa iyong code.

Ang susi ay nananatili sa lugar nito sa hashmap , tanging ang halaga ay pinalitan ng hindi undefined . Unawain na ang for..in cycle ay pupunta pa rin sa pamamagitan ng key na ito.

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

Gamit ang pamamaraang ito, hindi lahat ng mga pamamaraan para sa pagtukoy sa pag-aari ng ari-arian ay gagana gaya ng inaasahan.

Gayunpaman, ang code na ito:

object.field === undefined

ay gagana nang katumbas para sa parehong pamamaraan.

mga pagsubok

Summing up, may mga pagkakaiba sa mga paraan ng pagtukoy ng pagkakaroon ng isang ari-arian at para sa for..in loop.

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. *'); 

Mag-ingat sa mga paglabas ng memorya!

Bagaman ang obj[prop] = undefined mas mabilis kaysa sa delete obj[prop] , isa pang mahalagang pagsasaa>obj[prop] = undefined ay maaaring hindi laging may kaugnayan. delete obj[prop] nagtanggal prop mula sa obj at binubura ito mula sa memorya, habang obj[prop] = undefined nagtatakda lamang ang prop halaga sa hindi undefined na nag-iiwan ng mga prop pa sa memorya. Samakatuwid, sa mga sitwasyon kung saan may maraming mga susi na nilikha at tinanggal, ang paggamit ng obj[prop] = undefined maaaring humantong sa mahusay na memorya ng pagkakapare-pareho (nagiging sanhi ng pag-freeze ng pahina) at potensyal na isang error sa labas ng memorya. Suriin ang sumusunod na code.

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

Sa kodigo sa itaas, lamang nodeRecords[i][lastTime] = undefined; ay magreresulta sa isang napakalaking pagtagas ng memory dahil sa bawat frame ng animation. Ang bawat frame, ang lahat ng mga elemento ng 65536 DOM ay kukuha ng isa pang 65,536 na indibidwal na mga puwang, ngunit ang nakaraang mga puwang na 65,536 ay itatakda lamang sa hindi natukoy, na nag-iiwan sa kanila na nakabitin sa memorya. Magpatuloy, subukang patakbuhin ang code sa itaas sa console at makita para sa iyong sarili. Pagkatapos ng sapilitang error sa memorya, subukang patakbuhin muli ito, maliban sa susunod na bersyon ng code, na gumagamit ng delete operator sa halip.

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

Tulad ng makikita mula sa snippet code sa itaas, mayroong i>delete operator. Gayunpaman, huwag kang mag-alala tungkol sa problemang ito. Ito ay magiging isang problema lamang sa mga bagay ng mahabang buhay, na patuloy na nagdaragdag ng mga bagong susi sa kanila. Sa anumang iba pang mga kaso (ito ay halos bawat kaso sa tunay na programming), ito ay pinaka-maipapayo na gamitin obj[prop] = undefined . Ang pangunahing layunin ng seksyon na ito ay upang maipakita lamang ang iyong pansin sa katotohanan na sa mga bihirang kaso ito ay nagiging isang problema sa iyong code, pagkatapos ay maaari mong mas madaling maunawaan ang problema at, samakatuwid, huwag mag-aksaya ng oras sa pag-aaral ng iyong code upang mahanap at maunawaan ang problemang ito.

Hindi laging naka-set sa hindi undefined

Ang isang aspeto ng Javascript na mahalaga upang isaa>

 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 

Gayunpaman, mayroong dalawang pangunahing mga problema na hindi maaaring alisin kapag gumagamit ng mga polymorphic arrays:

  1. Sila ay mabagal at hindi epektibo. Kapag na-access ang isang tiyak na index, sa halip na lamang sa pagkuha ng isang pandaigdigang uri para sa isang array, ang browser ay dapat na makatanggap ng isang uri batay sa isang index, kung saan ang bawat index ay nag-iimbak ng karagdagang metadata ng uri nito.
  2. Pagkatapos ng polymorphic, laging polymorphic. Kapag ang isang array ay ginawa polymorphic, polymorphism ay hindi maaaring kinansela sa Webkit browser. Kaya, kahit na ibalik mo ang isang polymorphic array bi>

Maaari mong ihalintulad ang polymorphism ng pagkagumon sa droga. Sa unang sulyap, tila hindi kapani-paniwa>

Ngunit, paano tumutukoy ang pagkakatulad ng gamot upang delete operasyon? Ang sagot ay naglalaman ng huling linya ng code sa snippet sa itaas. Kaya hayaan itong mabago, oras na ito na may isang iba ng kahulugan.

 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 

Magbayad ng pansin. bar[1] = "" ay hindi nagiging sanhi ng polymorphism, samanta>bar[1] = undefined . Samakatuwid, laging kinakai>

  • Kapag gumagamit ng isang array / variable na ipinasok sa isang primitibong Boolean, gamitin ang halaga na false o hindi undefined bi>
  • Kapag gumagamit ng isang array / variable na ipinasok sa isang numerong primitive, gamitin ang 0 bi>NaN at Infinity ). Kapag ang isang integer ay bumaba sa isang double, hindi ito maaaring mauri bi>
  • Kapag gumagamit ng array / variable na ipinasok sa isang primitive na string, gamitin ang "" bi>
  • Kapag ginagamit ang Simbolo, maghintay, bakit ginagamit mo ang Simbolo?!?! Masamang juju character para sa pagganap. Ang lahat ng mga character na programmed na gamitin ay maaaring reprogrammed upang hindi gumamit ng mga character, na nagreresulta sa mas mabilis na code-free code. Ang mga simbolo ay talagang isang hindi mabisang meta-asukal.
  • Kapag gumagamit ng anumang bagay, gamitin null .

Gayunpaman, maging maingat! Huwag simulan ang paggawa nito sa lahat ng umiiral na code, dahil malamang na masira ang naturang umiiral na code at / o kasalukuyan ang mga kakaibang error. Sa halip, ang naturang epektibong pagsasanay ay dapat na ipatupad mula pa sa simula, at kapag nagko-convert ng umiiral na code inirerekomenda na mag-double, triple, quadruple check ng lahat ng mga linya na may kaugnayan sa ito, bi>

770
12 февр. Sumagot Dan 12 Peb 2014-02-12 20:48 '14 sa 20:48 2014-02-12 20:48

215
16 окт. sumagot na ibinigay sa redsquare Oct 16 2008-10-16 14:03 '08 at 2:03 pm 2008-10-16 14:03

I-update ang 2018-07-21: Sa loob ng mahabang panahon ay napahiya ako tungkol sa sagot na ito, kaya sa palagay ko hinawakan ko ito nang kaunti. Lamang ng isang maliit na komento, paglilinaw at pag-format upang pabilisin ang pagbabasa ng mga hindi kinakai>


SHORT VERSION

Ang tunay na sagot sa tanong

Tulad ng sinabi ng iba, maaari mong gamitin ang delete .

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

Napakalaking katumbas

Huwag delete mula sa array. Array.prototype.splice paggamit na ito Array.prototype.splice .

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

LONG VERSION

JavaScript ay isang OOP na wika, kaya lahat ng bagay ay isang bagay, kabi>

Sa mga arrays, sa kaibahan sa mga simpleng lumang bagay, ang paggamit ng mga delete dahon ng basura sa anyo ng null , na lumilikha ng isang "butas" sa array.

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

Tulad ng iyong nakikita, delete ang hindi laging gumagana gaya ng inaasahan. Ang halaga ay mapapasukin, ngunit ang memorya ay hindi ipagkakalat. Sa ibang salita, ang array[4] ay hindi lumilipat sa array[3] . Hindi tulad ng Array.prototype.unshift , na Array.prototype.unshift isang elemento sa simula ng isang array at nagbabago ang lahat ng bagay ( array[0] ay nagiging array[1] , atbp.),

Sa totoo >null at hindi undefined - na kung saan, ito ay lubos na kakaiba - ang pag-uugali na ito ay hindi dapat maging kamangha-mangha, dahil ang delete ay isang unary operator, tulad ng typeof , na rigidly na napilitan sa wika at hindi dapat pag-aalaga ang tungkol sa uri ng bagay na ginamit, Array ay isang subclass ng Object may mga pamamaraan na partikular na dinisenyo para sa pagtatrabaho sa mga arrays. Samakatuwid, wa>delete na magkaroon ng isang espesyal na kaso na inihanda upang ibalik ang isang array, dahil ito ay makapagpabagal lamang sa trabaho na may hindi kai>

Siyempre nagulat ako sa akin. Dahil sinulat ko ito upang bigyang-katwiran ang aking krusada laban sa "wa>

Hindi pinapansin ang mga panganib at mga problema na likas sa null at nasayang na espasyo, ito ay maaaring maging problema kung ang array ay kai>

Aling ay isang kahila-hilakbot na dahilan para sa pag-alis ng null s-- null ay mapanganib lamang kung ginamit nang mali at wa>delete mula sa isang array ay dahil ang pag-alis ng mga puno ng basura at maruruming istraktura ng data sa paligid ay marumi at madaling kapitan ng sakit.

Nasa ibaba ang isang contrived script na nakakakuha ng masyadong mahaba, kaya maaari kang pumunta sa seksyon ng "Solusyon" kung gusto mo. Ang tanging dahilan na iniiwan ko ang seksyon na ito ay sa tingin ko ang i>

... Ito ay bobo, alam ko.

Ang contrived at pang-mataga>

Halimbawa, ipagpalagay na lumikha ka ng isang webapp na gumagamit ng JSON serialization upang iimbak ang array na ginamit para sa mga tab sa isang string ( localStorage sa kasong ito). Ipaalam din sa kanila na ang code ay gumagamit ng numeric indices ng mga elemento ng array para sa "pagbibigay ng pangalan" sa kanila kapag gumuhit sa screen. Bakit mo ginagawa ito at hindi >

Well, ipaalam sa akin na sinusubukan mong i-save ang memorya sa kahilingan ng isang gumagamit na nagpapatakbo ng PDP-11 minicomputer mula noong 1960, tumatakbo UNIX, at nagsulat ng sarili nitong JavaScript na katugmang interface na may JavaScript browser support, dahil ang X11 ay hindi sa labas ng tanong.

Ang isang mas bobo script ng marginal script gamit ang delete sa tinukoy na array ay null polusyon ng array at malamang na humantong sa mga error sa application mamaya. At kung i-check mo ang null , awtomatiko itong laktawan ang mga numero, sa resulta na ang mga nakikitang mga tab ay mukhang [1] [2] [4] [5]...

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

Oo, hindi talaga ito ang gusto mo.

Ngayon ay maaari mong i-save ang pangalawang iterator, halimbawa j , sa pagdagdag lamang kapag aktwal na mga halaga ay basahin mula sa array. Ngunit tiyak na hindi ito malulutas ang null problema, at gusto mo pa rin ang user na ito ng Troll PDP-11. Alas, ang kanyang computer ay wa>(huwag magtanong kung paano siya namamahala upang mahawakan ang isang array ng variable width ...) .

Kaya nagpadala siya sa iyo ng sulat sa galit:

 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 

Ngayon ikaw ay nasa iyong katapusan. Ang guy na ito ay patuloy na nagreklamo tungkol sa iyong aplikasyon, at nais mong sabihin sa kanya upang mai-shut up at pumunta sa pinakamahusay na computer.

Solusyon: Array.prototype.splice

Sa kabutihang palad, ang mga arrays ay may isang espesyal na paraan para sa pag-alis ng mga index at reallocating memory: Array.prototype.splice() . Maaari kang magsulat ng ganito:

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

At ganoon >(Gusto ko pa rin sabihin sa kanya kahit na ...)

Array.prototype.splice vs Array.prototype.slice

Mahalaga kong tandaan ang pagkakaiba sa pagitan ng dalawang mga katulad na pinangalanang function na, dahil ang mga ito ay parehong kapaki-pakinabang.

Array.prototype.splice (simula, n)

.splice() mutates isang array at nagbabalik ng mga remote na indeks. Ang array ay gupitin simula sa index, start at n elemento ay hiwa. Kung n ay hindi tinukoy, ang buong array pagkatapos start n = array.length - start ( 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 (simula, wakas)

.slice() ay hindi mapanira at nagbabalik ng isang bagong array na naglalaman ng tinukoy na mga indeks mula start hanggang end . Kung end natitirang bahagi ay hindi natukoy, ang pag-uugali ay magiging katulad ng .splice() ( end = array.length ). Ang pag-uugali ay medyo kumplikado, dahil sa i>end nagsisimula sa 1 sa halip na 0. Hindi ko alam kung bakit ito nangyayari, ngunit ito ay. Bi>end <= start , ang resulta ay isang wa>

 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] 

Sa katunayan, hindi ito ang nangyayari, ngunit mas madaling isipin ito. Ayon sa MDN, ito ang tunay na nangyayari:

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

Ang index na tinukoy sa pamamagitan ng end ay ibinubukod lamang mula sa slice. Ang mga indeks sa mga panaklong ay nagpapahiwatig kung ano ang ini-hiwa. Sa anumang kaso, ang pag-uugali ay hindi madaling maunawaan at dahil sa ang katunayan na ito ay nagiging sanhi ng makatarungang bahagi ng mga error na "isa pagkatapos ng isa", upang .splice() mo itong kapaki-pakinabang upang gawing higit ang .splice() uugali ng .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); } 

Tandaan na ang pag-andar sa wrapper ay para sa mga napakalakas na uri at babalik null kung may isang bagay na hindi pinagana. Kabi>"3" . Ito ay nananatili para sa programmer na maging masigasig sa kanyang mga uri. Ito ay dapat mag-ambag sa magandang programming practice.

I-update ang tungkol sa is_array()

Nalalapat ito sa fragment na ito (na natanggal na ngayon):

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

Kaya, tulad nito, talagang mayroong isang built-in na paraan upang malaman kung ang array ay talagang isang array, at ito ay Array.isArray() , na ipinakilala sa ECMAScript 5 (Disyembre 2009). Я нашел это, глядя на вопрос, есть ли вопрос о том, чтобы сообщать массивы с объектов, чтобы увидеть, было ли лучшее решение, чем мое, или добавить мое, если их не было. Итак, если вы используете версию 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 };