Як выдаліць ўласцівасць з аб'екта JavaScript?

Скажам, я ствараю аб'ект наступным чынам:

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

Які найлепшы спосаб выдаліць ўласцівасць regex , каб у выніку атрымаць новы myObject наступным чынам:

 var myObject = { "ircEvent": "PRIVMSG", "method": "newURI" }; 
5276
16 окт. зададзены johnstok 16 каст. 2008-10-16 13:57 '08 у 13:57 2008-10-16 13:57
@ 37 адказаў
  • 1
  • 2

Вось так:

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

Demo

kangax напісаў неверагодна падрабязнае паведамленне ў блогу пра заяву delete ў сваім блогу, Разуменне выдалення .  Настойліва рэкамендуецца. 

7292
16 окт. адказ дадзены nickf 16 каст. 2008-10-16 13:58 '08 у 13:58 2008-10-16 13:58

delete аператара нечакана запавольваецца!

Паглядзіце на бенчмарк .

Выдаліць - адзіны верны спосаб выдаліць ўласцівасці аб'екта без якіх-небудзь рэшткаў, але ён працуе ~ у 100 разоў больш павольна, у параўнанні з яго "альтэрнатыўным", які ўстанаўлівае object[key] = undefined .

Гэтая альтэрнатыва не з'яўляецца правільным адказам на гэтае пытанне! Але, калі вы выкарыстоўваеце яго з асцярогай, вы можаце значна паскорыць некаторыя алгарытмы. Калі вы выкарыстоўваеце delete у цыклах, і ў вас праблемы з прадукцыйнасцю, прачытайце падрабязнае тлумачэнне.

Калі варта выкарыстоўваць delete і калі зададзенае значэнне undefined ?

Аб'ект можа разглядацца як набор пар ключ-значэнне. Тое, што я называю "значэннем", з'яўляецца прымітыўным ці спасылкай на іншы аб'ект, звязаны з гэтым "ключом".

Выкарыстоўвайце delete , калі вы перадаеце аб'ект выніку ў код, на якім у вас няма кантролю (ці калі вы не ўпэўненыя ў сваёй камандзе або сабе).

Ён выдаляе ключ з хэш-карты.

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

Калі вы не ўпэўненыя ў прадукцыйнасці, выкарыстоўвайце параметр undefined . Гэта можа сур'ёзна паўплываць на ваш код.

Ключ застаецца на сваім месцы ў hashmap, толькі значэнне замяняецца undefined . Зразумейце, што for..in цыкл усё роўна будзе перабіраць гэты ключ.

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

Выкарыстоўваючы гэты метад, не ўсе спосабы вызначэння ўласцівасці існавання будуць працаваць, як чакалася.

Аднак гэты код:

object.field === undefined

будуць паводзіць сябе эквівалентна для абодвух метадаў.

тэсты

Падводзячы вынік, існуюць адрозненні ў спосабах вызначэння існавання ўласцівасці і for..in цыклу 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. *'); too  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. *'); in  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. *'); 

Сцеражыцеся уцечак памяці!

Хоць obj[prop] = undefined хутчэй, чым delete obj[prop] , яшчэ адна важная меркаванне складаецца ў тым, што obj[prop] = undefined не заўсёды можа быць дарэчным. delete obj[prop] выдаляе prop з obj і сцірае яго з памяці, тады як obj[prop] = undefined проста ўсталёўвае значэнне prop для undefined якое пакідае prop яшчэ ў памяці. Таму ў сітуацыях, калі існуе шмат ключоў, якія ствараюцца і выдаляюцца, выкарыстанне obj[prop] = undefined можа прывесці да дарагой ўзгодненасці памяці (прымушаючы старонку замярзаць) і патэнцыйна памылцы па-за памяці. Вывучыце наступны код.

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

У прыведзеным вышэй кодзе проста робіцца nodeRecords[i][lastTime] = undefined; прывядзе да масіўнай ўцечкі памяці з-за кожнага кадра анімацыі. Кожны кадр, усе элементы 65536 DOM будуць займаць яшчэ 65536 асобных слотаў, але папярэднія слоты 65536 будуць устаноўлены толькі на нявызначаныя, што пакідае іх вісяць ў памяці. Працягвайце, паспрабуйце запусціць вышэйзгаданы код у кансолі і пераканайцеся самі. Пасля прымусовай памылкі з-за памяці паспрабуйце запусціць яе нанова, за выключэннем наступнай версіі кода, у якой замест гэтага выкарыстоўваецца аператар delete .

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

Як відаць з прыведзенага вышэй фрагмента кода, існуюць некаторыя рэдкія прыдатныя варыянты выкарыстання для аператара delete . Аднак не турбуйцеся пра гэтую праблему занадта шмат. Гэта стане праблемай толькі з аб'ектамі працяглага жыцця, якія пастаянна дадаюць да іх новыя ключы. У любым іншым выпадку (гэта амаль кожны выпадак у рэальным праграмаванні), найбольш мэтазгодна выкарыстоўваць obj[prop] = undefined . Асноўная мэта гэтага падзелу - проста звярнуць вашу ўвагу на тое, каб у рэдкіх выпадках гэта стала праблемай у вашым кодзе, тады вы можаце больш лёгка зразумець праблему і, такім чынам, не марнаваць час на аналіз свайго кода, каб знайсці і зразумець гэтую праблему.

Не заўсёды зададзена для undefined

Адным з аспектаў Javascript, які важна разгледзець, з'яўляецца палімарфізм. Палімарфізм - гэта прысваенне аднолькавых зменных / слотаў ў аб'ектах розных тыпаў, як паказана ніжэй.

 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 browser 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 its entries have the 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 

Тым не менш, існуюць дзве асноўныя праблемы, якія немагчыма ліквідаваць пры выкарыстанні паліморфных масіваў:

  1. Яны павольныя і неэфектыўныя. Пры доступе да вызначанага індэксе замест таго, каб проста атрымліваць глабальны тып для масіва, браўзэр замест гэтага павінен атрымліваць тып на аснове індэкса, у якім кожны індэкс захоўвае дадатковыя метададзеныя яго тыпу.
  2. Пасля паліморфнага, заўсёды паліморфнага. Калі масіў зроблены паліморфны, палімарфізм не можа быць адменены ў браўзэрах Webkit. Такім чынам, нават калі вы адновіце паліморфны масіў як неполиморфный, ён усё роўна будзе захоўвацца браўзэрам у выглядзе паліморфнага масіва.

Можна прыпадобніць палімарфізм наркатычнай залежнасці. На першы погляд, гэта здаецца неверагодна прыбытковым: прыгожы даволі пухнаты код. Затым кодэр ўводзіць свой масіў у прэпарат палімарфізму. Імгненна паліморфных матрыца становіцца менш эфектыўнай, і яна ніколі не можа стаць такой жа эфектыўнай, як і раней, з таго часу, як яна наркотизирована. Каб суаднесці такую ​​акалічнасць з рэальнай жыццём, хто-небудзь з какаіну можа нават не мець магчымасці кіраваць просты дзвярной ручкай, а тым больш не ў стане разлічыць лічбы PI. Аналагічна, масіў на прэпараце палімарфізму не можа быць гэтак эфектыўным, як мономорфный масіў.

Але, як аналогія з наркотыкамі адносіцца да аперацыі delete ? Адказ утрымлівае апошнюю радок кода ў прыведзеным вышэй фрагменце. Такім чынам, няхай гэта будзе перагледжана, на гэты раз з завіхрэнняў.

 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 all its entries have the 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 

Звярніце ўвагу. bar[1] = "" не выклікае палімарфізм, тады як bar[1] = undefined робіць. Таму заўсёды варта, калі гэта магчыма, выкарыстоўваць адпаведны тып для сваіх аб'ектаў, каб выпадкова не выклікаць палімарфізм. Адзін з такіх асоб можа выкарыстоўваць наступны спіс у якасці агульнай спасылкі, каб атрымаць іх. Аднак, калі ласка, не выкарыстоўвайце відавочна адзначаныя ніжэй ідэі. Замест гэтага выкарыстоўвайце ўсё, што добра працуе для вашага кода.

  • Пры выкарыстанні масіва / зменнай, уведзенай у Булеўскі прымітыў, выкарыстоўвайце значэнне false або undefined як пустое значэнне. Хоць пазбегнуць непатрэбнага палімарфізму добра, перапісванне ўсяго вашага кода, каб відавочна забараніць яго, хутчэй за ўсё, прывядзе да зніжэння прадукцыйнасці. Выкарыстоўвайце разумнае меркаванне!
  • Пры выкарыстанні масіва / зменнай, уведзенай у лікавы прымітыў, выкарыстоўвайце 0 ў якасці пустога значэння. Звярніце ўвагу, што ўнутры ёсць два тыпу лікаў: хуткія цэлыя лікі (ад 2147483647 да -2147483648 ўключна) і павольныя падвойныя кропкі з якая плавае коскі (што заўгодна, акрамя NaN і Infinity ). Калі цэлы лік паніжаецца да двайніка, яго нельга аднесці да цэлага ліку.
  • Пры выкарыстанні масіва / зменнай, уведзенай у радковы прымітыў, выкарыстоўвайце "" ў якасці пустога значэння.
  • Пры выкарыстанні Сымбаля, пачакайце, чаму вы карыстаецеся Сімвал?!?! Сімвалы дрэнны juju для выканання. Усе запраграмаваныя на выкарыстанне Сімвалы могуць быць перапраграмаваць, каб не выкарыстоўваць сімвалы, што прыводзіць да больш хуткага коду без знакаў. Сімвалы - гэта сапраўды проста неэфектыўны мета-цукар.
  • Пры выкарыстанні чаго-небудзь яшчэ выкарыстоўвайце null .

Аднак будзьце ўважлівыя! Не пачынайце рабіць гэта з усім існуючым кодам, паколькі ён, хутчэй за ўсё, зламае такой існуючы код і / або прадставіць дзіўныя памылкі. Хутчэй, такая эфектыўная практыка павінна быць рэалізаваная з самага пачатку, а пры пераўтварэнні існуючага кода рэкамендуецца двойчы, трайная, чатырохкратная праверка ўсіх радкоў, якія адносяцца да гэтага, як спроба абнавіць стары код да гэтай новай практыкі, можа быць як рызыкоўна, так як гэта карысна .

770
12 февр. адказ дадзены Dan 12 февр. 2014-02-12 20:48 '14 а 20:48 2014/02/12 20:48

215
16 окт. адказ дадзены redsquare 16 каст. 2008-10-16 14:03 '08 у 14:03 2008-10-16 14:03

Абнаўленне 2018/07/21: Доўгі час я адчуваў збянтэжанасць ў сувязі з гэтым адказам, таму лічу, што я крыху дакрануўся да яго. Проста невялікі каментар, тлумачэнне і фарматаванне, каб паскорыць чытанне непатрэбных доўгіх і заблытаных частак гэтага адказу.


КАРОТКАЯ ВЕРСІЯ

Фактычны адказ на пытанне

Як казалі іншыя, вы можаце выкарыстоўваць delete .

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

масіўны эквівалент

Ня delete з масіва. Array.prototype.splice гэтага выкарыстоўвайце Array.prototype.splice .

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

доўгая версія

JavaScript - гэта мова ААП, таму ўсё гэта аб'ект, уключаючы масівы. Такім чынам, я лічу неабходным пазначыць на канкрэтнае перасцярогу.

У масівах, у адрозненне ад простых старых аб'ектаў, выкарыстанне delete пакідае за смеццем у форме null , ствараючы "дзірку" ў масіве.

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

Як вы можаце бачыць, delete не заўсёды працуе так, як можна было б чакаць. Значэнне перазапісвальны, але памяць не пераразмяркоўваецца. Іншымі словамі, array[4] не перасоўваецца ў array[3] . У адрозненне ад Array.prototype.unshift , які ўстаўляе элемент у пачатак масіва і зрушвае ўсё дагары ( array[0] становіцца array[1] і г.д.),

Шчыра кажучы, акрамя ўстаноўкі null а не undefined --which, гэта зусім дзіўна - гэта паводзіны не павінна здзіўляць, паколькі delete - гэта унарный аператар, такі як typeof , які жорстка ўкручаны ў мову і не павінен клапаціцца пра тып выкарыстоўванага аб'екта, тады як Array з'яўляецца падклас Object з метадамі, спецыяльна прызначанымі для працы з масівамі. Таму няма ніякіх падставаў для delete каб мець спецыяльны выпадак, прыгатаваны для паўторнага зрушэння масіва, паколькі гэта проста запаволіць працу з непатрэбнай працай. Азіраючыся назад, мае чаканні былі нерэалістычнымі.

Вядома, гэта мяне здзівіла. Таму што я напісаў гэта, каб апраўдаць мой крыжовы паход супраць "нулявога смецця":

Ігнаруючы небяспекі і праблемы, уласцівыя null , і прастора марна, гэта можа быць праблематычна, калі масіў павінен быць дакладным.

Які з'яўляецца жахлівым апраўданнем для збавення ад null s-- null з'яўляецца небяспечным толькі пры няправільным выкарыстанні і не мае нічога агульнага з "дакладнасцю". Сапраўдная прычына, па якой вы не павінны delete з масіва, заключаецца ў тым, што пакідаючы запоўненыя смеццем і брудныя структуры дадзеных вакол, неакуратна і схільна памылак.

Ніжэй прыведзены надуманы сцэнар, які становіцца даволі доўгім, таму вы можаце перайсці да падзелу "Рашэнне", калі хочаце. Адзіная прычына, па якой я пакідаю гэты раздзел, - гэта тое, што я думаю, што некаторыя людзі, верагодна, лічаць гэта пацешным, і я не хачу быць "тым хлопцам", які адпраўляе "смешны" адказ, а затым выдаляе з яго усе "смешныя",

... Гэта па-дурному, я ведаю.

Надуманы і доўгатэрміновы сцэнар PDP-11

Напрыклад, выкажам здагадку, што вы ствараеце webapp, які выкарыстоўвае JSON-Серыялізацыя для захоўвання масіва, які выкарыстоўваецца для "вакенцаў" у радку (у дадзеным выпадку, localStorage ). Хай таксама кажуць, што код выкарыстоўвае лікавыя індэксы элементаў масіва для "назвы" іх пры маляванні на экране. Чаму вы робіце гэта, а не проста захоўваеце "тытул"? Таму што ... прычыны.

Добра, дазвольце сказаць, што вы спрабуеце захаваць памяць па просьбе гэтага аднаго карыстальніка, які запускае мінікампутараў PDP-11 з 1960 года, які працуе пад кіраваннем UNIX, і напісаў уласны уласны інтэрфейс, сумяшчальны з JavaScript, з падтрымкай JavaScript браўзэра, таму што X11 ня можа быць і гаворкі.

Ўсё больш і больш дурны сцэнар краявога сцэнара, выкарыстоўваючы delete ў паказаным масіве, прывядзе да null забруджванню масіва і, верагодна, прывядзе да з'яўлення памылак у дадатку пазней. І калі вы праверыце null , яно будзе аўтаматычна прапускаць колькасці, у выніку чаго адлюстроўваныя ўкладкі будуць выглядаць як [1] [2] [4] [5]...

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

Так, гэта вызначана не тое, што вы хацелі.

Цяпер вы можаце захаваць другі итератор, напрыклад j , для павелічэння толькі тады, калі сапраўдныя значэння счытваюцца з масіва. Але гэта дакладна не вырашыць null праблему, і вам усё роўна спадабаецца гэты карыстальнік Troll PDP-11. На жаль, у яго кампутара проста недастаткова памяці для захоўвання гэтага апошняга цэлага ліку (не пытайцеся, як яму ўдаецца апрацоўваць масіў зменнай шырыні ...).

Такім чынам, ён пасылае вам ліст у гневе:

 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 code made my browser segfault 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 

Цяпер вы на сваім канцы. Гэты хлопец пастаянна скардзіўся на ваша прыкладанне, і вы хочаце сказаць яму, каб ён заткнуўся і пайшоў на лепшы кампутар.

Рашэнне: Array.prototype.splice

На шчасце, масівы маюць спецыяльны метад для выдалення індэксаў і пераразмеркавання памяці: Array.prototype.splice() . Вы маглі б напісаць нешта накшталт гэтага:

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

І проста так, вы задаволеныя г-ном PDP-11. Ура! (Я б усё ж сказаў яму, хоць ...)

Array.prototype.splice vs Array.prototype.slice

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

Array.prototype.splice (пачатак, n)

.splice() муціруе масіў і вяртае аддаленыя індэксы. Масіў наразаецца, пачынаючы з індэкса, start і n элементаў выразаюцца. Калі n не пазначана, увесь масіў пасля 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 (пачатак, канец)

.slice() з'яўляецца неразбуральнай і вяртае новы масіў, які змяшчае названыя індэксы ад start да end . Калі end пакінуты неадзначаныя, паводзіны будзе такім жа, як .splice() ( end = array.length ). Паводзіны крыху складана, паколькі па нейкай прычыне end індэксы ад 1 замест 0. Я не ведаю, чаму гэта адбываецца, але так яно і ёсць. Акрамя таго, калі end <= start , вынікам будзе пусты масіў.

 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] 

На самай справе гэта не тое, што адбываецца, але лягчэй думаць пра гэта. Згодна з MDN, вось што адбываецца на самай справе:

 // 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 , проста выключаецца з зрэзу. Пазначаныя ў дужках індэксы паказваюць, што наразаецца. У любым выпадку, паводзіны не з'яўляецца інтуітыўна і звязана з тым, што ён выклікае сваю справядлівую долю памылак "адзін за адным", таму вам можа здацца карысным зрабіць функцыю-абалонку больш .splice() паводзін .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); } 

Звярніце ўвагу, што функцыя-абгортка прызначана для вельмі строгіх тыпаў і вяртае значэнне null калі нешта адключана. Гэта ўключае ў сябе радок тыпу "3" . Застаецца праграмісту старанна ставіцца да яго тыпах. Гэта павінна спрыяць добрай практыцы праграмавання.

Абнаўленне адносна is_array()

Гэта ставіцца да гэтага (цяпер выдаленага) фрагменце:

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

Такім чынам, як аказалася, на самай справе ёсць убудаваны спосаб вызначыць, ці сапраўды масіў з'яўляецца масівам, і гэта Array.isArray() , уведзены ў ECMAScript 5 (снежань 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 };