تفاوت بین توابع معمولی و توابع Arrow

توابع در جاوااسکریپت به دو روش‌ مختلف می‌توانند تعریف شوند. یکی از این روش‌ها، تابع  arrow نام دارد. این تابع یکی از ویژگی‌های جدیدی هست که در ES6 معرفی شده است و یک شکل ساده‌تر و کوتاه‌تر برای نوشتن تابع می‌باشد. اگرچه هر دو نوع توابع کار یکسانی را انجام می‌دهند، اما تفاوت‌هایی نیز بین آن‌ها وجود دارد. در این مقاله قصد داریم تا بیشتر در مورد تفاوت بین توابع معمولی و توابع arrow صحبت کنیم.

سینتکس

مثالی از یک تابع arrow در زیر داریم:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// (param1, param2, paramN) => expression
// ES5
var add = function(x, y) {
return x + y;
};
// ES6
let add = (x, y) => { return x + y };
// (param1, param2, paramN) => expression // ES5 var add = function(x, y) { return x + y; }; // ES6 let add = (x, y) => { return x + y };
// (param1, param2, paramN) => expression
// ES5
var add = function(x, y) {
  return x + y;
};
// ES6
let add = (x, y) => { return x + y };

سینتکس تابع arrow به توسعه دهنده اجازه می‌دهد تا تابع را با تعداد خط کد کم‌تر بنویسد و به همان نتیجه دست پیدا کند.

اگر تابع یک خطی باشد، آکولاد لازم نیست. در این حالت، مثال بالا را می‌توانیم به شکل زیر بنویسیم:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
let add = (x, y) => x + y;
let add = (x, y) => x + y;
let add = (x, y) => x + y;

اگر تابع فقط یک آرگومان داشته باشد، حتی پرانتز نیز لازم نیست:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
let squareNum = x => x * x;
let squareNum = x => x * x;
let squareNum = x => x * x;

سوالی که پیش می‌آید این است، اگر تابع هیچ آرگومانی نداشته باشد چه اتفاقی می‌افتد؟

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
let sayHi = _ => console.log(“Hi”);
let sayHi = _ => console.log(“Hi”);
let sayHi = _ => console.log(“Hi”);

اتصال(Bind) آرگومان‌ها

توابع arrow اتصال آرگومان ندارند. یعنی نمی‌توانند در مقدار آرگومان‌ها تغییر ایجاد کنند. با این حال، آ‌‌ن‌ها به آبجکت آرگومان‌های نزدیک‌ترین تابع غیر arrow والدشان دسترسی دارند. همچنین برای گرفتن آرگومان‌های ارسال شده به توابع arrow از پارامترهای نام‌گذاری شده و پارامتر Rest استفاده می‌شود.

به عنوان مثال، در توابع معمولی:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
let myFunc = {
showArgs(){
console.log(arguments);
}
};
myFunc.showArgs(1, 2, 3, 4);
let myFunc = { showArgs(){ console.log(arguments); } }; myFunc.showArgs(1, 2, 3, 4);
let myFunc = {  
 showArgs(){ 
  console.log(arguments); 
 } 
}; 
myFunc.showArgs(1, 2, 3, 4);

در خروجی نهایی، آبجکت آرگومان‌ نمایش داده می‌شود.

اما در توابع arrow:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
let myFunc = {
showArgs : () => {
console.log(...arguments);
}
};
myFunc.showArgs(1, 2, 3, 4);
let myFunc = { showArgs : () => { console.log(...arguments); } }; myFunc.showArgs(1, 2, 3, 4);
let myFunc = {  
  showArgs : () => { 
  console.log(...arguments); 
 } 
}; 
myFunc.showArgs(1, 2, 3, 4);

در خروجی نهایی هنگام فراخوانی تابع، خطای

Uncaught ReferenceError: arguments is not defined
Uncaught ReferenceError: arguments is not definedرخ می‌دهد.

کلمه کلیدی this

یکی دیگر از مواردی که تفاوت بین توابع معمولی و توابع arrow به حساب می‌آید، کلمه کلیدی this است. در تابع arrow، برخلاف تابع معمولی این ویژگی خاص وجود ندارد و  مقدار this در داخل تابع در طول چرخه عمر آن، ثابت باقی می‌ماند و به نزدیک‌ترین تابع غیر arrow والدش مربوط می‌شود.

به عنوان مثال:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
let me = {
name: "Ashutosh Verma",
thisInArrow:() => {
console.log("My name is " + this.name); // no 'this' binding here
},
thisInRegular(){
console.log("My name is " + this.name); // 'this' binding works here
}
};
me.thisInArrow();
me.thisInRegular();
let me = { name: "Ashutosh Verma", thisInArrow:() => { console.log("My name is " + this.name); // no 'this' binding here }, thisInRegular(){ console.log("My name is " + this.name); // 'this' binding works here } }; me.thisInArrow(); me.thisInRegular();
let me = { 
 name: "Ashutosh Verma", 
 thisInArrow:() => { 
 console.log("My name is " + this.name); // no 'this' binding here 
 }, 
 thisInRegular(){ 
 console.log("My name is " + this.name); // 'this' binding works here 
 } 
};
me.thisInArrow(); 
me.thisInRegular();

هنگام فراخوانی تابع ()thisInArrow کلمه کلیدی this کار نمی‌کند و اتصال(bind) صورت نمی‌گیرد، در نتیجه خروجی

"My name is"
"My name is"می‌شود. اما در زمان فراخوانی تابع ()thisInRegular، خروجی کد
"My name is Ashutosh Verma"
"My name is Ashutosh Verma"است.

کلمه کلیدی new

توابع معمولی که با عبارت function ایجاد می‌شوند، قابل ساخت(construct) و فراخوانی هستند. پس می‌توان آن‌ها را با استفاده از کلمه کلیدی new فراخوانی کرد.

اما توابع arrow فقط قابل فراخوانی هستند و قابلیت ساخته شدن ندارند، یعنی این توابع هرگز نمی‌توانند به عنوان توابع سازنده(constructor) مورد استفاده قرار بگیرند. پس نمی‌توان آن‌ها را با کلمه کلیدی new فراخوانی کرد.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
let add = (x, y) => console.log(x + y);
new add(2,3);
let add = (x, y) => console.log(x + y); new add(2,3);
let add = (x, y) => console.log(x + y);
new add(2,3);

در مثال بالا، وقتی

new add(2,3)
new add(2,3)فراخوانی می‌شود، خطای
TypeError: add is not a constructor
TypeError: add is not a constructorرخ می‌دهد.

عدم وجود پارامترها با نام‌های تکراری

در توابع arrow آرگومان‌های مختلف، چه در حالت strict و چه در حالت non-strict نمی‌توانند نام‌های تکراری داشته باشند.

به عنوان مثال، کد جاوااسکریپت زیر در حالت معمولی یک کد معتبر است:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
function add(x, x){}
function add(x, x){}
function add(x, x){}

اما هنگام استفاده از حالت strict، معتبر نخواهد بود:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
'use strict';
function add(x, x){}
// SyntaxError: duplicate formal argument x
'use strict'; function add(x, x){} // SyntaxError: duplicate formal argument x
'use strict';
function add(x, x){}
// SyntaxError: duplicate formal argument x

اما در توابع arrow آرگومان‌ها با نام‌های تکراری، چه حالت strict و چه حالت non-strict همیشه نامعتبر هستند.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
(x, x) => {}
// SyntaxError: duplicate argument names not allowed in this context
(x, x) => {} // SyntaxError: duplicate argument names not allowed in this context
(x, x) => {}
// SyntaxError: duplicate argument names not allowed in this context

 

منبع

دیدگاه‌ها:

افزودن دیدگاه جدید