الإسناد بالتفكيك في JavaScript

من موسوعة حسوب
مراجعة 15:44، 28 يناير 2018 بواسطة عبد اللطيف ايمش (نقاش | مساهمات) (استبدال النص - '\[\[تصنيف:(.*)\]\]' ب'{{SUBPAGENAME}}')
(فرق) → مراجعة أقدم | المراجعة الحالية (فرق) | مراجعة أحدث ← (فرق)

الإسناد بالتفكيك (destructuring assignment) يسمح باستخراج القيم الموجودة في المصفوفات أو خاصيات أحد الكائنات إلى متغيرات مستقلة.

البنية العامة

var a, b, rest;
[a, b] = [10, 20];
console.log(a); // 10
console.log(b); // 20

[a, b, ...rest] = [10, 20, 30, 40, 50];
console.log(a); // 10
console.log(b); // 20
console.log(rest); // [30, 40, 50]

({ a, b } = { a: 10, b: 20 });
console.log(a); // 10
console.log(b); // 20


// Stage 3 proposal
({a, b, ...rest} = {a: 10, b: 20, c: 30, d: 40});
console.log(a); // 10
console.log(b); // 20
console.log(rest); //{c: 30, d: 40}

الوصف

يمكن استخدام التعابير المختصرة لإنشاء المصفوفات والكائنات لبناء مجموعة من البيانات:

var x = [1, 2, 3, 4, 5];

الإسناد بالتفكيك يستخدم صيغةً مشابهةً لذلك، لكن على الجانب الأيسر من معامل الإسناد، وذلك لتعريف أسماء المتغيرات التي ستُسنَد القيم إليها:

var x = [1, 2, 3, 4, 5];
var [y, z] = x;
console.log(y); // 1
console.log(z); // 2

هذه الصيغة تشبه الصيغ المتاحة بلغات البرمجة الأخرى مثل Perl و Python.

تفكيك المصفوفات

عملية إسناد بسيطة

var foo = ['one', 'two', 'three'];

var [one, two, three] = foo;
console.log(one);   // "one"
console.log(two);   // "two"
console.log(three); // "three"

فصل عملية الإسناد عن التعريف

يمكن إسناد القيم بالتفكيك بمعزل عن مكان تعريفها:

var a, b;

[a, b] = [1, 2];
console.log(a); // 1
console.log(b); // 2

القيم الافتراضية

يمكن إسناد قيمة افتراضية إلى المتغير، وذلك في حال كانت القيمة المُستخرَجة من المصفوفة هي undefined:

var a, b;

[a=5, b=7] = [1];
console.log(a); // 1
console.log(b); // 7

التبديل بين قيم متغيرين

يمكن تبديل بين قيم متغيرين باستخدام الإسناد بالتفكيك دون استخدام متغيّر مؤقت:

var a = 1;
var b = 3;

[a, b] = [b, a];
console.log(a); // 3
console.log(b); // 1

تفسير مصفوفة معادة من دالة

من الممكن إعادة مصفوفات من الدوال، واستخدام الإسناد بالتفكيك سيُسهِّل التعامل معها.

على سبيل المثال، الدالة f()‎ تُعيد القيم ‎[1, 2]‎ كمخرجات، والتي يمكن إسنادها إلى متغيرات بسهولة باستخدام الإسناد بالتفكيك:

function f() {
  return [1, 2];
}

var a, b; 
[a, b] = f(); 
console.log(a); // 1
console.log(b); // 2

تجاهل بعض القيم المعادة

يمكنك تجاهل القيم التي لست بحاجةٍ لها:

function f() {
  return [1, 2, 3];
}

var [a, , b] = f();
console.log(a); // 1
console.log(b); // 3

إسناد بقية المصفوفة إلى متغير

عند الإسناد بالتفكيك على مصفوفة، فيمكنك استخراج قيم معيّنة وإسناد ما تبقى منها إلى متغيرٍ باستخدام معامل البقية:

var [a, ...b] = [1, 2, 3];
console.log(a); // 1
console.log(b); // [2, 3]

لاحظ أنَّه سيرمى الخطأ SyntaxError إذا استخدمنا فاصلةً بعد معامل البقية:

var [a, ...b,] = [1, 2, 3];
// SyntaxError: rest element may not have a trailing comma

استخراج قيم من ناتج مطابقة تعبير نمطي

عندما تُطابِق الدالة exec()‎ سلسلةً نصيةً اعتمادًا على تعبيرٍ نمطي (regular expression) فستُعيد مصفوفةً أوّلُ عنصرٍ فيها يحتوي على السلسلة النصية التي جرت مطابقتها كلها، ثم السلاسل النصية الفرعية التي تُطابِق الأنماط الموجودة بين قوسين؛ يسمح لنا الإسناد بالتفكيك باستخراج الأقسام التي نريدها من المصفوفة بسهولة، ويُمكِّننا من تجاهل السلسلة النصية التي جرت مطابقتها كلها إن لم تكن ضروريةً:

function parseProtocol(url) { 
  var parsedURL = /^(\w+)\:\/\/([^\/]+)\/(.*)$/.exec(url);
  if (!parsedURL) {
    return false;
  }
  console.log(parsedURL); // ["https://academy.hsoub.com/courses/front-end-web-development", "https", "academy.hsoub.com", "courses/front-end-web-development"]

  var [, protocol, fullhost, fullpath] = parsedURL;
  return protocol;
}

console.log(parseProtocol('https://academy.hsoub.com/courses/front-end-web-development')); // "https"

تفكيك الكائنات

عملية إسناد بسيطة

var o = {p: 42, q: true};
var {p, q} = o;

console.log(p); // 42
console.log(q); // true

فصل عملية الإسناد عن التعريف

يمكن إسناد القيم بالتفكيك بمعزل عن مكان تعريفها:

var a, b;

({a, b} = {a: 1, b: 2});

من المهم جدًا ملاحظة الأقواس المحيطة بعملية الإسناد السابقة ( ... ) عند فصل عملية الإسناد عن التعريف.

فالتعبير {a, b} = {a: 1, b: 2} ليس صالحًا لوحده، لأنَّ القسم الأيسر من تعبير الإسناد (أي {a, b}) سيُعدّ على أنَّه قسمٌ كتلي (block)؛ لكن التعبير ({a, b} = {a: 1, b: 2}) صالحٌ، وهو يكافئ var {a, b} = {a: 1, b: 2}‎.

انتبه إلى أنَّ التعبير ( ... ) يجب أن يُسبَق بفاصلة منقوطة، وإلا فسيفسَّر على أنَّه تعبيرٌ لتنفيذ الدالة الموجودة في السطر السابق.

إسناد إلى أسماء متغيرات جديدة

يمكن استخراج القيمة من الكائن وإسنادها إلى متغير له اسم مختلف عن اسم خاصية الكائن:

var o = {p: 42, q: true};
var {p: foo, q: bar} = o;
 
console.log(foo); // 42 
console.log(bar); // true

القيم الافتراضية

يمكن إسناد قيمة افتراضية إلى المتغير، وذلك في حال كانت القيمة المُستخرَجة من الكائن هي undefined:

var {a = 10, b = 5} = {a: 3};

console.log(a); // 3
console.log(b); // 5

إسناد إلى أسماء متغيرات جديدة مع توفير قيم افتراضية

يمكن استخراج القيمة من الكائن وإسنادها إلى متغيرٍ له اسم مختلف، إضافةً إلى توفير قيم افتراضية لها:

var {a:aa = 10, b:bb = 5} = {a: 3};

console.log(aa); // 3
console.log(bb); // 5

حلقة تكرار مع الإسناد بالتفكيك

var people = [
  {
    name: 'Ahmad Mostafa',
    family: {
      mother: 'Reem Mostafa',
      father: 'Hussam Mostafa',
      sister: 'Raghad Mostafa'
    },
    age: 35
  },
  {
    name: 'Abd al-Salam Mansor',
    family: {
      mother: 'Norah Mansor',
      father: 'Bashir Mansor',
      brother: 'Ameen Mansor'
    },
    age: 25
  }
];

for (var {name: n, family: {father: f}} of people) {
  console.log('Name: ' + n + ', Father: ' + f);
}

// "Name: Ahmad Mostafa, Father: Hussam Mostafa"
// "Name: Abd al-Salam Mansor, Father: Bashir Mansor"

استخراج القيم من الكائنات الممررة إلى دالة

هذا المثال يستخرج قيمة id و displayName و firstName من الكائن المُمرَّر ويعرضها:

function userId({id}) {
  return id;
}

function whois({displayName, fullName: {firstName: name}}) {
  console.log(displayName + ' is ' + name);
}

var user = { 
  id: 42, 
  displayName: 'jode',
  fullName: { 
      firstName: 'Jude',
      lastName: 'Al-halabi'
  }
};

console.log('userId: ' + userId(user)); // "userId: 42"
whois(user); // "jode is Jude"

أسماء الخاصيات المحسوبة

يمكن استخدام أسماء الخاصيات المحسوبة، كما في الشكل المختصر لإنشاء الكائنات، عند الإسناد بالتفكيك:

let key = 'z';
let {[key]: foo} = {z: 'bar'};

console.log(foo); // "bar"

معامل البقية عند إسناد الكائنات بالتفكيك

let {a, b, ...rest} = {a: 10, b: 20, c: 30, d: 40}
a; // 10 
b; // 20 
rest; // { c: 30, d: 40 }

أسماء خاصيات للكائنات غير صالحة كمُعرِّفات

يمكن توفير اسم بديل عن الخاصيات التي لا تصلح كمُعرِّفات للمتغيرات في JavaScript:

const foo = { 'fizz-buzz': true };
const { 'fizz-buzz': fizzBuzz } = foo;

console.log(fizzBuzz); // "true"

دعم المتصفحات

الميزة Chrome Firefox Internet Explorer Opera Safari
الدعم الأساسي 49 41 غير مدعومة نعم 8
الدعم في المصفوفات 49 41 غير مدعومة نعم غير مدعومة
الدعم في الكائنات 60 55 غير مدعومة نعم غير مدعومة

على النقيض من متصفح IE، يدعم متصفح Edge الإسناد بالتفكيك في المصفوفات (دونًا عن الكائنات).

مصادر ومواصفات