نصائح وحيل ES6 لجعل التعليمات البرمجية أكثر وضوحًا وأقصر وأسهل في القراءة!

نصائح وحيل ES6 لجعل التعليمات البرمجية أكثر وضوحًا وأقصر وأسهل في القراءة!

حرفية القالب

تجعل القوالب الحرفية العمل مع السلاسل أسهل بكثير من ذي قبل. لقد بدأت بعلامة ظهر ، ويمكن أن تحتوي على متغيرات مدرجة باستخدام ${variable}. قارن هذين السطرين من التعليمات البرمجية:

var fName = 'Peter', sName = 'Smith', age = 43, job= 'photographer';var a = 'Hi, I\'m ' + fName + ' ' + sName + ', I\'m ' + age + ' and work as a ' + job + '.';var b = `Hi, I'm ${ fName } ${ sName }, I'm ${ age } and work as a ${ job }.`;

هذا يجعل الحياة أبسط بكثير والرمز أسهل في القراءة. يمكنك وضع أي شيء داخل الأقواس المتعرجة: المتغيرات أو المعادلات أو استدعاءات الوظائف. سأستخدم هذه في الأمثلة في جميع أنحاء هذه المقالة.

تحديد النطاق اللغوي

لطالما تم تحديد نطاق JavaScript بواسطة الدوال ، وهذا هو السبب في أنه أصبح من الشائع التفاف ملف JavaScript بالكامل في تعبير دالة فارغ تم استدعاؤه على الفور (IIFE). يتم ذلك لعزل جميع المتغيرات في الملف ، لذلك لا توجد تعارضات متغيرة.

الآن ، لدينا نطاق الكتلة وإعلانين متغيرين جديدين مرتبطين بكتلة.

إعلان 'دعونا'

هذا مشابه varلكن به بعض الاختلافات الملحوظة. نظرًا لأنه تم تحديد نطاقه ، يمكن الإعلان عن متغير جديد يحمل نفس الاسم دون التأثير على المتغيرات الخارجية.

var a = 'car' ;{ let a = 5; console.log(a) // 5}console.log(a) // car

نظرًا لارتباطه بنطاق الكتلة ، فإنه يحل سؤال المقابلة الكلاسيكي:

"ما هو الناتج ، وكيف ستجعله يعمل كما تتوقع؟"

for (var i = 1; i  { console.log(i); }, 1000);}

في هذه الحالة يكون الناتج "5 5 5 5 5" لأن المتغير i يتغير في كل تكرار.

إذا قمت بالتبديل varلذلك letكل شيء يتغير. الآن ، تنشئ كل حلقة نطاق كتلة جديدًا بقيمة أنا مرتبطة بتلك الحلقة. على الرغم من أنك كتبت:

{let i = 1; setTimeout(() => { console.log(i) }, 1000)} {let i = 2; setTimeout(() => { console.log(i) }, 1000)} {let i = 3; setTimeout(() => { console.log(i) }, 1000)} {let i = 4; setTimeout(() => { console.log(i) }, 1000)} {let i = 5; setTimeout(() => { console.log(i) }, 1000)} 

فرق آخر بين varو letهو أن ذلك letلم يتم رفعه كما varهو.

{ console.log(a); // undefined console.log(b); // ReferenceError var a = 'car'; let b = 5;}

نظرًا لتشديد نطاقه وسلوكه الأكثر قابلية للتنبؤ ، قال بعض الأشخاص أنه يجب عليك استخدامه letبدلاً من var، باستثناء الحالات التي تحتاج فيها تحديدًا إلى رفع أو تحديد نطاق varالإعلان.

مقدار ثابت

إذا كنت تريد الإعلان عن متغير ثابت في JavaScript من قبل ، فقد كان من المعتاد تسمية المتغير في أحرف كبيرة للكتل. ومع ذلك ، فإن هذا لن يؤمن المتغير - فقط دع المطورين الآخرين يعرفون أنه ثابت ولا ينبغي تغييره.

الآن لدينا constالإعلان.

{ const c = "tree"; console.log(c); // tree c = 46; // TypeError! }

constلا تجعل المتغير ثابتًا ، فقط يقفل تعيينه. إذا كان لديك مهمة معقدة (كائن أو مصفوفة) ، فلا يزال من الممكن تعديل القيمة.

{ const d = [1, 2, 3, 4]; const dave = { name: 'David Jones', age: 32}; d.push(5); dave.job = "salesman"; console.log(d); // [1, 2, 3, 4, 5] console.log(dave); // { age: 32, job: "salesman", name: 'David Jones'}}

مشكلة في وظائف تحديد النطاق

تم تحديد إعلانات الوظائف الآن لتكون مرتبطة بمسح النطاق.

{ bar(); // works function bar() { /* do something */ }}bar(); // doesn't work

تأتي المشكلة عندما تعلن عن دالة داخل ifبيان.

ضع في اعتبارك هذا:

if ( something) { function baz() { console.log('I passed') }} else { function baz() { console.log('I didn\'t pass') } } baz();

قبل ES6 ، كان من الممكن رفع كلا الإعلانين الوظيفيين وستكون النتيجة 'I didn\'t pass'بغض النظر عما somethingكان.

الآن نحصل عليه 'ReferenceError'، كما bazهو الحال دائمًا بنطاق الكتلة.

الانتشار

يقدم ES6 ...المشغل ، والذي يشار إليه باسم "مشغل الانتشار". له استخدامان رئيسيان: نشر مصفوفة أو كائن في مصفوفة أو كائن جديد ، وربط عدة معاملات في مصفوفة.

حالة الاستخدام الأولى هي الحالة التي من المحتمل أن تصادفها أكثر من غيرها ، لذلك سننظر في ذلك أولاً.

let a = [3, 4, 5];let b = [1, 2, ...a, 6];console.log(b); // [1, 2, 3, 4, 5, 6]

يمكن أن يكون هذا مفيدًا جدًا لتمرير مجموعة من المتغيرات إلى دالة من مصفوفة.

function foo(a, b, c) { console.log(`a=${a}, b=${b}, c=${c}`)} let data = [5, 15, 2];foo( ...data); // a=5, b=15, c=2

يمكن أيضًا نشر كائن ، وإدخال كل زوج من أزواج القيمة الرئيسية في الكائن الجديد. (انتشار الكائن في الواقع في المرحلة 4 من الاقتراح وسيكون رسميًا في ES2018. وهو مدعوم فقط بواسطة Chrome 60 أو أحدث ، و Firefox 55 أو أحدث ، و Node 6.4.0 أو أحدث)

let car = { type: 'vehicle ', wheels: 4};let fordGt = { make: 'Ford', ...car, model: 'GT'};console.log(fordGt); // {make: 'Ford', model: 'GT', type: 'vehicle', wheels: 4}

ميزة أخرى لعامل الانتشار هي أنه يقوم بإنشاء مصفوفة أو كائن جديد. المثال أدناه ينشئ مصفوفة جديدة لـ b، لكنه cيشير فقط إلى نفس المصفوفة.

let a = [1, 2, 3];let b = [ ...a ];let c = a;b.push(4);console.log(a); // [1, 2, 3]console.log(b); // [1, 2, 3, 4] referencing different arraysc.push(5);console.log(a); // [1, 2, 3, 5] console.log(c); // [1, 2, 3, 5] referencing the same array

حالة الاستخدام الثانية هي تجميع المتغيرات معًا في مصفوفة. هذا مفيد جدًا عندما لا تعرف عدد المتغيرات التي يتم تمريرها إلى دالة.

function foo(...args) { console.log(args); } foo( 'car', 54, 'tree'); // [ 'car', 54, 'tree' ] 

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

يمكن الآن تحديد الوظائف بالمعلمات الافتراضية. تتم تهيئة القيم المفقودة أو غير المعرفة بالقيمة الافتراضية. فقط كن حذرًا - لأنه يتم فرض القيم الخالية والخاطئة على 0.

function foo( a = 5, b = 10) { console.log( a + b);} foo(); // 15foo( 7, 12 ); // 19foo( undefined, 8 ); // 13foo( 8 ); // 18foo( null ); // 10 as null is coerced to 0

يمكن أن تكون القيم الافتراضية أكثر من مجرد قيم - يمكن أن تكون أيضًا تعبيرات أو وظائف.

function foo( a ) { return a * 4; }function bar( x = 2, y = x + 4, z = foo(x)) { console.log([ x, y, z ]);}bar(); // [ 2, 6, 8 ]bar( 1, 2, 3 ); //[ 1, 2, 3 ] bar( 10, undefined, 3 ); // [ 10, 14, 3 ]

التدمير

التدمير هو عملية تفكيك المصفوفة أو الكائن الموجود على الجانب الأيسر من علامة التساوي. يمكن أن تأتي المصفوفة أو الكائن من متغير أو دالة أو معادلة.

let [ a, b, c ] = [ 6, 2, 9];console.log(`a=${a}, b=${b}, c=${c}`); //a=6, b=2, c=9
function foo() { return ['car', 'dog', 6 ]; } let [ x, y, z ] = foo();console.log(`x=${x}, y=${y}, z=${z}`); // x=car, y=dog, z=6

مع إتلاف الكائن ، يمكن إدراج مفاتيح الكائن داخل الأقواس المتعرجة لاستخراج زوج المفتاح والقيمة.

function bar() { return {a: 1, b: 2, c: 3}; }let { a, c } = bar();console.log(a); // 1console.log(c); // 3console.log(b); // undefined

Sometimes, you want to extract the values but assign them to a new variable. This is done using a 'key: variable' pairing on the left of the equals sign.

function baz() { return { x: 'car', y: 'London', z: { name: 'John', age: 21} }; }let { x: vehicle, y: city, z: { name: driver } } = baz();
console.log( `I'm going to ${city} with ${driver} in their ${vehicle}.`); // I'm going to London with John in their car. 

Another thing that object destructuring allows is assigning a value to multiple variables.

let { x: first, x: second } = { x: 4 };console.log( first, second ); // 4, 4

Object Literals and Concise Parameters

When you are creating an object literal from variables, ES6 allows you to omit the key if it is the same as the variable name.

let a = 4, b = 7;let c = { a: a, b: b };let concise = { a, b };console.log(c, concise) // {a: 4, b: 7}, {a: 4, b: 7}

This can also be used in combination with destructuring to make your code much simpler and cleaner.

function foo() { return { name: 'Anna', age: 56, job: { company: 'Tesco', title: 'Manager' } };} 
// pre ES6let a = foo(), name = a.name, age = a.age, company = a.job.company;
// ES6 destructuring and concise parameters let { name, age, job: {company}} = foo();

It can also be used to destructure objects passed into functions. Method 1 and 2 are how you would have done it before ES6, and method 3 uses destructuring and concise parameters.

let person = { name: 'Anna', age: 56, job: { company: 'Tesco', title: 'Manager' }};
// method 1function old1( person) { var yearOfBirth = 2018 - person.age; console.log( `${ person.name } works at ${ person.job.company } and was born in ${ yearOfBirth }.`);}
// method 2function old1( person) { var age = person.age, yearOfBirth = 2018 - age, name = person.name, company = person.job.company; console.log( `${ name } works at ${ company } and was born in ${ yearOfBirth }.`);} 
// method 3function es6({ age, name, job: {company}}) { var yearOfBirth = 2018 - age; console.log( `${ name } works at ${ company } and was born in ${ yearOfBirth }.`);} 

Using ES6, we can extract the age, name and company without extra variable declaration.

Dynamic Property Names

ES6 adds the ability to create or add properties with dynamically assigned keys.

let city= 'sheffield_';let a = { [ city + 'population' ]: 350000};a[ city + 'county' ] = 'South Yorkshire';console.log(a); // {sheffield_population: 350000, sheffield_county: 'South Yorkshire' }

Arrow Functions

Arrow functions have two main aspects: their structure and their this binding.

They can have a much simpler structure than traditional functions because they don't need the function key word, and they automatically return whatever is after the arrow.

var foo = function( a, b ) { return a * b;} 
let bar = ( a, b ) => a * b;

If the function requires more than a simple calculation, curly braces can be used and the function returns whatever is returned from the block scope.

let baz = ( c, d ) => { let length = c.length + d.toString().length; let e = c.join(', '); return `${e} and there is a total length of ${length}`;}

One of the most useful places for arrow functions is in array functions like .map, .forEach or .sort.

let arr = [ 5, 6, 7, 8, 'a' ];let b = arr.map( item => item + 3 );console.log(b); // [ 8, 9, 10, 11, 'a3' ]

As well as having a shorter syntax, it also fixes the issues that often arose around the this binding behaviour. The fix with pre-ES6 functions was to store the this reference, often as a self variable.

var clickController = { doSomething: function (..) { var self = this; btn.addEventListener( 'click', function() { self.doSomething(..) }, false ); } };

This had to be done because the this binding is dynamic. This means that the this inside the event listener and the this inside the doSomething do not refer to the same thing.

Inside arrow functions, the this binding is lexical, not dynamic. This was the main design feature of the arrow function.

Whilst lexical this binding can be great, sometimes that's not what is wanted.

let a = { oneThing: ( a ) => { let b = a * 2; this.otherThing(b); }, otherThing: ( b ) => {....} };
a.oneThing(6);

When we use a.oneThing(6), the this.otherThing( b ) reference fails as this doesn't point to the a object, but to the surrounding scope. If you are rewriting legacy code using ES6 syntax, this is something to watch out for.

for … of Loops

ES6 adds a way to iterate over each of the values in an array. This is different from the existing for ... in loop that loops over the key/index.

let a = ['a', 'b', 'c', 'd' ];// ES6 for ( var val of a ) { console.log( val );} // "a" "b" "c" "d"// pre-ES6 for ( var idx in a ) { console.log( idx );} // 0 1 2 3

Using the new for … of loop saves adding a let val = a[idx] inside each loop.

Arrays, strings, generators and collections are all iterable in standard JavaScript. Plain objects can't normally be iterated over, unless you have defined an iterator for it.

Number Literals

ES5 code handled decimal and hexadecimal number formats well, but octal form wasn't specified. In fact, it was actively disallowed in strict mode.

أضاف ES6 تنسيقًا جديدًا ، مضيفًا oبعد الحرف الأول 0للإعلان عن الرقم ثماني. لقد قاموا أيضًا بإضافة تنسيق ثنائي.

Number( 29 ) // 29Number( 035 ) // 35 in old octal form. Number( 0o35 ) // 29 in new octal form Number( 0x1d ) // 29 in hexadecimal Number( 0b11101 ) // 29 in binary form

وأكثر بكثير…

هناك الكثير والكثير مما يقدمه لنا ES6 لجعل الكود الخاص بنا أنظف وأقصر وأسهل في القراءة وأكثر قوة. أهدف إلى كتابة استمرار لهذه المقالة يغطي الأجزاء الأقل شهرة من ES6.

إذا كنت لا تستطيع الانتظار كل هذا الوقت ، يمكنك قراءة كتاب Kyle Simpson's You Don't Know JS على ES6 ، أو تحقق من هذا الموقع الصغير الرائع!

هل تريد أن تصبح مطورًا وتحصل على أول وظيفة برمجية لك؟ قم بتنزيل الخطوات السبع لتصبح مطورًا وتحصل على وظيفتك الأولى.

التالي -> كيفية تأمين وظيفة أحلامك. إتقان عملية المقابلة

إذا أعجبك هذا ووجدته مفيدًا ، أظهر دعمك من خلال التصفيق والاشتراك للحصول على المزيد من المقالات مثل هذه!