كيف أقوم بإزالة خاصية من كائن JavaScript؟


معطى كائن:

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

كيف يمكنني إزالة الخاصية regex للحصول على myObject التالي؟

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

الإجابة رقم 1

لإزالة خاصية من كائن (تغيير الكائن)، يمكنك القيام بذلك باستخدام الكلمة المفتاحية delete، هكذا:

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

تجريبي

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

console.log(myObject);

بالنسبة لأي شخص مهتم بقراءة المزيد عن ذلك، قام مستخدم Stack Overflow المعروف باسم kangax بكتابة منشور مدونة مفصل للغاية عن جملة delete على مدونته، Understanding delete. ينصح به بشدة.

إذا كنت ترغب في الحصول على كائن جديد يحتوي على كل مفاتيح الكائن الأصلي ما عدا بعض المفاتيح، يمكنك استخدام التفكيك.

تجريبي

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

// assign the key regex to the variable _ indicating it will be unused
const { regex: _, ...newObj } = myObject;

console.log(newObj);   // has no 'regex' key
console.log(myObject); // remains unchanged

الإجابة رقم 2

يمكن التفكير في الكائنات في جافاسكريبت على أنها خرائط بين المفاتيح والقيم. يُستخدم عامل delete لإزالة هذه المفاتيح، المعروفة أكثر باسم خصائص الكائن، واحدة في كل مرة.

var obj = {
  myProperty: 1    
}
console.log(obj.hasOwnProperty('myProperty')) // true
delete obj.myProperty
console.log(obj.hasOwnProperty('myProperty')) // false

المشغل delete لا يحرر الذاكرة بشكل مباشر، ويختلف عن مجرد تعيين قيمة null أو undefined لخاصية، من حيث أن الخاصية نفسها تُزال من الكائن. لاحظ أنه إذا كانت قيمة الخاصية المحذوفة من نوع مرجعي (كائن)، وما زال جزء آخر من برنامجك يحتفظ بمرجع إلى ذلك الكائن، فإن هذا الكائن، بالطبع، لن يتم جمعه من قِبل جامع القمامة إلا بعد أن تختفي كل المراجع إليه.

سيعمل delete فقط على الخصائص التي يحدد واصفها أنها قابلة للتكوين.

الإجابة رقم 3

سؤال قديم، إجابة حديثة. باستخدام تفكيك الكائنات، وهي ميزة من 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.

تعديل:

لإعادة التعيين لنفس المتغير، استخدم let:

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

الإجابة رقم 4

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

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

هذا يعمل في فايرفوكس وإنترنت إكسبلورر، وأعتقد أنه يعمل في جميع المتصفحات الأخرى.

الإجابة رقم 5

يتم استخدام العامل delete لإزالة الخصائص من الكائنات.

const obj = { foo: "bar" };

delete obj.foo;
obj.hasOwnProperty("foo"); // false

لاحظ أنه بالنسبة للمصفوفات، هذا ليس هو نفسه إزالة عنصر. لإزالة عنصر من مصفوفة، استخدم Array#splice أو Array#pop. على سبيل المثال:

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

تفاصيل

من الناحية الصارمة، من المستحيل فعليًا حذف أي شيء في جافاسكريبت. عامل delete لا يحذف الكائنات ولا يحرر الذاكرة. بدلاً من ذلك، يقوم بتعيين المعامل الخاص به إلى undefined ويتلاعب بالكائن الأصل بحيث يختفي العضو.

let parent = {
    member: { str: "Hello" }
};
let secondref = parent.member;

delete parent.member;
parent.member;        // undefined
secondref;            // { str: "Hello" }

الكائن object لم يُحذف. المرجع فقط هو الذي يُحذف. يتم تحرير الذاكرة بواسطة جامع القمامة فقط عندما تتم إزالة جميع المراجع إلى الكائن.

تحذير مهم آخر هو أن عامل delete لن يعيد تنظيم الهياكل من أجلك، وهذا له نتائج قد تبدو غير بديهية. على سبيل المثال، حذف فهرس من مصفوفة سيترك "ثغرة" فيها.

let array = [0, 1, 2, 3]; // [0, 1, 2, 3]
delete array[2];          // [0, 1, empty, 3]

هذا لأن المصفوفات هي كائنات. لذا فإن الفهارس هي نفسها المفاتيح.

let fauxarray = {0: 1, 1: 2, length: 2};
fauxarray.__proto__ = [].__proto__;
fauxarray.push(3);
fauxarray;                // [1, 2, 3]
Array.isArray(fauxarray); // false
Array.isArray([1, 2, 3]); // true

تتعامل الدوال المدمجة المختلفة في جافاسكريبت مع المصفوفات التي تحتوي على فراغات فيها بشكل مختلف.

  • ستتجنب جمل for..in الفهرس الفارغ تمامًا.

  • حلقة for الساذجة ستُعطي undefined للقيمة عند الفهرس.

  • أي طريقة تستخدم Symbol.iterator ستُرجع undefined للقيمة عند الفهرس.

  • forEach وmap وreduce ستتجاوز ببساطة الفهرس المفقود، لكنها لن تزيله

مثال :

let array = [1, 2, 3]; // [1,2,3]
delete array[1];       // [1, empty, 3]
array.map(x => 0);     // [0, empty, 0]

لذلك، لا ينبغي استخدام العامل delete للحالة الشائعة المتمثلة في إزالة العناصر من مصفوفة. تحتوي المصفوفات على طرق مخصصة لإزالة العناصر وإعادة تخصيص الذاكرة: Array#splice() و Array#pop.

Array#splice(البداية[, عدد_الحذف[, العنصر1[, العنصر2[, ...]]]])

تقوم Array#splice بتغيير المصفوفة، وتُرجع أي مؤشرات تمت إزالتها. يتم إزالة deleteCount عناصر ابتداءً من الفهرس start، ويتم إدراج item1, item2... itemN في المصفوفة ابتداءً من الفهرس start. إذا تم حذف deleteCount، يتم إزالة العناصر من startIndex إلى نهاية المصفوفة.

let a = [0,1,2,3,4]
a.splice(2,2) // returns the removed elements [2,3]
// ...and `a` is now [0,1,4]

هناك أيضًا دالة باسم مشابه، ولكن مختلفة، على Array.prototype: Array#slice.

مصفوفة#قص([البداية[, النهاية]])

Array#slice غير مدمّر، ويعيد مصفوفة جديدة تحتوي على الفهارس المحددة من start إلى end. إذا تُرك end غير محدد، فإنه يكون افتراضيًا عند نهاية المصفوفة. إذا كان end موجبًا، فإنه يحدد الفهرس غير الشامل بدءًا من الصفر للتوقف عنده. إذا كان end سالبًا، فإنه يحدد الفهرس للتوقف عنده عن طريق العد إلى الوراء من نهاية المصفوفة (على سبيل المثال، -1 سيستبعد الفهرس النهائي). إذا كان end <= start، فإن النتيجة ستكون مصفوفة فارغة.

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

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

مصفوفة#إزالة_العنصر_الأخير

Array#pop يزيل العنصر الأخير من المصفوفة، ويعيد هذا العنصر. هذه العملية تغير طول المصفوفة. العملية العكسية هي push

مصفوفة#إزاحة

Array#shift مشابه لـ pop، باستثناء أنه يزيل العنصر الأول. العملية المعاكسة هي unshift.

الإجابة رقم 6

تركيب الانتشار (ES6)

لإكمال إجابة كوين، في حال كنت تريد إزالة متغير ديناميكي باستخدام صيغة الانتشار، يمكنك فعل ذلك على النحو التالي:

const key = 'a';

const { [key]: foo, ...rest } = { a: 1, b: 2, c: 3 };

console.log(foo);  // 1
console.log(rest); // { b: 2, c: 3 }

* foo سيكون متغيرًا جديدًا بقيمة a (التي هي 1).


إجابة موسعة 😇

هناك بعض الطرق الشائعة لإزالة خاصية من كائن (أو للتعامل معها على هذا النحو).
لكل منها مزاياه وعيوبه الخاصة (تحقق من مقارنة الأداء هذه):

مشغل الحذف :

إنه قابل للقراءة وقصير. ومع ذلك، قد لا يكون الخيار الأفضل إذا كنت تعمل على عدد كبير من الكائنات، حيث أن أداؤه ليس مُحسّنًا.

delete obj[key];

إعادة التعيين :

في بعض الظروف، يمكن أن يكون مفيدًا. إنه أسرع بأكثر من مرتين من عامل delete، ولكن كل من المفتاح والقيمة لا يتم حذفه أبدًا ويمكن التكرار عليهما (أو تخطيهما).

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

مشغل الانتشار :

يسمح لنا هذا العامل ES6 بإرجاع كائن جديد تمامًا، مستثنيًا أي خصائص، دون تعديل الكائن الحالي. الجانب السلبي هو أن أداؤه هو الأسوأ من بين المذكورات أعلاه ولا يُنصح باستخدامه عندما تحتاج إلى إزالة العديد من الخصائص في نفس الوقت.

{ [key]: val, ...rest } = obj;

الإجابة رقم 7

بديل آخر هو استخدام مكتبة Underscore.js.

لاحظ أن _.pick() و _.omit() كلاهما يُرجع نسخة من الكائن ولا يغير الكائن الأصلي مباشرة. يجب أن يؤدي تعيين النتيجة إلى الكائن الأصلي الغرض المطلوب (لم يُعرض مثال لذلك).

المرجع: الرابط _.pick(object, *keys)

إرجاع نسخة من الكائن، مصفاة لتحتوي فقط على القيم للمفاتيح المدرجة في القائمة البيضاء (أو مصفوفة المفاتيح الصالحة).

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

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

المرجع: الرابط _.omit(object, *keys)

إرجاع نسخة من الكائن، مصفاة لاستبعاد المفاتيح المدرجة في القائمة السوداء (أو مصفوفة من المفاتيح).

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

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

بالنسبة للمصفوفات، يمكن استخدام _.filter() و _.reject() بطريقة مشابهة.

الإجابة رقم 8

لنسخ كائن بدون خاصية:

على سبيل المثال:

let object = { a: 1, b: 2, c: 3 };

ونحن بحاجة إلى حذف a.

  1. مع مفتاح مخصص صريح:

    const { a, ...rest } = object;
    object = rest;
    
  2. مع مفتاح مكون قابل للتغيير:

    const propKey = 'a';
    const { [propKey]: propValue, ...rest } = object;
    object = rest;
    
  3. دالة سهم رائعة 😎:

    const removeProperty = (propKey, { [propKey]: propValue, ...rest }) => rest;
    
    object = removeProperty('a', object);
    
  4. لـ عدة عقارات

    const removeProperties = (object, ...keys) => (keys.length ? removeProperties(removeProperty(keys.pop(), object), ...keys) : object);
    

الاستخدام :

object = removeProperties(object, 'a', 'b') // result => { c: 3 }

أو :

const propsToRemove = ['a', 'b']
object = removeProperties(object, ...propsToRemove) // result => { c: 3 }

الإجابة رقم 9

المصطلح الذي استخدمته في عنوان سؤالك، إزالة خاصية من كائن جافاسكريبت، يمكن تفسيره بعدة طرق مختلفة. أحدها هو إزالتها من كامل الذاكرة وقائمة مفاتيح الكائن، والآخر هو مجرد إزالتها من كائنك فقط. كما ذُكر في بعض الإجابات الأخرى، كلمة 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"];

بمعنى آخر، يصبح من الممكن حذف كائن جافا سكريبت بمجرد عدم وجود أي مرجع متبقي في الكود الخاص بك يشير إلى ذلك الكائن.


تحديث:

شكراً لـ @AgentME:

تعيين خاصية إلى null قبل حذفها لا يحقق أي شيء (ما لم يكن الكائن قد تم ختمه بواسطة Object.seal ويفشل الحذف. هذا ليس هو الحال عادة إلا إذا حاولت ذلك بشكل محدد).

للحصول على مزيد من المعلومات حول Object.seal: Object.seal()

الإجابة رقم 10

جاء ECMAScript 2015 (أو ES6) مع كائن Reflect المدمج. من الممكن حذف خاصية من كائن عن طريق استدعاء دالة Reflect.deleteProperty() مع تمرير الكائن الهدف ومفتاح الخاصية كمعاملات:

Reflect.deleteProperty(myJSONObject, 'regex');

والذي يعادل:

delete myJSONObject['regex'];

ولكن إذا لم تكن خاصية الكائن قابلة للتكوين، فلا يمكن حذفها لا باستخدام دالة deleteProperty ولا باستخدام عامل الحذف delete:

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

تجعل دالة Object.freeze() جميع خواص الكائن غير قابلة للتكوين (إلى جانب أشياء أخرى). تُعيد دالة deleteProperty (وكذلك معامل الحذف delete) 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

الإجابة رقم 11

افترض أن لديك كائنًا يبدو هكذا:

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

ملاحظة

بينما يمكنك من الناحية التقنية استخدام delete لمصفوفة، فإن استخدامه سيؤدي إلى الحصول على نتائج غير صحيحة عند استدعاء على سبيل المثال Hogwarts.staff.length لاحقًا. بعبارة أخرى، delete سيزيل العنصر، لكنه لن يحدث قيمة خاصية length. استخدام delete سيؤدي أيضًا إلى إفساد الفهرسة الخاصة بك.

لذا، عند حذف القيم من كائن، يجب دائمًا أولاً النظر فيما إذا كنت تتعامل مع خصائص الكائن أو إذا كنت تتعامل مع قيم المصفوفة، واختيار الاستراتيجية المناسبة بناءً على ذلك.

إذا كنت تريد تجربة هذا، يمكنك استخدام هذا Fiddle كنقطة انطلاق.

الإجابة رقم 12

أنا شخصياً أستخدم Underscore.js أو Lodash لمعالجة الكائنات والمصفوفات:

myObject = _.omit(myObject, 'regex');

الإجابة رقم 13

استخدام طريقة delete هو أفضل طريقة للقيام بذلك، وفقًا لوصف MDN، يقوم عامل الحذف بإزالة خاصية من كائن. لذا يمكنك ببساطة كتابة:

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

عامل الحذف يقوم بإزالة خاصية معينة من كائن. عند الحذف بنجاح، سيُرجع true، وإلا سيتم إرجاع false. ومع ذلك، من المهم مراعاة السيناريوهات التالية:

  • إذا كانت الخاصية التي تحاول حذفها غير موجودة، فلن يكون للحذف أي تأثير وسيعيد true
  • إذا كانت هناك خاصية بنفس الاسم موجودة في سلسلة النماذج الأولية للكائن، فعند الحذف، سيستخدم الكائن الخاصية من سلسلة النماذج الأولية (بمعنى آخر، الحذف يؤثر فقط على الخصائص الخاصة بالكائن نفسه).
  • أي خاصية معلنة باستخدام var لا يمكن حذفها من النطاق العالمي أو من نطاق الدالة.
  • وبالتالي، لا يمكن لـ delete حذف أي دوال في النطاق العام (سواء كان هذا جزءًا من تعريف دالة أو تعبير دالة).
  • يمكن حذف الدوال التي هي جزء من كائن (بعيداً عن النطاق العام) باستخدام delete.
  • أي خاصية تم إعلانها باستخدام let أو const لا يمكن حذفها من النطاق الذي تم تعريفها فيه. الخصائص غير القابلة للتكوين لا يمكن إزالتها. يشمل ذلك خصائص الكائنات المدمجة مثل Math و Array و Object والخصائص التي تم إنشاؤها كغير قابلة للتكوين باستخدام طرق مثل Object.defineProperty().

يعطي الجزء التالي مثالًا بسيطًا آخر:

var Employee = {
  age: 28,
  name: 'Alireza',
  designation: 'developer'
}

console.log(delete Employee.name);   // returns true
console.log(delete Employee.age);    // returns true

// When trying to delete a property that does 
// not exist, true is returned 
console.log(delete Employee.salary); // returns true

لمزيد من المعلومات ولمشاهدة المزيد من الأمثلة، قم بزيارة الرابط أدناه:

https://developer.mozilla.org/ar/docs/Web/JavaScript/Reference/Operators/delete

الإجابة رقم 14

هناك بعض الطرق لإزالة الخصائص من كائن:

1) الإزالة باستخدام واصل خاصية النقطة (قابل للتغيير)

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

delete myObject.regex;
console.log(myObject);

2. إزالة باستخدام عامِل الوصول إلى الخاصية بالأقواس المربعة (قابل للتغيير)

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

delete myObject['regex'];
console.log(myObject);
// or
const name = 'ircEvent';
delete myObject[name];
console.log(myObject);

3) إزالة العنصر دون تغيير الكائن الأصلي ممكن باستخدام تفكيك الكائن وصياغة الباقي (ثابت)

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

const { regex, ...myObjectRest} = myObject;
console.log(myObjectRest); 

الإجابة رقم 15

حل آخر، باستخدام Array#reduce.

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

myObject = Object.keys(myObject).reduce(function(obj, key) {
  if (key != "regex") {           //key you want to remove
    obj[key] = myObject[key];
  }
  return obj;
}, {});

console.log(myObject);

ومع ذلك، سيقوم بتغيير الكائن الأصلي. إذا كنت تريد إنشاء كائن جديد بدون المفتاح المحدد، فقط قم بتعيين دالة reduce لمتغير جديد، على سبيل المثال:

(إي إس 6)

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

الإجابة رقم 16

هناك الكثير من الإجابات الجيدة هنا، لكني أود فقط أن أضيف أنه عند استخدام delete لإزالة خاصية في JavaScript، من الحكمة غالبًا أولاً التحقق مما إذا كانت تلك الخاصية موجودة لتجنب الأخطاء.

مثال

var obj = {"property":"value", "property2":"value"};

if (obj && obj.hasOwnProperty("property2")) {
  delete obj.property2;
} else {
  //error handling
}

بسبب الطبيعة الديناميكية لجافا سكريبت، غالبًا ما تكون هناك حالات لا تعرف فيها ببساطة ما إذا كانت الخاصية موجودة أم لا. التحقق مما إذا كان obj موجودًا قبل استخدام && يضمن أيضًا أنك لن تُحدث خطأً نتيجة استدعاء دالة hasOwnProperty() على كائن غير معرف.

آسف إذا لم يضف هذا إلى حالتك الخاصة، لكنني أعتقد أن هذا تصميم جيد يمكن اعتماده عند إدارة الكائنات وخصائصها.

الإجابة رقم 17

هذا المنشور قديم جدًا وأجد أنه مفيد جدًا لذلك قررت مشاركة دالة unset التي كتبتها في حال رأى شخص آخر هذا المنشور وفكر لماذا الأمر ليس بسيطًا كما في دالة 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"}

الإجابة رقم 18

باستخدام ramda#dissoc ستحصل على كائن جديد بدون الخاصية regex:

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

يمكنك أيضًا استخدام وظائف أخرى لتحقيق نفس التأثير - تجاهل، اختر، ...

الإجابة رقم 19

جرّب الطريقة التالية. قم بتعيين قيمة الخاصية Object إلى undefined. ثم قم بـ stringify للكائن و parse.

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

myObject.regex = undefined;
myObject = JSON.parse(JSON.stringify(myObject));

console.log(myObject);

الإجابة رقم 20

استخدام Lodash

import omit from 'lodash/omit';

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

استخدام رامدا

R.omit(['a', 'd'], {a: 1, b: 2, c: 3, d: 4}); //=> {b: 2, c: 3}

الإجابة رقم 21

إذا كنت تريد حذف خاصية متداخلة بعمق داخل الكائن، فيمكنك استخدام الدالة التكرارية التالية مع المسار إلى الخاصية كوسيطة ثانية:

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

مثال :

var a = {
    level1:{
        level2:{
            level3: {
                level4: "yolo"
            }
        }
    }
};

deepObjectRemove(a, ["level1", "level2", "level3"]);
console.log(a);

//Prints {level1: {level2: {}}}

الإجابة رقم 22

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

const obj = {
    "Filters":[
        {
            "FilterType":"between",
            "Field":"BasicInformationRow.A0",
            "MaxValue":"2017-10-01",
            "MinValue":"2017-09-01",
            "Value":"Filters value"
        }
    ]
};

let new_obj1 = Object.assign({}, obj.Filters[0]);
let new_obj2 = Object.assign({}, obj.Filters[0]);

/*

// old version

let shaped_obj1 = Object.keys(new_obj1).map(
    (key, index) => {
        switch (key) {
            case "MaxValue":
                delete new_obj1["MaxValue"];
                break;
            case "MinValue":
                delete new_obj1["MinValue"];
                break;
        }
        return new_obj1;
    }
)[0];


let shaped_obj2 = Object.keys(new_obj2).map(
    (key, index) => {
        if(key === "Value"){
            delete new_obj2["Value"];
        }
        return new_obj2;
    }
)[0];


*/


// new version!

let shaped_obj1 = Object.keys(new_obj1).forEach(
    (key, index) => {
        switch (key) {
            case "MaxValue":
                delete new_obj1["MaxValue"];
                break;
            case "MinValue":
                delete new_obj1["MinValue"];
                break;
            default:
                break;
        }
    }
);

let shaped_obj2 = Object.keys(new_obj2).forEach(
    (key, index) => {
        if(key === "Value"){
            delete new_obj2["Value"];
        }
    }
);

الإجابة رقم 23

إزالة الخصائص في جافاسكريبت

هناك العديد من الخيارات المختلفة المعروضة في هذه الصفحة، ليس لأن معظم الخيارات خاطئة - أو لأن الإجابات مكررة - ولكن لأن التقنية المناسبة تعتمد على الوضع الذي أنت فيه وأهداف المهام التي تحاول أنت و/أو فريقك تحقيقها. للإجابة على سؤالك بشكل قاطع، يجب معرفة:

  1. إصدار ECMAScript الذي تستهدفه
  2. نطاق أنواع الكائنات التي تريد إزالة الخصائص عليها ونوع أسماء الخصائص التي تحتاج إلى القدرة على تجاهلها (سلاسل فقط؟ رموز؟ مراجع ضعيفة مرتبطة بكائنات عشوائية؟ كل هذه كانت أنواع مؤشرات الخصائص في جافا سكريبت منذ سنوات الآن)
  3. الأخلاقيات/الأنماط البرمجية التي تستخدمها أنت وفريقك. هل تفضل النهج الوظيفية ويُمنع التغيير في فريقك، أم تستخدم تقنيات كائنية التغيير بشكل فوضوي؟
  4. هل تبحث عن تحقيق ذلك باستخدام جافا سكريبت فقط أم أنك مستعد وقادر على استخدام مكتبة خارجية؟

بمجرد الإجابة على تلك الاستفسارات الأربعة، هناك أساسًا أربع فئات من "إزالة الخصائص" في 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 وفهارس المصفوفة بالإضافة إلى السلاسل النصية وتعمل في كل إصدار من إصدارات JavaScript باستثناء الإصدار الأول. ومع ذلك، فهي قابلة للتغيير، مما ينتهك بعض مبادئ البرمجة ولها تأثيرات على الأداء. كما أنها قد تؤدي إلى استثناءات غير ملتقطة عند استخدامها على خصائص غير قابلة للتكوين في الوضع الصارم.

إغفال خاصية السلسلة القائمة على الراحة

هذه الفئة مخصصة للتعامل مع مثيلات الكائنات البسيطة أو المصفوفات في نكهات 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"

الإجابة رقم 24

ادعاء دان بأن 'حذف' بطيء جدًا والمعيار الذي نشره كان مثار شك. لذا أجريت الاختبار بنفسي في كروم 59. يبدو أن 'حذف' أبطأ بحوالي 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 o.a; delete o.b; delete o.c; delete o.d; delete o.e;
}
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};
   o.a = o.b = o.c = o.d = o.e = undefined;
}
console.log (Date.now()-t2);  // 205

لاحظ أنني قمت عمدًا بتنفيذ أكثر من عملية 'حذف' واحدة في دورة حلقة واحدة لتقليل التأثير الناتج عن العمليات الأخرى.

الإجابة رقم 25

إليك طريقة ES6 لإزالة الإدخال بسهولة:

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

const removeItem = 'regex';

const { [removeItem]: remove, ...rest } = myObject;

console.log(remove); // "^http://.*"
console.log(rest); // Object { ircEvent: "PRIVMSG", method: "newURI" }

الإجابة رقم 26

@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's 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 }

الإجابة رقم 27

يمكنك استخدام مرشح مثل الموجود أدناه

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

// Way 1

let filter1 = {}
  Object.keys({...myObject}).filter(d => {
  if(d !== 'regex'){
    filter1[d] = myObject[d];
  }
})

console.log(filter1)

// Way 2

let filter2 = Object.fromEntries(Object.entries({...myObject}).filter(d =>
d[0] !== 'regex'
))

console.log(filter2)

الإجابة رقم 28

لقد استخدمت Lodash "unset" لجعل ذلك يحدث أيضًا للكائن المتداخل... فقط هذا يحتاج إلى كتابة منطق صغير للحصول على مسار مفتاح الخاصية الذي تتوقعه طريقة omit.

  1. طريقة تُرجع مسار الخاصية كمصفوفة

var a = {"bool":{"must":[{"range":{"price_index.final_price":{"gt":"450", "lt":"500"}}}, {"bool":{"should":[{"term":{"color_value.keyword":"Black"}}]}}]}};

function getPathOfKey(object,key,currentPath, t){
    var currentPath = currentPath || [];

    for(var i in object){
        if(i == key){
            t = currentPath;
        }
        else if(typeof object[i] == "object"){
            currentPath.push(i)
            return getPathOfKey(object[i], key,currentPath)
        }
    }
    t.push(key);
    return t;
}
document.getElementById("output").innerHTML =JSON.stringify(getPathOfKey(a,"price_index.final_price"))
<div id="output">

</div>
  1. ثم استخدم طريقة Lodash unset لإزالة الخاصية من الكائن.

var unset = require('lodash.unset');
unset(a, getPathOfKey(a, "price_index.final_price"));