এনক্যাপসুলেটেড বেনামে ফাংশন সিনট্যাক্স ব্যাখ্যা করুন


372

সারসংক্ষেপ

আপনি জাভাস্ক্রিপ্টে এনক্যাপসুলেটেড বেনাম ফাংশনগুলির জন্য সিনট্যাক্সের পিছনের যুক্তিটি ব্যাখ্যা করতে পারেন? কেন এই কাজ করে: (function(){})();কিন্তু এটি করে না function(){}();:?


আমি কি জানি

জাভাস্ক্রিপ্টে, কেউ এর মতো একটি নামযুক্ত ফাংশন তৈরি করে:

function twoPlusTwo(){
    alert(2 + 2);
}
twoPlusTwo();

আপনি একটি বেনামে ফাংশনও তৈরি করতে পারেন এবং এটিকে একটি ভেরিয়েবলের জন্য নির্ধারণ করতে পারেন:

var twoPlusTwo = function(){
    alert(2 + 2);
};
twoPlusTwo();

আপনি কোনও বেনামে ফাংশন তৈরি করে কোডের একটি ব্লককে encapsulate করতে পারেন, তারপরে এটি বন্ধনীতে মোড়ানো এবং অবিলম্বে এটি কার্যকর করে:

(function(){
    alert(2 + 2);
})();

সম্ভাব্য বিরোধী ভেরিয়েবলের সাথে বর্তমান স্কোপ বা গ্লোবাল স্কোপকে বিশৃঙ্খলা এড়াতে - মডেলাইজড স্ক্রিপ্টগুলি তৈরি করার সময় এটি দরকারী, যেমন গ্রিসমোনকি স্ক্রিপ্টস, জিকুয়েরি প্লাগইন ইত্যাদির ক্ষেত্রে

এখন, আমি বুঝতে পারি যে এটি কেন কাজ করে। বন্ধনীগুলি বিষয়বস্তুগুলি আবদ্ধ করে এবং কেবল ফলাফল প্রকাশ করে (আমি নিশ্চিত যে এটির বর্ণনা করার আরও ভাল উপায় আছে) যেমন এর সাথে (2 + 2) === 4


আমি কি বুঝতে পারি না

তবে কেন এটি সমানভাবে কাজ করে না তা আমি বুঝতে পারি না:

function(){
    alert(2 + 2);
}();

আপনি কি আমাকে তা ব্যাখ্যা করতে পারেন?


39
আমি মনে করি এই সমস্ত বিচিত্র স্বরলিপি এবং সংজ্ঞা / সেটিং / কলিং ফাংশনগুলি প্রাথমিকভাবে জাভাস্ক্রিপ্টের সাথে কাজ করার সবচেয়ে বিভ্রান্তিকর অংশ। লোকেরা তাদের সম্পর্কেও কথা বলতে চায় না। এটি গাইড বা ব্লগের উপর জোর দেওয়া বিষয় নয়। এটি আমার মনকে উড়িয়ে দেয় কারণ এটি বেশিরভাগ মানুষের জন্য বিভ্রান্তিকর কিছু এবং জেএস-তে সাবলীল লোকেরা অবশ্যই এর মধ্যে দিয়ে গেছে। এটি এই ফাঁকা নিষিদ্ধ বাস্তবের মতো যা নিয়ে কখনই কথা হয় না।
আহনিবিজ্যাকড

1
এছাড়াও এই নির্মাণের উদ্দেশ্য সম্পর্কে পড়ুন , বা একটি ( প্রযুক্তিগত ) ব্যাখ্যা ( এখানেও ) পরীক্ষা করুন। প্রথম বন্ধনী স্থাপনের জন্য, তাদের অবস্থান সম্পর্কে এই প্রশ্নটি দেখুন ।
বার্গি

ওটি: যারা এই
বেনাম

এটি অবিলম্বে আমন্ত্রিত ফাংশন এক্সপ্রেশন (আইআইএফই) এর একটি সাধারণ কেস।
আমিনু কানো

উত্তর:


410

এটি কাজ করে না কারণ এটি একটি হিসাবে পার্স করা হচ্ছে FunctionDeclaration, এবং ফাংশন ঘোষণার নাম সনাক্তকারী বাধ্যতামূলক

যখন আপনি এটি প্রথম বন্ধনী দিয়ে ঘিরেছেন তখন এটি হিসাবে মূল্যায়ন করা হয় FunctionExpression, এবং ফাংশন এক্সপ্রেশনগুলি নামকরণ করা যায় কি না।

ব্যাকরণটি এর FunctionDeclarationমতো দেখতে:

function Identifier ( FormalParameterListopt ) { FunctionBody }

এবং FunctionExpressionএস:

function Identifieropt ( FormalParameterListopt ) { FunctionBody }

আপনি দেখতে পাচ্ছেন Identifier(আইডেন্টিফায়ার অপ্ট ) টোক ইনটি al FunctionExpressionচ্ছিক, সুতরাং আমাদের নাম নির্ধারিত ছাড়াই একটি ফাংশন এক্সপ্রেশন থাকতে পারে:

(function () {
    alert(2 + 2);
}());

বা নামযুক্ত ফাংশন এক্সপ্রেশন:

(function foo() {
    alert(2 + 2);
}());

পেরেন্টেসিস (আনুষ্ঠানিকভাবে গ্রুপিং অপারেটর নামে পরিচিত ) কেবলমাত্র প্রকাশের চারপাশে থাকতে পারে এবং একটি ফাংশন এক্সপ্রেশন মূল্যায়ন করা হয়।

ব্যাকরণ দুটি উত্পাদন অস্পষ্ট হতে পারে, এবং তারা ঠিক একই দেখতে পারে, উদাহরণস্বরূপ:

function foo () {} // FunctionDeclaration

0,function foo () {} // FunctionExpression

পার্সার জানে এটি প্রাসঙ্গিক যেখানে এটি প্রদর্শিত হবে তার উপর নির্ভর করে এটি একটি FunctionDeclarationবা একটি কিনা।FunctionExpression

উপরের উদাহরণে, দ্বিতীয়টি একটি এক্সপ্রেশন, কারণ কমা অপারেটরটি কেবলমাত্র এক্সপ্রেশনগুলি পরিচালনা করতে পারে।

অন্যদিকে, FunctionDeclarationএসগুলি কেবলমাত্র " Program" কোড বলা হয় যার অর্থ বিশ্বব্যাপী সুযোগের বাইরে কোড এবং FunctionBodyঅন্য ফাংশনের অভ্যন্তরের অভ্যন্তরে কোড উপস্থিত হতে পারে।

ব্লকের অভ্যন্তরীণ ক্রিয়াকলাপগুলি এড়ানো উচিত, কারণ তারা একটি অনির্দেশ্য আচরণের নেতৃত্ব দিতে পারে, যেমন:

if (true) {
  function foo() {
    alert('true');
  }
} else {
  function foo() {
    alert('false!');
  }
}

foo(); // true? false? why?

উপরের কোডটি আসলে একটি উত্পন্ন করা উচিত SyntaxError, যেহেতু Blockকেবলমাত্র একটি বিবৃতি থাকতে পারে (এবং ইসমাএসক্রিপ্ট নির্দিষ্টকরণ কোনও ফাংশন বিবৃতি সংজ্ঞায়িত করে না), তবে বেশিরভাগ বাস্তবায়ন সহনীয় এবং কেবলমাত্র দ্বিতীয়টি ফাংশন গ্রহণ করবে, যা সতর্কতা দেয় 'false!'

মজিলা বাস্তবায়নগুলি - রাইনো, স্পাইডারমনকি - এর একটি আলাদা আচরণ রয়েছে। তাদের ব্যাকরণটিতে একটি অ-মানক ফাংশন বিবৃতি রয়েছে, যার অর্থ ফাংশনটি রান-টাইমে মূল্যায়ন করা হবে , পার্স সময়ে নয়, যেমনটি FunctionDeclarationএস এর সাথে ঘটে । এই বাস্তবায়নে আমরা প্রথম ফাংশনটি সংজ্ঞায়িত করব।


ক্রিয়াকলাপগুলি বিভিন্ন উপায়ে ঘোষণা করা যেতে পারে, নিম্নলিখিতগুলির সাথে তুলনা করুন :

1- একটি ফাংশন নির্ধারিত ফাংশন কনস্ট্রাক্টরের সাথে ভেরিয়েবলের বহুগুণে নির্ধারিত :

var multiply = new Function("x", "y", "return x * y;");

2- একটি ফাংশন একটি ফাংশন ঘোষণা নামে সংখ্যাবৃদ্ধি :

function multiply(x, y) {
    return x * y;
}

3- একটি ফাংশন এক্সপ্রেশনটি ভেরিয়েবলের গুণকে নির্ধারিত হয় :

var multiply = function (x, y) {
    return x * y;
};

4- একটি নামাঙ্কিত ফাংশন অভিব্যক্তি FUNC_NAME পরিবর্তনশীল নির্ধারিত সংখ্যাবৃদ্ধি :

var multiply = function func_name(x, y) {
    return x * y;
};

2
সিএমএসের উত্তরটি সঠিক। ফাংশন ঘোষণা এবং এক্সপ্রেশনগুলির একটি গভীর গভীরতার জন্য, এই নিবন্ধটি কাঙ্গাক্স দ্বারা দেখুন
টিম ডাউন

এটি একটি দুর্দান্ত উত্তর। এটি উত্সের পাঠ্যকে কীভাবে পার্স করা হয়- এবং বিএনএফের কাঠামোর সাথে নিবিড়ভাবে যুক্ত বলে মনে হচ্ছে। আপনার উদাহরণ 3 এ, আমি কি বলতে পারি যে এটি একটি ফাংশন এক্সপ্রেশন কারণ এটি একটি সমান চিহ্ন হিসাবে অনুসরণ করে, যে আকারটি কোনও ফাংশন ডিক্লেয়ারেশন / বিবৃতি যখন নিজেই কোনও লাইনে প্রদর্শিত হয়? আমি অবাক হই যে এর উদ্দেশ্যটি কী হবে - এটি কেবল একটি নামকৃত ফাংশন ঘোষণার হিসাবে ব্যাখ্যা করা হয়েছে, তবে কোনও নাম ছাড়াই? যদি আপনি এটিকে কোনও ভেরিয়েবলের উপর অর্পণ না করে, নামকরণ না করে বা কল দিচ্ছেন না তবে এটি কী উদ্দেশ্যে কাজ করে?
ব্রেটন

1
আহা। খুব দরকারী. ধন্যবাদ, সিএমএস মোজিলা ডক্স যে আপনার লিঙ্ক এই অংশটি বিশেষভাবে জ্ঞানগর্ভ হয়: developer.mozilla.org/En/Core_JavaScript_1.5_Reference/...
Premasagar

1
+1, যদিও আপনার ক্রিয়াকলাপের এক্সপ্রেশনটিতে ভুল অবস্থানে বন্ধন বন্ধনী ছিল :-)
নিকফিটজ

1
@ গোবিন্দরাই, নং ফাংশন ঘোষণাগুলি সংকলনের সময় পরিচালনা করা হয় এবং একটি সদৃশ ফাংশন ঘোষণা পূর্ববর্তী ঘোষণাকে ওভাররাইড করে। রানটাইমের সময়, ফাংশন ঘোষণাটি ইতিমধ্যে উপলব্ধ এবং এই ক্ষেত্রে, যেটি উপলব্ধ তা হ'ল "মিথ্যা" সতর্ক করে। আরও তথ্যের জন্য, পড়ুন আপনি জেএস জানেন না
সৌরভ মিসরা

50

যদিও এটি একটি পুরানো প্রশ্নোত্তর, এটি এমন একটি বিষয় নিয়ে আলোচনা করে যা আজ অবধি অনেক বিকাশকারীকে একটি লুপের জন্য ফেলে দেয়। আমি যে জাভাস্ক্রিপ্ট বিকাশকারী প্রার্থীর সাথে সাক্ষাত্কার নিয়েছি তার সংখ্যা গণনা করতে পারি না যারা আমাকে কোন ফাংশন ঘোষণার এবং একটি ফাংশন প্রকাশের মধ্যে পার্থক্য বলতে পারেনি এবং যার সাথে সাথে অনুরোধ করা ফাংশন এক্সপ্রেশন কী তা সম্পর্কে কোনও ধারণা নেই।

যদিও আমি উল্লেখ করতে চাই, একটি খুব গুরুত্বপূর্ণ বিষয় যা প্রেমেসাগরের কোড স্নিপেট একটি নাম শনাক্তকারী দেওয়া হলেও তা কাজ করবে না।

function someName() {
    alert(2 + 2);
}();

এটি কাজ না করার কারণটি হ'ল জাভাস্ক্রিপ্ট ইঞ্জিন এটিকে সম্পূর্ণরূপে সম্পর্কযুক্ত গ্রুপিং অপারেটরের দ্বারা কোনও ফাংশন ঘোষণার হিসাবে ব্যাখ্যা করে এবং গোষ্ঠী অপারেটরদের অবশ্যই একটি এক্সপ্রেশন থাকতে পারে। জাভাস্ক্রিপ্ট অনুসারে, উপরের কোডের স্নিপেটটি নীচের সাথে সমান।

function someName() {
    alert(2 + 2);
}

();

আমি আরেকটি বিষয় উল্লেখ করতে চাই যে কিছু লোকের কিছুটা ব্যবহার হতে পারে তা হ'ল যে কোনও নাম শনাক্তকারী আপনি কোনও ফাংশন এক্সপ্রেশন হিসাবে সরবরাহ করেন সেটি ফাংশন সংজ্ঞা থেকে নিজেকে বাদ দিয়ে কোডের প্রসঙ্গে বেশ ব্যর্থ is

var a = function b() {
    // do something
};
a(); // works
b(); // doesn't work

var c = function d() {
    window.setTimeout(d, 1000); // works
};

অবশ্যই, ডিবাগিং কোডের ক্ষেত্রে আপনার ফাংশন সংজ্ঞা সহ নাম শনাক্তকারীদের ব্যবহার সর্বদা সহায়ক, তবে এটি সম্পূর্ণ অন্য কিছু ... :-)


17

দুর্দান্ত উত্তর ইতিমধ্যে পোস্ট করা হয়েছে। তবে আমি লক্ষ করতে চাই যে ফাংশন ঘোষণাগুলি একটি খালি সমাপ্তির রেকর্ড ফিরিয়ে দেয়:

14.1.20 - রানটাইম শব্দার্থক: মূল্যায়ন

FunctionDeclaration : function BindingIdentifier ( FormalParameters ) { FunctionBody }

  1. সাধারণ কমপ্লিট (খালি) ফিরুন ।

এই সত্যটি পর্যবেক্ষণ করা সহজ নয়, কারণ প্রত্যাশিত মান পাওয়ার চেষ্টার বেশিরভাগ উপায়গুলি ফাংশন ঘোষণাকে একটি ফাংশন প্রকাশে রূপান্তরিত করে। তবে evalএটি দেখায়:

var r = eval("function f(){}");
console.log(r); // undefined

খালি সমাপ্তির রেকর্ড কল করা কোনও অর্থহীন নয়। সে কারণেই function f(){}()কাজ করতে পারি না। আসলে জেএস ইঞ্জিন এটিকে কল করার চেষ্টাও করে না, প্রথম বন্ধনীকে অন্য বিবৃতিটির অংশ হিসাবে বিবেচনা করা হয়।

তবে আপনি যদি বন্ধনীতে ফাংশনটি আবদ্ধ করেন তবে এটি একটি ফাংশন এক্সপ্রেশন হয়ে যায়:

var r = eval("(function f(){})");
console.log(r); // function f(){}

ফাংশন এক্সপ্রেশন একটি ফাংশন অবজেক্ট প্রদান করে। এবং তাই আপনাকে কল করতে পারেন: (function f(){})()


লজ্জা এই উত্তর উপেক্ষা করা হয়। গৃহীত উত্তরের মতো বিস্তৃত না হলেও এটি কিছু খুব দরকারী অতিরিক্ত তথ্য সরবরাহ করে এবং আরও বেশি ভোটের দাবি রাখে
অভ্রোহোম ইয়িসরোয়েল

10

জাভাস্ক্রিপ্টে এটিকে তাত্ক্ষণিকভাবে আহ্বান করা ফাংশন এক্সপ্রেশন (আইআইএফই) বলা হয়

এটিকে একটি ক্রিয়াকলাপের অভিব্যক্তি হিসাবে গড়ে তুলতে আপনাকে:

  1. () ব্যবহার করে এটি বন্ধ করুন

  2. এটির আগে একটি শূন্য অপারেটর রাখুন

  3. এটি একটি ভেরিয়েবলকে বরাদ্দ করুন।

অন্যথায় এটি ফাংশন সংজ্ঞা হিসাবে বিবেচিত হবে এবং তারপরে আপনি নিম্নলিখিত পদ্ধতিতে একই সাথে কল করতে / অনুরোধ করতে পারবেন না:

 function (arg1) { console.log(arg1) }(); 

উপরেরটি আপনাকে ত্রুটি দেবে। কারণ আপনি কেবল তাত্ক্ষণিকভাবে কোনও ফাংশন প্রকাশ করতে পারেন expression

এটি বেশ কয়েকটি উপায়ে অর্জন করা যেতে পারে: ওয়ে 1:

(function(arg1, arg2){
//some code
})(var1, var2);

উপায় 2:

(function(arg1, arg2){
//some code
}(var1, var2));

উপায় 3:

void function(arg1, arg2){
//some code
}(var1, var2);

উপায় 4:

  var ll = function (arg1, arg2) {
      console.log(arg1, arg2);
  }(var1, var2);

উপরের সমস্তগুলি তত্ক্ষণাত ফাংশন এক্সপ্রেশনটি শুরু করবে।


3

আমার আর একটি ছোট মন্তব্য আছে। আপনার কোড একটি ছোট পরিবর্তন দিয়ে কাজ করবে:

var x = function(){
    alert(2 + 2);
}();

আমি আরও বিস্তৃত সংস্করণের পরিবর্তে উপরের সিনট্যাক্সটি ব্যবহার করি:

var module = (function(){
    alert(2 + 2);
})();

কারণ আমি ভিএম-তে জাভাস্ক্রিপ্ট ফাইলগুলির জন্য সঠিকভাবে কাজ করতে ইন্ডেন্টেশনটি পরিচালনা করতে পারি নি। মনে হচ্ছে খোলা বন্ধনী ভিতরে কোঁকড়ানো ধনুর্বন্ধনী পছন্দ করেন না Vim im


সুতরাং যখন এই সিনট্যাক্সটি কাজ করে যখন আপনি কার্যকর একটি ভেরিয়েবলের জন্য নির্ধারিত ফলাফল নির্ধারণ করেন, কিন্তু স্বতন্ত্র নয়?
প্যাসলি

1
@paislee - কারণ জাভাস্ক্রিপ্ট ইঞ্জিন ব্যাখ্যা করে কোনো বৈধ জাভাস্ক্রিপ্ট বিবৃতি দিয়ে শুরু functionহিসেবে শব্দ ফাংশন ঘোষণা যে ক্ষেত্রে চিহ্ন ()হিসেবে ব্যাখ্যা করা হয় গোষ্ঠীবদ্ধ অপারেটর যা, জাভাস্ক্রিপ্ট সিনট্যাক্স নিয়ম অনুযায়ী, শুধুমাত্র পারে এবং আবশ্যক একটি JavaScript অভিব্যক্তি ধারণ করে।
natlee75

1
@ বোসোনিক্স - আপনার পছন্দসই বাক্য গঠনটি ভালভাবে কাজ করে তবে আপনার উল্লেখ করা "আরও বিস্তৃত স্প্রেড সংস্করণ" বা ()গ্রুপিং অপারেটরের ( যেখানে ডগলাস ক্রকফোর্ড দৃ strongly়ভাবে প্রস্তাব দেয়) এর মধ্যে আবদ্ধ থাকে সেই রূপটি ধারাবাহিকতার জন্য ব্যবহার করা ভাল ধারণা : এটি আইআরএফইগুলি কোনও ভেরিয়েবলের দায়িত্ব ছাড়াই ব্যবহার করা সাধারণ, এবং যদি আপনি ধারাবাহিকভাবে ব্যবহার না করেন তবে এই মোড়ানো প্যারেন্টেসিসগুলি অন্তর্ভুক্ত করা ভুলে যাওয়া সহজ।
natlee75

0

সম্ভবত সংক্ষিপ্ত উত্তরটি হবে

function() { alert( 2 + 2 ); }

একটি ফাংশন আক্ষরিক যা একটি (বেনামে) ফাংশন সংজ্ঞায়িত করে। একটি অতিরিক্ত () -জোড়া, যা এক্সপ্রেশন হিসাবে ব্যাখ্যা করা হয়, শীর্ষ স্তরে প্রত্যাশিত হয় না, কেবল আক্ষরিক হয়।

(function() { alert( 2 + 2 ); })();

একটি অভিব্যক্তি বিবৃতিতে যা একটি বেনামি ফাংশন প্রার্থনা করে।


0
(function(){
     alert(2 + 2);
 })();

উপরেরটি বৈধ বাক্য গঠন কারণ প্যারেন্টেসিসের ভেতর দিয়ে পাস করা যে কোনও কিছুই ফাংশন এক্সপ্রেশন হিসাবে বিবেচিত হয়।

function(){
    alert(2 + 2);
}();

উপরে বৈধ সিনট্যাক্স নয়। কারণ জাভা স্ক্রিপ্ট সিনট্যাক্স পার্সার ফাংশন কীওয়ার্ডের পরে ফাংশনটির নাম সন্ধান করে যেহেতু এটি কোনও ত্রুটি নিক্ষেপ করে এমন কিছুই খুঁজে পায় না।


2
আপনার উত্তরটি ভুল না হলেও গ্রহণযোগ্য উত্তর ইতিমধ্যে ডিপ্টে এই সমস্তটি কভার করে।
আর্নল্ড

0

আপনি এটির মতো ব্যবহার করতে পারেন:

! function() { console.log('yeah') }()

অথবা

!! function() { console.log('yeah') }()

!- অবহেলা অপশনটি fn সংজ্ঞাটিকে fn অভিব্যক্তিতে রূপান্তরিত করে, সুতরাং, আপনি এটির সাথে সাথেই এটি শুরু করতে পারেন ()। ব্যবহার হিসাবে 0,fn defবা একইvoid fn def


-1

এগুলি যেমন প্যারামিটার-আর্গুমেন্টের সাথে ব্যবহার করা যেতে পারে

var x = 3; 
var y = 4;

(function(a,b){alert(a + b)})(x,y)

7 হিসাবে ফলাফল হবে


-1

এই অতিরিক্ত বন্ধনী গ্লোবাল নেমস্পেস এবং বেনামে ফাংশনগুলির মধ্যে অতিরিক্ত বেনামী ফাংশন তৈরি করে যাতে কোড রয়েছে। এবং জাভাস্ক্রিপ্ট ফাংশনগুলির মধ্যে অন্যান্য ফাংশনগুলির মধ্যে ঘোষিত কেবল প্যারেন্ট ফাংশনের নেমস্পেসের অ্যাক্সেস করতে পারে। বিশ্বব্যাপী সুযোগ এবং প্রকৃত কোড স্কোপিংয়ের মধ্যে অতিরিক্ত অবজেক্ট (বেনামে ফাংশন) থাকায় এটি ধরে রাখা যায় না।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.