سؤال

لقد بدأت مؤخرا الحفاظ على شخص آخر شفرة جافا سكريبت.أنا إصلاح الخلل وإضافة ميزات و أيضا محاولة لترتيب رمز وجعلها أكثر اتساقا.

المطور السابق يستخدم طريقتين إعلان وظائف وأنا لا يمكن أن تنجح إذا كان هناك سبب وراء ذلك أم لا.

طريقتين هي:

var functionOne = function() {
    // Some code
};
function functionTwo() {
    // Some code
}

ما هي أسباب استخدام هذه طريقتين مختلفتين و ما هي إيجابيات وسلبيات كل منها ؟ هل هناك أي شيء يمكن القيام به مع أسلوب واحد التي لا يمكن القيام به مع الآخر ؟

هل كانت مفيدة؟

المحلول

الفرق هو أن functionOne هي وظيفة التعبير و حتى معرفة فقط عندما يتم الوصول إلى خط ، بينما functionTwo هو إعلان وظيفة ويعرف بمجرد المحيطة بها وظيفة أو سيناريو يتم تنفيذه (بسبب الرفع).

على سبيل المثال وظيفة التعبير:

// TypeError: functionOne is not a function
functionOne();

var functionOne = function() {
  console.log("Hello!");
};

و إعلان وظيفة:

// Outputs: "Hello!"
functionTwo();

function functionTwo() {
  console.log("Hello!");
}

هذا يعني أيضا أنك لا يمكن مشروط تحديد المهام باستخدام وظيفة الإعلانات:

if (test) {
   // Error or misbehavior
   function functionThree() { doSomething(); }
}

سبق فعلا يعرف functionThree بغض النظر عن test's القيمة إلا إذا use strict هو في الواقع في هذه الحالة يثير ببساطة خطأ.

نصائح أخرى

أولا أريد أن الصحيح جريج: function abc(){} وراقب أيضا — اسم abc ويعرف في نطاق أين هذا التعريف هو واجهتها.على سبيل المثال:

function xyz(){
  function abc(){};
  // abc is defined here...
}
// ...but not here

ثانيا ، أنه من الممكن الجمع بين أنماط:

var xyz = function abc(){};

xyz هو ذاهب إلى تعريف كالعادة ، abc هو معروف في جميع المتصفحات إلا انترنت إكسبلورر — لا تعتمد على كونها محددة.ولكن سوف تكون محددة داخل الجسم:

var xyz = function abc(){
  // xyz is visible here
  // abc is visible here
}
// xyz is visible here
// abc is undefined here

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

function abc(){};
var xyz = abc;

في هذه الحالة, كل xyz و abc هي الأسماء المستعارة من نفس الكائن:

console.log(xyz === abc); // prints "true"

سبب واحد مقنع لاستخدام جنبا إلى جنب الاسلوب هو "اسم" سمة مهمة من الكائنات (غير معتمدة من قبل برنامج Internet Explorer).أساسا عند تعريف دالة مثل

function abc(){};
console.log(abc.name); // prints "abc"

اسمها هو تعيين تلقائيا.ولكن عند تعريف مثل

var abc = function(){};
console.log(abc.name); // prints ""

اسمها فارغة — أنشأنا مجهول وظيفة تسند إلى بعض متغير.

آخر سبب وجيه لاستخدام جنبا إلى جنب هو نمط استخدام قصيرة الداخلية اسم للإشارة إلى نفسه ، مع توفير طويلة غير متضاربة اسم المستخدمين الخارجيين:

// Assume really.long.external.scoped is {}
really.long.external.scoped.name = function shortcut(n){
  // Let it call itself recursively:
  shortcut(n - 1);
  // ...
  // Let it pass itself as a callback:
  someFunction(shortcut);
  // ...
}

في المثال أعلاه يمكننا أن نفعل نفس الشيء مع خارجي اسم لكن سيكون غير عملي جدا (أبطأ).

(طريقة أخرى للإشارة إلى نفسه هو استخدام arguments.callee, التي لا تزال طويلة نسبيا ، غير معتمدة في الوضع الدقيق.)

في أعماقي, جافا سكريبت يعامل كل البيانات بشكل مختلف.هذا هو إعلان وظيفة:

function abc(){}

abc هنا يتم تعريف في كل مكان في النطاق الحالي:

// We can call it here
abc(); // Works

// Yet, it is defined down there.
function abc(){}

// We can call it again
abc(); // Works

كما أنه رفع من خلال return بيان:

// We can call it here
abc(); // Works
return;
function abc(){}

هذه هي وظيفة التعبير:

var xyz = function(){};

xyz هنا يتم تعريف من وجهة مهمة:

// We can't call it here
xyz(); // UNDEFINED!!!

// Now it is defined
xyz = function(){}

// We can call it here
xyz(); // works

وظيفة الإعلان مقابلوظيفة التعبير هو السبب الحقيقي لماذا هناك فرق تجلى جريج.

حقيقة ممتعة:

var xyz = function abc(){};
console.log(xyz.name); // Prints "abc"

وأنا شخصيا أفضل "وظيفة التعبير" الإعلان لأن هذه الطريقة لا يمكن التحكم في الرؤية.عندما تحدد وظيفة مثل

var abc = function(){};

وأنا أعلم أنني تعريف الدالة محليا.عندما تحدد وظيفة مثل

abc = function(){};

أعلم أنني محددة على توفير أنني لم تحدد abc في أي مكان في سلسلة من النطاقات.هذا النمط من تعريف مرونة حتى عند استخدامها داخل eval().بينما تعريف

function abc(){};

يعتمد على السياق و قد أترك لكم التخمين حيث هو في الواقع تعريف ، خاصة في حالة eval() — الجواب:ذلك يعتمد على المتصفح.

هنا المتهدمة على النماذج القياسية التي تخلق وظائف: (المقالة الأصلية مكتوبة على سؤال آخر ، ولكن تكييفها بعد أن انتقلت إلى الكنسي السؤال.)

حيث:

القائمة السريعة:

  • إعلان وظيفة

  • "مجهول" function التعبير (الذي على الرغم من المصطلح في بعض الأحيان خلق الوظائف مع الأسماء)

  • اسمه function التعبير

  • Accessor وظيفة مهيئ (ES5+)

  • السهم وظيفة التعبير (ES2015+) (الذي ، مثل وظيفة مجهول التعبير لا تنطوي على صريح الاسم ، ومع ذلك يمكن أن تخلق وظائف مع الأسماء)

  • طريقة الإعلان في وجوه مهيئ (ES2015+)

  • منشئ الطريقة الإعلانات في class (ES2015+)

إعلان وظيفة

النموذج الأول هو إعلان وظيفة, التي تبدو مثل هذا:

function x() {
    console.log('x');
}

وظيفة الإعلان ، إعلان;هذا ليس بيان أو التعبير.على هذا النحو, لا اتبع ذلك مع ; (على الرغم من أن القيام بذلك هو غير مؤذية).

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

لأنه معالجتها من قبل أي خطوة بخطوة التعليمات البرمجية في نفس السياق يمكنك أن تفعل أشياء من هذا القبيل:

x(); // Works even though it's above the declaration
function x() {
    console.log('x');
}

حتى ES2015, المواصفات لم تغطي ما محرك جافا سكريبت يجب أن تفعل إذا كنت وضعت إعلان وظيفة داخل هيكل الرقابة مثل try, if, switch, while, ، وما إلى ذلك ، مثل هذا:

if (someCondition) {
    function foo() {    // <===== HERE THERE
    }                   // <===== BE DRAGONS
}

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

على الرغم من أن يفعل هذا لم يكن المحدد حتى ES2015 ، المسموح به التمديد دعم وظيفة الإعلانات في كتل.للأسف (لا محالة), محركات مختلفة فعلت أشياء مختلفة.

كما من ES2015, مواصفات يقول ماذا أفعل.في الواقع, أنه يعطي ثلاثة أشياء منفصلة القيام به:

  1. إذا كان في وضع فضفاضة لا على مستعرض ويب ، محرك جافا سكريبت من المفترض أن تفعل شيئا واحدا
  2. إذا فضفاضة في وضع مستعرض ويب ، محرك جافا سكريبت من المفترض أن تفعل شيئا آخر
  3. إذا كان في الصارم وضع (المتصفح أو لا) ، محرك جافا سكريبت من المفترض أن تفعل شيء آخر

قواعد تفقد أوضاع صعبة ، ولكن في الصارم وضع وظيفة الإعلانات في كتل سهلة:إنهم المحلية إلى كتلة (لديهم كتلة نطاق, الذي هو أيضا جديد في ES2015) وهم حاملين إلى أعلى كتلة.لذلك:

"use strict";
if (someCondition) {
    foo();               // Works just fine
    function foo() {
    }
}
console.log(typeof foo); // "undefined" (`foo` is not in scope here
                         // because it's not in the same block)

"مجهول" function التعبير

الثاني شيوعا يسمى وظيفة مجهول التعبير:

var y = function () {
    console.log('y');
};

مثل كل التعبيرات انه تقييمها عندما وصلت في خطوة بخطوة تنفيذ التعليمات البرمجية.

في ES5 ، وظيفة هذا يخلق لديه اسم (إنه مجهول).في ES2015 ، وظيفة تعيين الاسم إذا أمكن استنتاج ذلك من السياق.في المثال أعلاه, اسم يكون y.شيء مشابه يحدث هذا عندما تكون الدالة قيمة خاصية مهيئ.(لمزيد من التفاصيل على عندما يحدث هذا وقواعد البحث عن SetFunctionName في مواصفات — يبدو في جميع أنحاء المكان.)

اسمه function التعبير

النموذج الثالث هو اسمه وظيفة التعبير ("فرح"):

var z = function w() {
    console.log('zw')
};

وظيفة هذا يخلق لديه الاسم الصحيح (w في هذه الحالة).مثل كل التعبيرات ، هذا هو تقييم عندما وصلت في خطوة بخطوة تنفيذ التعليمات البرمجية.اسم الدالة هو لا إضافة إلى نطاق في التعبير تظهر ؛ اسم هو في نطاق داخل الدالة نفسها:

var z = function w() {
    console.log(typeof w); // "function"
};
console.log(typeof w);     // "undefined"

علما بأن NFEs كثيرا ما كانت مصدرا البق تطبيقات جافا سكريبت.IE8 في وقت سابق ، على سبيل المثال ، التعامل مع NFEs تماما بشكل غير صحيح, إنشاء وظائف مختلفة في أوقات مختلفة اثنين.الإصدارات في وقت مبكر من سفاري وكان المسائل أيضا.والخبر السار هو أن الإصدارات الحالية من المتصفحات (IE9 يصل الحالية سفاري) لا تملك تلك القضايا أكثر من ذلك.(ولكن حتى كتابة هذه السطور ، للأسف ، IE8 لا يزال قيد الاستخدام على نطاق واسع ، وذلك باستخدام NFEs مع رمز شبكة الإنترنت بشكل عام لا تزال إشكالية.)

Accessor وظيفة مهيئ (ES5+)

في بعض الأحيان وظائف يمكن أن يتسلل إلى حد كبير دون أن يلاحظها أحد;هذا هو الحال مع accessor وظائف.هنا مثال:

var obj = {
    value: 0,
    get f() {
        return this.value;
    },
    set f(v) {
        this.value = v;
    }
};
console.log(obj.f);         // 0
console.log(typeof obj.f);  // "number"

لاحظ أنه عندما كنت تستخدم وظيفة لم تستخدم ()!ذلك لأنها accessor وظيفة عن مكان الإقامة.ونحن على تعيين الخاصية بالطريقة العادية ، ولكن وراء الكواليس ، يتم استدعاء الدالة.

يمكنك أيضا إنشاء accessor الوظائف مع Object.defineProperty, Object.defineProperties, و شهرة الحجة الثانية أن Object.create.

السهم وظيفة التعبير (ES2015+)

ES2015 يجلب لنا السهم وظيفة.وهنا مثال واحد:

var a = [1, 2, 3];
var b = a.map(n => n * 2);
console.log(b.join(", ")); // 2, 4, 6

نرى أن n => n * 2 شيء يختبئ في map() الدعوة ؟ هذه الوظيفة.

بضعة أشياء عن وظائف السهم:

  1. ليس لديهم الخاصة بهم this.بدلا من, أنها إغلاق أكثر على this من السياق حيث أنهم محددة.(كما أنها قريبة أكثر arguments ، super.) وهذا يعني أن this ضمن لهم هو نفس this حيث أنهم خلق و لا يمكن تغييرها.

  2. كما لاحظت فإن كنت لا تستخدم الكلمات الرئيسية function;بدلا من ذلك, يمكنك استخدام =>.

على n => n * 2 المثال أعلاه هو نموذج واحد منهم.إذا كان لديك العديد من الحجج لتمرير الوظيفة ، يمكنك استخدام parens:

var a = [1, 2, 3];
var b = a.map((n, i) => n * i);
console.log(b.join(", ")); // 0, 2, 6

(تذكر أن Array#map يمر دخول أول حجة ، ومؤشر الثانية.)

في كلتا الحالتين الجسم من وظيفة هو مجرد التعبير ؛ الدالة قيمة الإرجاع سيتم تلقائيا نتيجة هذا التعبير (لا تستخدم صريح return).

إذا كنت تريد أن تفعل أكثر من مجرد تعبير واحد, استخدام {} و صريح return (إذا كنت بحاجة إلى إرجاع القيمة) ، كما هو معتاد:

var a = [
  {first: "Joe", last: "Bloggs"},
  {first: "Albert", last: "Bloggs"},
  {first: "Mary", last: "Albright"}
];
a = a.sort((a, b) => {
  var rv = a.last.localeCompare(b.last);
  if (rv === 0) {
    rv = a.first.localeCompare(b.first);
  }
  return rv;
});
console.log(JSON.stringify(a));

النسخة بدون { ... } ويسمى وظيفة السهم مع التعبير الجسم أو موجزة الجسم.(أيضا:A موجزة السهم وظيفة.) واحد مع { ... } تعريف الجسم السهم وظيفة مع وظيفة الجسم.(أيضا:A مطول السهم وظيفة.)

طريقة الإعلان في وجوه مهيئ (ES2015+)

ES2015 يسمح أقصر شكل إعلان خاصية إشارات دالة يسمى تعريف الأسلوب;يبدو مثل هذا:

var o = {
    foo() {
    }
};

تقريبا ما يعادل في ES5 في وقت سابق ليكون:

var o = {
    foo: function foo() {
    }
};

الفرق (بخلاف الإسهاب) هو أن طريقة استخدام super, ولكن وظيفة لا يمكن.لذا فعلى سبيل المثال ، إذا كان لديك كائن محدد (مثلا) valueOf باستخدام طريقة بناء الجملة ، فإنه يمكن استخدام super.valueOf() للحصول على قيمة Object.prototype.valueOf قد عاد (قبل ويفترض أن تفعل شيئا آخر به) ، بينما ES5 النسخة لديك Object.prototype.valueOf.call(this) بدلا من ذلك.

وهذا يعني أيضا أن طريقة يحتوي على مرجع إلى كائن كان يعرف ، حتى إذا كان هذا الكائن هو مؤقت (على سبيل المثال, كنت تمر في Object.assign باعتبارها واحدة من مصدر الكائنات), طريقة بناء الجملة يمكن أن يعني أن الهدف من ذلك هو الاحتفاظ في الذاكرة عندما وإلا فإنه يمكن أن يكون القمامة التي تم جمعها (إذا كان محرك جافا سكريبت لا يكشف هذا الوضع والتعامل معها إذا كان أي من أساليب يستخدم super).

منشئ الطريقة الإعلانات في class (ES2015+)

ES2015 يجلب لنا class بناء الجملة ، بما في ذلك أعلن المنشئات والطرق:

class Person {
    constructor(firstName, lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }

    getFullName() {
        return this.firstName + " " + this.lastName;
    }
}

هناك نوعان من وظيفة الإعلانات أعلاه:واحد منشئ الذي يحصل على اسم Person, و getFullName, التي هي وظيفة تسند إلى Person.prototype.

متحدثا عن السياق العالمي ، على حد سواء ، var بيان FunctionDeclaration في النهاية سيتم إنشاء غير deleteable مكان الإقامة على الكائن العالمي ، ولكن قيمة كل يمكن أن تكون الكتابة.

الفرق الدقيق بين الطريقتين هو أنه عندما متغير مثيل تشغيل عملية (قبل الفعلية بتنفيذ التعليمات البرمجية) جميع المعرفات أعلن مع var سيتم تهيئة مع undefined, و تلك المستخدمة من قبل FunctionDeclaration's سوف تكون متاحة منذ تلك اللحظة ، على سبيل المثال:

 alert(typeof foo); // 'function', it's already available
 alert(typeof bar); // 'undefined'
 function foo () {}
 var bar = function () {};
 alert(typeof bar); // 'function'

تعيين bar FunctionExpression يقام حتى وقت التشغيل.

العقارية العالمية التي تم إنشاؤها من قبل FunctionDeclaration يمكن أن تكون الكتابة من دون أي مشاكل مثل قيمة المتغير, مثل:

 function test () {}
 test = null;

آخر فرق واضح بين مثالين على ذلك هو أن أول وظيفة لا اسم له ، ولكن الثانية ، والتي يمكن أن تكون مفيدة حقا عند التصحيح (أيتفتيش استدعاء المكدس).

عن تحرير المثال الأول (foo = function() { alert('hello!'); };) ، فمن غير معلنة المهمة ، وأود أن أشجعكم جدا دائما استخدام var الكلمات الرئيسية.

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

أيضا, تعيينات غير معلنة رمي ReferenceError على ECMAScript 5 تحت وضع الصارم.

يجب أن تقرأ:

ملاحظة:هذا الجواب قد تم دمجها من سؤال آخر, في الشك و سوء فهم من المرجع أن معرفات أعلن مع FunctionDeclaration, لا يمكن أن تكون الكتابة وهو ليس كذلك.

اثنين من مقتطفات الشفرة كنت قد نشرت وستكون هناك تقريبا لجميع الأغراض ، تتصرف بنفس الطريقة.

ومع ذلك ، فإن الفرق في السلوك هو أنه مع الخيار الأول (var functionOne = function() {}) أن وظيفة لا يمكن إلا أن يسمى بعد ذلك نقطة في المدونة.

مع الخيار الثاني (function functionTwo()), وظيفة متوفرة التعليمات البرمجية التي يتم تشغيلها أعلاه حيث الوظيفة المعلنة.

هذا هو لأنه مع الخيار الأول ، وظيفة تعيين متغير foo في وقت التشغيل.في الثاني ، وظيفة تسند إلى هذا المعرف ، foo, في تحليل الوقت.

المزيد من المعلومات التقنية

جافا سكريبت ثلاثة طرق تحديد الوظائف.

  1. أول مقتطف يظهر وظيفة التعبير.هذا ينطوي على استخدام "وظيفة" مشغل لإنشاء دالة - نتيجة أن المشغل يمكن تخزينها في أي متغير أو كائن الملكية.وظيفة التعبير قوية بهذه الطريقة.وظيفة التعبير غالبا ما يسمى "وظيفة مجهول" ، لأنه لا يجب أن يكون له اسم ،
  2. الثاني المثال هو إعلان وظيفة.يستخدم هذا "وظيفة" البيان لإنشاء وظيفة.وظيفة متاحة في تحليل الوقت يمكن أن يسمى أي مكان في هذا النطاق.لا يزال يمكنك تخزينه في متغير أو كائن الملكية في وقت لاحق.
  3. الطريقة الثالثة تحديد وظيفة هو "وظيفة()" منشئ, الذي لا يظهر في آخر الأصلي.ليس من المستحسن استخدام هذا كما أنه يعمل بنفس الطريقة eval(), التي لها مشاكل.

أفضل شرح جريج الإجابة

functionTwo();
function functionTwo() {
}

لماذا لا الخطأ ؟ كنا دائما أن تعبيرات يتم تنفيذها من أعلى إلى أسفل(??)

لأن:

وظيفة الإعلانات و الإعلانات المتغيرة دائما انتقلت (hoisted) بخفاء إلى أعلى تحتوي على النطاق من قبل مترجم جافا سكريبت.وظيفة معلمات اللغة-الأسماء المعرفة من الواضح بالفعل هناك. بن الكرز

وهذا يعني أن رمز مثل هذا:

functionOne();                  ---------------      var functionOne;
                                | is actually |      functionOne();
var functionOne = function(){   | interpreted |-->
};                              |    like     |      functionOne = function(){
                                ---------------      };

لاحظ أن التنازل عن جزء من الإعلانات لا رفع.فقط الاسم هو رفع.

ولكن في حالة مع وظيفة الإعلانات كامل الجسم وظيفة سيتم رفع كذلك:

functionTwo();              ---------------      function functionTwo() {
                            | is actually |      };
function functionTwo() {    | interpreted |-->
}                           |    like     |      functionTwo();
                            ---------------

البعض من المعلقين قد غطت بالفعل الدلالي الفرق من الخيارين أعلاه.أردت أن أشير إلى الأسلوبية الفرق:إلا أن "الإحالة" الاختلاف يمكن تعيين خاصية كائن آخر.

أنا في كثير من الأحيان بناء وحدات جافا سكريبت مع نمط من هذا القبيل:

(function(){
    var exports = {};

    function privateUtil() {
            ...
    }

    exports.publicUtil = function() {
            ...
    };

    return exports;
})();

مع هذا النمط ، الوظائف العامة سوف نستخدم كل مهمة ، في حين الخاص بك استخدام وظائف الإعلان.

(لاحظ أيضا أن التنازل يجب أن تتطلب منقوطة بعد البيان ، في حين أن الإعلان يحظر ذلك.)

مثال عندما تفضل الأسلوب الأول أن الثاني هو عندما تحتاج إلى تجنب تجاوز الدالة التعاريف السابقة.

مع

if (condition){
    function myfunction(){
        // Some code
    }
}

, هذا تعريف myfunction ستتجاوز أي التعريف السابق ، حيث سيتم القيام به في تحليل الوقت.

في حين

if (condition){
    var myfunction = function (){
        // Some code
    }
}

هل الصحيح وظيفة تحديد myfunction فقط عندما condition والتقى.

وهو سبب مهم هو أن إضافة واحد فقط متغير باسم "جذور" من مساحة الاسم الخاصة بك...

var MyNamespace = {}
MyNamespace.foo= function() {

}

أو

var MyNamespace = {
  foo: function() {
  },
  ...
}

هناك العديد من التقنيات namespacing.إنها تصبح أكثر أهمية مع عدد كبير من جافا سكريبت الوحدات المتاحة.

انظر أيضا كيف أعلن مساحة في جافا سكريبت ؟

الرفع هو مترجم جافا سكريبت عمل من نقل جميع متغير وظيفة الإعلانات إلى الأعلى من النطاق الحالي.

ومع ذلك, فقط الفعلية الإعلانات رفع.من خلال ترك الواجبات أين هم.

  • المتغير/وظيفة المعلن داخل صفحة عالمية يمكن الوصول إلى أي مكان في هذه الصفحة.
  • المتغير/الوظائف المعلنة داخل الدالة تواجه النطاق المحلي.يعني أنها متاحة/الوصول إلى داخل الجسم وظيفة (نطاق) ، فهي ليست متاحة خارج وظيفة الجسم.

متغير

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

global_Page = 10;                                               var global_Page;      « undefined
    « Integer literal, Number Type.   -------------------       global_Page = 10;     « Number         
global_Page = 'Yash';                 |   Interpreted   |       global_Page = 'Yash'; « String
    « String literal, String Type.    «       AS        «       global_Page = true;   « Boolean 
var global_Page = true;               |                 |       global_Page = function (){          « function
    « Boolean Type                    -------------------                 var local_functionblock;  « undefined
global_Page = function (){                                                local_functionblock = 777;« Number
    var local_functionblock = 777;                              };  
    // Assigning function as a data.
};  

وظيفة

function Identifier_opt ( FormalParameterList_opt ) { 
      FunctionBody | sequence of statements

      « return;  Default undefined
      « return 'some data';
}
  • وظائف معلنة داخل الصفحة هي رفع إلى أعلى الصفحة بعد الوصول العالمي.
  • وظائف معلنة داخل الدالة-كتلة رفع إلى أعلى كتلة.
  • الافتراضي القيمة المرجعة من الدالة 'غير معرف', متغير إعلان القيمة الافتراضية أيضا 'undefined'

    Scope with respect to function-block global. 
    Scope with respect to page undefined | not available.
    

إعلان وظيفة

function globalAccess() {                                  function globalAccess() {      
}                                  -------------------     }
globalAccess();                    |                 |     function globalAccess() { « Re-Defined / overridden.
localAccess();                     «   Hoisted  As   «         function localAccess() {
function globalAccess() {          |                 |         }
     localAccess();                -------------------         localAccess(); « function accessed with in globalAccess() only.
     function localAccess() {                              }
     }                                                     globalAccess();
}                                                          localAccess(); « ReferenceError as the function is not defined

وظيفة التعبير

        10;                 « literal
       (10);                « Expression                (10).toString() -> '10'
var a;                      
    a = 10;                 « Expression var              a.toString()  -> '10'
(function invoke() {        « Expression Function
 console.log('Self Invoking');                      (function () {
});                                                               }) () -> 'Self Invoking'

var f; 
    f = function (){        « Expression var Function
    console.log('var Function');                                   f ()  -> 'var Function'
    };

وظيفة تعيين متغير سبيل المثال:

(function selfExecuting(){
    console.log('IIFE - Immediately-Invoked Function Expression');
}());

var anonymous = function (){
    console.log('anonymous function Expression');
};

var namedExpression = function for_InternalUSE(fact){
    if(fact === 1){
        return 1;
    }

    var localExpression = function(){
        console.log('Local to the parent Function Scope');
    };
    globalExpression = function(){ 
        console.log('creates a new global variable, then assigned this function.');
    };

    //return; //undefined.
    return fact * for_InternalUSE( fact - 1);   
};

namedExpression();
globalExpression();

سكريبت تفسير

var anonymous;
var namedExpression;
var globalExpression;

anonymous = function (){
    console.log('anonymous function Expression');
};

namedExpression = function for_InternalUSE(fact){
    var localExpression;

    if(fact === 1){
        return 1;
    }
    localExpression = function(){
        console.log('Local to the parent Function Scope');
    };
    globalExpression = function(){ 
        console.log('creates a new global variable, then assigned this function.');
    };

    return fact * for_InternalUSE( fact - 1);    // DEFAULT UNDEFINED.
};

namedExpression(10);
globalExpression();

يمكنك التحقق من وظيفة الإعلان التعبير اختبار أكثر من متصفح تستخدم jsperf Test Runner


ES5 منشئ وظيفة الطبقات:وظيفة الكائنات التي تم إنشاؤها باستخدام وظيفة.النموذج الأولي.ربط

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

function Shape(id) { // Function Declaration
    this.id = id;
};
    // Adding a prototyped method to a function.
    Shape.prototype.getID = function () {
        return this.id;
    };
    Shape.prototype.setID = function ( id ) {
        this.id = id;
    };

var expFn = Shape; // Function Expression

var funObj = new Shape( ); // Function Object
funObj.hasOwnProperty('prototype'); // false
funObj.setID( 10 );
console.log( funObj.getID() ); // 10

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

ArrowFunction : ArrowParameters => ConciseBody.

const fn = (item) => { return item & 1 ? 'Odd' : 'Even'; };
console.log( fn(2) ); // Even
console.log( fn(3) ); // Odd

انا إضافة بلدي الإجابة فقط لأن الجميع قد غطت رفع الجزء جيدا.

لقد تساءلت عن الطريقة التي هي أفضل لفترة طويلة الآن, و شكرا http://jsperf.com الآن وأنا أعلم :)

enter image description here

وظيفة الإعلانات أسرع, و هذا هو ما يهم حقا في ويب ديف صحيح ؟ ;)

إعلان وظيفة وظيفة التعبير تعيين إلى متغير تتصرف بنفس بمجرد الربط هو المنشأة.

هناك فرق إلا في كيف و عندما وظيفة الكائن هو في الواقع المرتبطة متغير.هذا الاختلاف يرجع إلى آلية تسمى متغير الرفع في جافا سكريبت.

أساسا كل وظيفة الإعلانات و الإعلانات المتغيرة هي رفع إلى أعلى وظيفة في الإعلان يحدث (وهذا هو السبب في أننا نقول أن جافا سكريبت لديه وظيفة نطاق).

  • عند إعلان وظيفة هو رفع, وظيفة الجسم "يتبع" حتى عندما وظيفة الجسم يتم تقييم متغير على الفور تكون ملزمة وظيفة الكائن.

  • عند تعريف متغير هو رفع, التهيئة لا لا متابعة, ولكن "خلفها".المتغير هو تهيئة undefined في بداية وظائف الجسم, و سوف يكون تعيين قيمة في موقعه الأصلي في القانون.(في الواقع ، فإنه سيتم تعيين القيمة في كل موقع إعلان متغير مع نفس اسم يحدث.)

ترتيب الرفع المهم أيضا:وظيفة الإعلانات تأخذ الأسبقية على تعريفات المتغير مع نفس الاسم ، وآخر وظيفة الإعلان الأسبقية السابقة وظيفة الإعلانات مع نفس الاسم.

بعض الأمثلة...

var foo = 1;
function bar() {
  if (!foo) {
    var foo = 10 }
  return foo; }
bar() // 10

متغير foo هو رفع إلى أعلى وظيفة ، تهيئة undefined, بحيث !foo هو true, لذا foo يتم تعيين 10.على foo خارج bar's نطاق يلعب أي دور و هو لم يمسها.

function f() {
  return a; 
  function a() {return 1}; 
  var a = 4;
  function a() {return 2}}
f()() // 2

function f() {
  return a;
  var a = 4;
  function a() {return 1};
  function a() {return 2}}
f()() // 2

وظيفة الإعلانات تأخذ الأسبقية على تعريفات المتغير ، وآخر وظيفة الإعلان "العصي".

function f() {
  var a = 4;
  function a() {return 1}; 
  function a() {return 2}; 
  return a; }
f() // 4

في هذا المثال a يتم تهيئة مع وظيفة الكائن الناتجة عن تقييم الوظيفة الثانية الإعلان ، ثم تم تعيينه 4.

var a = 1;
function b() {
  a = 10;
  return;
  function a() {}}
b();
a // 1

هنا تعريف الدالة هو يرفع أولا ، معلنا و تهيئة متغير a.التالي, يتم تعيين هذا المتغير 10.وبعبارة أخرى:المهمة لا تعيين الخارجي المتغير a.

المثال الأول هو إعلان وظيفة:

function abc(){}

المثال الثاني هو وظيفة التعبير:

var abc = function() {};

والفرق الرئيسي هو كيف يتم رفع (رفع وأعلنت).في المثال الأول ، كل وظيفة الإعلان هو رفع.في المثال الثاني فقط فار 'abc' هو رفع قيمتها (وظيفة) سوف يكون غير معروف ، وظيفة نفسها لا تزال في الموقف الذي أعلن عنه.

ببساطة:

//this will work
abc(param);
function abc(){}

//this would fail
abc(param);
var abc = function() {}

لدراسة المزيد عن هذا الموضوع أنا نوصي بشدة لك هذا الرابط

حيث رمز تكلفة الصيانة ، واسمه وظائف أكثر من الأفضل:

  • مستقلة عن المكان الذي هم أعلن (ولكن لا تزال محدودة النطاق).
  • أكثر مقاومة الأخطاء مثل المشروط التهيئة (كنت لا تزال قادرة على تجاوز إذا أردت).
  • رمز يصبح أكثر قابلية للقراءة من خلال تخصيص الوظائف المحلية بشكل منفصل من نطاق الوظيفة.عادة في نطاق وظائف يذهب الأولى ، تليها إعلانات الوظائف المحلية.
  • في مصحح أخطاء سوف نرى بوضوح اسم الدالة على مكدس الاستدعاءات بدلا من "مجهول/تقييم" وظيفة.

وأظن أكثر من الايجابيات المسماة وظائف متابعة.و ما ورد ميزة اسمه الوظائف هو العيب المجهول منها.

تاريخيا, وظائف مجهولة ظهر من عجز جافا سكريبت كلغة إلى قائمة أعضاء مسمى الوظائف:

{
    member:function() { /* How do I make "this.member" a named function? */
    }
}

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

لدي البرمجية التي لا تحتاج إلى تشغيل مع 160 مستقل-تصميم brandings.معظم التعليمات البرمجية في الملفات المشتركة ، ولكن العلامة التجارية الخاصة الأشياء في ملف منفصل لكل العلامات التجارية.

بعض brandings تتطلب مهام محددة, و البعض لا.أحيانا لا بد لي من إضافة وظائف جديدة إلى فعل العلامة التجارية الجديدة-أشياء محددة.أنا سعيد أن تغيير المشتركة مشفرة لكن لا تريد أن تضطر إلى تغيير جميع 160 مجموعات من العلامات التجارية الملفات.

باستخدام متغير جملة, يمكن أن تقوم بتعريف المتغير (مؤشر دالة أساسا) في رمز مشترك و إما تعيين تافهة كعب وظيفة ، أو تعيين إلى null.

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

من الناس في التعليقات أعلاه ، أظن أنه قد يكون من الممكن إعادة تعريف دالة ثابتة جدا, ولكن أعتقد المتغير الحل هو جميل و واضح.

في علوم الكمبيوتر حيث كنا نتحدث عن مجهول وظائف اسمه الوظائف.أعتقد أن الفرق الأكثر أهمية هو أن وظيفة مجهول لا بد أن اسم, ومن هنا جاء اسم وظيفة مجهول.في جافا سكريبت هو من الدرجة الأولى كائن حيوي أعلن في وقت التشغيل.

لمزيد من المعلومات حول وظائف مجهولة و امدا حساب التفاضل والتكامل, ويكيبيديا هو بداية جيدة (http://en.wikipedia.org/wiki/Anonymous_function).

جريج الإجابة هي جيدة بما فيه الكفاية, ولكن أنا لا تزال ترغب في إضافة شيء ما إلى ذلك علمت الآن فقط مشاهدة دوغلاس Crockford هو أشرطة الفيديو.

وظيفة التعبير:

var foo = function foo() {};

وظيفة البيان:

function foo() {};

وظيفة البيان هو مجرد اختصار var البيان مع function القيمة.

لذلك

function foo() {};

توسع

var foo = function foo() {};

والذي يوسع كذلك إلى:

var foo = undefined;
foo = function foo() {};

وكلاهما رفع الجزء العلوي من التعليمات البرمجية.

Screenshot from video

@EugeneLazutkin يعطي مثالا على ذلك حيث انه أسماء تعيين وظيفة أن يكون قادرا على استخدام shortcut() داخلية إشارة إلى نفسه. John Resig يعطي مثال آخر - نسخ متكررة الوظيفة المسندة إلى كائن آخر في تعلم جافا سكريبت المتقدم البرنامج التعليمي.في حين إسناد المهام إلى خصائص ليست بدقة السؤال هنا أوصي تحاول البرنامج التعليمي من - تشغيل التعليمات البرمجية من خلال النقر على زر في الزاوية اليمنى العليا ، وانقر نقرا مزدوجا فوق رمز لتحرير ترضيك.

أمثلة من البرنامج التعليمي:دعوات متكررة في yell():

اختبارات تفشل عندما الأصلي النينجا يتم إزالة الكائن. (الصفحة 13)

var ninja = { 
  yell: function(n){ 
    return n > 0 ? ninja.yell(n-1) + "a" : "hiy"; 
  } 
}; 
assert( ninja.yell(4) == "hiyaaaa", "A single object isn't too bad, either." ); 

var samurai = { yell: ninja.yell }; 
var ninja = null; 

try { 
  samurai.yell(4); 
} catch(e){ 
  assert( false, "Uh, this isn't good! Where'd ninja.yell go?" ); 
}

إذا كنت اسم الدالة التي سيتم استدعاء متكرر, الاختبارات سوف تمر. (صفحة 14)

var ninja = { 
  yell: function yell(n){ 
    return n > 0 ? yell(n-1) + "a" : "hiy"; 
  } 
}; 
assert( ninja.yell(4) == "hiyaaaa", "Works as we would expect it to!" ); 

var samurai = { yell: ninja.yell }; 
var ninja = {}; 
assert( samurai.yell(4) == "hiyaaaa", "The method correctly calls itself." );

آخر الفرق التي لم يرد ذكرها في إجابات أخرى هو أنه إذا كنت تستخدم وظيفة مجهول

var functionOne = function() {
    // Some code
};

واستخدام ذلك منشئ كما في

var one = new functionOne();

ثم one.constructor.name لن تكون محددة. Function.name هو غير القياسية ولكن يدعمه فايرفوكس, الكروم وغيرها بكت المستمدة من متصفحات IE 9+.

مع

function functionTwo() {
    // Some code
}
two = new functionTwo();

فمن الممكن لاسترداد اسم منشئ كسلسلة مع two.constructor.name.

إذا كنت تستخدم هذه الوظائف لخلق الكائنات ، سوف تحصل على:

var objectOne = new functionOne();
console.log(objectOne.__proto__); // prints "Object {}" because constructor is an anonymous function

var objectTwo = new functionTwo();
console.log(objectTwo.__proto__); // prints "functionTwo {}" because constructor is a named function

أول واحد (وظيفة doSomething(x)) يجب أن تكون جزءا من كائن التدوين.

ثانية واحدة (var doSomething = function(x){ alert(x);}) هو ببساطة إنشاء وظيفة مجهول و تعيين متغير ، doSomething.حتى doSomething() استدعاء الدالة.

قد ترغب في معرفة ما إعلان وظيفة و وظيفة التعبير هو.

إعلان وظيفة يحدد وظيفة اسمه متغير دون اشتراط تعيين متغير.وظيفة الإعلانات تحدث مستقل يبني و لا يمكن أن تكون متداخلة في غير وظيفة كتل.

function foo() {
    return 3;
}

ECMA 5 (13.0) يحدد بناء الجملة كما
وظيفة معرف ( FormalParameterListتختار ) { FunctionBody }

في الشرط المذكور أعلاه اسم الدالة مرئيا داخل نطاق نطاق الأم (وإلا فإنه لن يكون متاحا).

و في وظيفة التعبير

وظيفة التعبير يحدد وظيفة كجزء من أكبر التعبير اللغوي (عادة تعيين متغير ).وظائف محددة من خلال وظائف التعبيرات يمكن تسمية أو مجهول.وظيفة التعبير لا ينبغي أن تبدأ مع "وظيفة".

// Anonymous function expression
var a = function() {
    return 3;
}

// Named function expression
var a = function foo() {
    return 3;
}

// Self-invoking function expression
(function foo() {
    alert("hello!");
})();

ECMA 5 (13.0) يحدد بناء الجملة كما
وظيفة معرفتختار ( FormalParameterListتختار ) { FunctionBody }

أنا سرد الاختلافات أدناه:

  1. إعلان وظيفة يمكن وضعها في أي مكان في التعليمات البرمجية.حتى لو كان الاحتجاج قبل التعريف يظهر في المدونة ، يعدم وظيفة الإعلان ملتزمة الذاكرة أو في الطريقة التي يتم رفعها ، قبل أي رمز آخر في الصفحة يبدأ التنفيذ.

    نلقي نظرة على وظيفة أدناه:

    function outerFunction() {
        function foo() {
           return 1;
        }
        return foo();
        function foo() {
           return 2;
        }
    }
    alert(outerFunction()); // Displays 2
    

    هذا هو لأنه ، أثناء التنفيذ ، يبدو مثل:-

    function foo() {  // The first function declaration is moved to top
        return 1;
    }
    function foo() {  // The second function declaration is moved to top
        return 2;
    }
    function outerFunction() {
        return foo();
    }
    alert(outerFunction()); //So executing from top to bottom,
                            //the last foo() returns 2 which gets displayed
    

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

    بنفس وظيفة الدالة تستخدم التعبيرات:

    function outerFunction() {
        var foo = function() {
           return 1;
        }
        return foo();
        var foo = function() {
           return 2;
        }
    }
    alert(outerFunction()); // Displays 1
    

    وذلك لأن أثناء التنفيذ ، يبدو مثل:

    function outerFunction() {
       var foo = undefined;
       var foo = undefined;
    
       foo = function() {
          return 1;
       };
       return foo ();
       foo = function() {   // This function expression is not reachable
          return 2;
       };
    }
    alert(outerFunction()); // Displays 1
    
  2. أنها ليست آمنة لكتابة وظيفة الإعلانات في غير وظيفة كتل مثل إذا لأنها لن تكون متاحة.

    if (test) {
        function x() { doSomething(); }
    }
    
  3. اسمه وظيفة التعبير مثل واحد أدناه ، قد لا تعمل في المتصفحات Internet Explorer قبل إلى الإصدار 9.

    var today = function today() {return new Date()}
    

في ضوء "يدعى وظائف تظهر في تتبعات المكدس" الحجة, الحديث جافا سكريبت محركات هي في الواقع قادرة على تمثيل وظائف مجهولة.

حتى كتابة هذه السطور, V8, وspidermonkey, شقرا و نيترو دائما الرجوع إلى المسمى وظائف بأسمائهم.هم دائما تقريبا الرجوع إلى وظيفة مجهول من قبل معرف إذا كان لديه واحد.

وspidermonkey يمكن معرفة اسم وظيفة مجهول عاد من وظيفة أخرى.والباقي لا.

إذا كنت حقا تريد التكرار والنجاح رد لتظهر في تتبع, يمكنك أن اسم هذه أيضا...

[].forEach(function iterator() {});

ولكن بالنسبة للجزء الأكبر أنه لا يستحق مؤكدا على.

تسخير (كمان)

'use strict';

var a = function () {
    throw new Error();
},
    b = function b() {
        throw new Error();
    },
    c = function d() {
        throw new Error();
    },
    e = {
        f: a,
        g: b,
        h: c,
        i: function () {
            throw new Error();
        },
        j: function j() {
            throw new Error();
        },
        k: function l() {
            throw new Error();
        }
    },
    m = (function () {
        return function () {
            throw new Error();
        };
    }()),
    n = (function () {
        return function n() {
            throw new Error();
        };
    }()),
    o = (function () {
        return function p() {
            throw new Error();
        };
    }());

console.log([a, b, c].concat(Object.keys(e).reduce(function (values, key) {
    return values.concat(e[key]);
}, [])).concat([m, n, o]).reduce(function (logs, func) {

    try {
        func();
    } catch (error) {
        return logs.concat('func.name: ' + func.name + '\n' +
                           'Trace:\n' +
                           error.stack);
        // Need to manually log the error object in Nitro.
    }

}, []).join('\n\n'));

V8

func.name: 
Trace:
Error
    at a (http://localhost:8000/test.js:4:11)
    at http://localhost:8000/test.js:47:9
    at Array.reduce (native)
    at http://localhost:8000/test.js:44:27

func.name: b
Trace:
Error
    at b (http://localhost:8000/test.js:7:15)
    at http://localhost:8000/test.js:47:9
    at Array.reduce (native)
    at http://localhost:8000/test.js:44:27

func.name: d
Trace:
Error
    at d (http://localhost:8000/test.js:10:15)
    at http://localhost:8000/test.js:47:9
    at Array.reduce (native)
    at http://localhost:8000/test.js:44:27

func.name: 
Trace:
Error
    at a (http://localhost:8000/test.js:4:11)
    at http://localhost:8000/test.js:47:9
    at Array.reduce (native)
    at http://localhost:8000/test.js:44:27

func.name: b
Trace:
Error
    at b (http://localhost:8000/test.js:7:15)
    at http://localhost:8000/test.js:47:9
    at Array.reduce (native)
    at http://localhost:8000/test.js:44:27

func.name: d
Trace:
Error
    at d (http://localhost:8000/test.js:10:15)
    at http://localhost:8000/test.js:47:9
    at Array.reduce (native)
    at http://localhost:8000/test.js:44:27

func.name: 
Trace:
Error
    at e.i (http://localhost:8000/test.js:17:19)
    at http://localhost:8000/test.js:47:9
    at Array.reduce (native)
    at http://localhost:8000/test.js:44:27

func.name: j
Trace:
Error
    at j (http://localhost:8000/test.js:20:19)
    at http://localhost:8000/test.js:47:9
    at Array.reduce (native)
    at http://localhost:8000/test.js:44:27

func.name: l
Trace:
Error
    at l (http://localhost:8000/test.js:23:19)
    at http://localhost:8000/test.js:47:9
    at Array.reduce (native)
    at http://localhost:8000/test.js:44:27

func.name: 
Trace:
Error
    at http://localhost:8000/test.js:28:19
    at http://localhost:8000/test.js:47:9
    at Array.reduce (native)
    at http://localhost:8000/test.js:44:27

func.name: n
Trace:
Error
    at n (http://localhost:8000/test.js:33:19)
    at http://localhost:8000/test.js:47:9
    at Array.reduce (native)
    at http://localhost:8000/test.js:44:27

func.name: p
Trace:
Error
    at p (http://localhost:8000/test.js:38:19)
    at http://localhost:8000/test.js:47:9
    at Array.reduce (native)
    at http://localhost:8000/test.js:44:27 test.js:42

وspidermonkey

func.name: 
Trace:
a@http://localhost:8000/test.js:4:5
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1


func.name: b
Trace:
b@http://localhost:8000/test.js:7:9
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1


func.name: d
Trace:
d@http://localhost:8000/test.js:10:9
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1


func.name: 
Trace:
a@http://localhost:8000/test.js:4:5
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1


func.name: b
Trace:
b@http://localhost:8000/test.js:7:9
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1


func.name: d
Trace:
d@http://localhost:8000/test.js:10:9
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1


func.name: 
Trace:
e.i@http://localhost:8000/test.js:17:13
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1


func.name: j
Trace:
j@http://localhost:8000/test.js:20:13
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1


func.name: l
Trace:
l@http://localhost:8000/test.js:23:13
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1


func.name: 
Trace:
m</<@http://localhost:8000/test.js:28:13
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1


func.name: n
Trace:
n@http://localhost:8000/test.js:33:13
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1


func.name: p
Trace:
p@http://localhost:8000/test.js:38:13
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1

شقرا

func.name: undefined
Trace:
Error
   at a (http://localhost:8000/test.js:4:5)
   at Anonymous function (http://localhost:8000/test.js:47:9)
   at Global code (http://localhost:8000/test.js:42:1)


func.name: undefined
Trace:
Error
   at b (http://localhost:8000/test.js:7:9)
   at Anonymous function (http://localhost:8000/test.js:47:9)
   at Global code (http://localhost:8000/test.js:42:1)


func.name: undefined
Trace:
Error
   at d (http://localhost:8000/test.js:10:9)
   at Anonymous function (http://localhost:8000/test.js:47:9)
   at Global code (http://localhost:8000/test.js:42:1)


func.name: undefined
Trace:
Error
   at a (http://localhost:8000/test.js:4:5)
   at Anonymous function (http://localhost:8000/test.js:47:9)
   at Global code (http://localhost:8000/test.js:42:1)


func.name: undefined
Trace:
Error
   at b (http://localhost:8000/test.js:7:9)
   at Anonymous function (http://localhost:8000/test.js:47:9)
   at Global code (http://localhost:8000/test.js:42:1)


func.name: undefined
Trace:
Error
   at d (http://localhost:8000/test.js:10:9)
   at Anonymous function (http://localhost:8000/test.js:47:9)
   at Global code (http://localhost:8000/test.js:42:1)


func.name: undefined
Trace:
Error
   at e.i (http://localhost:8000/test.js:17:13)
   at Anonymous function (http://localhost:8000/test.js:47:9)
   at Global code (http://localhost:8000/test.js:42:1)


func.name: undefined
Trace:
Error
   at j (http://localhost:8000/test.js:20:13)
   at Anonymous function (http://localhost:8000/test.js:47:9)
   at Global code (http://localhost:8000/test.js:42:1)


func.name: undefined
Trace:
Error
   at l (http://localhost:8000/test.js:23:13)
   at Anonymous function (http://localhost:8000/test.js:47:9)
   at Global code (http://localhost:8000/test.js:42:1)


func.name: undefined
Trace:
Error
   at Anonymous function (http://localhost:8000/test.js:28:13)
   at Anonymous function (http://localhost:8000/test.js:47:9)
   at Global code (http://localhost:8000/test.js:42:1)


func.name: undefined
Trace:
Error
   at n (http://localhost:8000/test.js:33:13)
   at Anonymous function (http://localhost:8000/test.js:47:9)
   at Global code (http://localhost:8000/test.js:42:1)


func.name: undefined
Trace:
Error
   at p (http://localhost:8000/test.js:38:13)
   at Anonymous function (http://localhost:8000/test.js:47:9)
   at Global code (http://localhost:8000/test.js:42:1)

نيترو

func.name: 
Trace:
a@http://localhost:8000/test.js:4:22
http://localhost:8000/test.js:47:13
reduce@[native code]
global code@http://localhost:8000/test.js:44:33

func.name: b
Trace:
b@http://localhost:8000/test.js:7:26
http://localhost:8000/test.js:47:13
reduce@[native code]
global code@http://localhost:8000/test.js:44:33

func.name: d
Trace:
d@http://localhost:8000/test.js:10:26
http://localhost:8000/test.js:47:13
reduce@[native code]
global code@http://localhost:8000/test.js:44:33

func.name: 
Trace:
a@http://localhost:8000/test.js:4:22
http://localhost:8000/test.js:47:13
reduce@[native code]
global code@http://localhost:8000/test.js:44:33

func.name: b
Trace:
b@http://localhost:8000/test.js:7:26
http://localhost:8000/test.js:47:13
reduce@[native code]
global code@http://localhost:8000/test.js:44:33

func.name: d
Trace:
d@http://localhost:8000/test.js:10:26
http://localhost:8000/test.js:47:13
reduce@[native code]
global code@http://localhost:8000/test.js:44:33

func.name: 
Trace:
i@http://localhost:8000/test.js:17:30
http://localhost:8000/test.js:47:13
reduce@[native code]
global code@http://localhost:8000/test.js:44:33

func.name: j
Trace:
j@http://localhost:8000/test.js:20:30
http://localhost:8000/test.js:47:13
reduce@[native code]
global code@http://localhost:8000/test.js:44:33

func.name: l
Trace:
l@http://localhost:8000/test.js:23:30
http://localhost:8000/test.js:47:13
reduce@[native code]
global code@http://localhost:8000/test.js:44:33

func.name: 
Trace:
http://localhost:8000/test.js:28:30
http://localhost:8000/test.js:47:13
reduce@[native code]
global code@http://localhost:8000/test.js:44:33

func.name: n
Trace:
n@http://localhost:8000/test.js:33:30
http://localhost:8000/test.js:47:13
reduce@[native code]
global code@http://localhost:8000/test.js:44:33

func.name: p
Trace:
p@http://localhost:8000/test.js:38:30
http://localhost:8000/test.js:47:13
reduce@[native code]
global code@http://localhost:8000/test.js:44:33

𝗧𝗵𝗲𝗿𝗲 𝗮𝗿𝗲 𝗳𝗼𝘂𝗿 𝗻𝗼𝘁𝗲𝘄𝗼𝗿𝘁𝗵𝘆 𝗰𝗼𝗺𝗽𝗮𝗿𝗶𝘀𝗼𝗻𝘀 𝗯𝗲𝘁𝘄𝗲𝗲𝗻 𝘁𝗵𝗲 𝘁𝘄𝗼 𝗱𝗶𝗳𝗳𝗲𝗿𝗲𝗻𝘁 𝗱𝗲𝗰𝗹𝗮𝗿𝗮𝘁𝗶𝗼𝗻𝘀 𝗼𝗳 𝗳𝘂𝗻𝗰𝘁𝗶𝗼𝗻𝘀 𝗮𝘀 𝗹𝗶𝘀𝘁𝗲𝗱 𝗯𝗲𝗹𝗼𝘄.

  1. توافر (نطاق) وظيفة

الأعمال التالية لأن function add() وراقب إلى أقرب كتلة:

try {
  console.log("Success: ", add(1, 1));
} catch(e) {
  console.log("ERROR: " + e);
}

function add(a, b){
  return a + b;
}

التالية لا يعمل (لأن var add= superseeds على function add()).

try {
  console.log("Success: ", add(1, 1));
} catch(e) {
  console.log("ERROR: " + e);
}

var add=function add(a, b){
  return a + b;
}

التالية لا تعمل بسبب add وأعلن بعد استخدامها.

try {
  console.log("Success: ", add(1, 1));
} catch(e) {
  console.log("ERROR: " + e);
}

var add=function(a, b){
  return a + b;
}

  1. (وظيفة).اسم

اسم الوظيفة function thefuncname(){} هو thefuncname عندما أعلن هذا الطريق.

function foobar(a, b){}

console.log(foobar.name);

var a = function foobar(){};

console.log(a.name);

وإلا إذا كانت الوظيفة المعلنة function(){}, ، وظيفة.اسم المتغير الأول يستخدم لتخزين وظيفة.

var a = function(){};
var b = (function(){ return function(){} });

console.log(a.name);
console.log(b.name);

إذا كان هناك أي متغيرات تعيين وظيفة ، ثم وظائف اسم سلسلة فارغة ("").

console.log((function(){}).name === "");

وأخيرا ، في حين أن متغير الوظيفة المخصصة في البداية بتعيين اسم المتعاقبة المتغيرات تعيين وظيفة لا تغيير الاسم.

var a = function(){};
var b = a;
var c = b;

console.log(a.name);
console.log(b.name);
console.log(c.name);

  1. الأداء

في جوجل V8 و فايرفوكس وspidermonkey قد يكون هناك عدد قليل من ميكروثانية JIST تجميع الفرق ، ولكن في النهاية النتيجة هي بالضبط نفس.لإثبات هذا, دعونا دراسة كفاءة JSPerf في microbenchmarks بمقارنة سرعة اثنين فارغة التعليمات البرمجية المتكررة.على JSPerf الاختبارات وجدت هنا.و ، jsben.ch testsare العثور عليها هنا.كما ترون, هناك ملحوظة فرق عندما يكون هناك شيء.إذا كنت حقا أداء غريب مثلي ، ثم أنه قد يكون من المفيد في حين الخاص بك في محاولة للحد من عدد من المتغيرات والوظائف في نطاق وخاصة القضاء على تعدد الأشكال (مثل استخدام نفس متغير لتخزين اثنين من أنواع مختلفة).

  1. متغير التحولية

عند استخدام var الكلمة لتعريف متغير, ثم يمكنك إعادة تعيين القيمة إلى متغير مثل ذلك.

(function(){
    "use strict";
    var foobar = function(){}; // initial value
    try {
        foobar = "Hello World!"; // new value
        console.log("[no error]");
    } catch(error) {
        console.log("ERROR: " + error.message);
    }
    console.log(foobar, window.foobar);
})();

ومع ذلك ، عندما نستخدم const-البيان ، مرجع متغير يصبح غير قابل للتغيير.هذا يعني أننا لا يمكن تخصيص قيمة للمتغير.يرجى ملاحظة أن هذا لا يجعل محتويات المتغير الثابت:إذا كنت تفعل const arr = [], ثم يمكنك لا تزال تفعل arr[10] = "example".فقط تفعل شيئا مثل arr = "new value" أو arr = [] رمي خطأ كما سنرى فيما بعد.

(function(){
    "use strict";
    const foobar = function(){}; // initial value
    try {
        foobar = "Hello World!"; // new value
        console.log("[no error]");
    } catch(error) {
        console.log("ERROR: " + error.message);
    }
    console.log(foobar, window.foobar);
})();

ومن المثير للاهتمام, إذا نعلن عن المتغير كما function funcName(){}, ثم ثبات المتغير هو نفسه معلنا أنه مع var.

(function(){
    "use strict";
    function foobar(){}; // initial value
    try {
        foobar = "Hello World!"; // new value
        console.log("[no error]");
    } catch(error) {
        console.log("ERROR: " + error.message);
    }
    console.log(foobar, window.foobar);
})();

𝗪𝗵𝗮𝘁 𝗜𝘀 𝗧𝗵𝗲 "𝗡𝗲𝗮𝗿𝗲𝘀𝘁 𝗕𝗹𝗼𝗰𝗸"

"أقرب كتلة" هو أقرب "وظيفة" (بما في ذلك غير متزامن وظائف, وظائف مولد و غير متزامن وظائف مولد).لكن المثير للاهتمام ، function functionName() {} يتصرف مثل var functionName = function() {} عندما تكون في غير إغلاق كتلة البنود خارج قال الإغلاق.نلاحظ.

  • عادي var add=function(){}

try {
  // typeof will simply return "undefined" if the variable does not exist
  if (typeof add !== "undefined") {
    add(1, 1); // just to prove it
    console.log("Not a block");
  }else if(add===undefined){ // this throws an exception if add doesn't exist
    console.log('Behaves like var add=function(a,b){return a+b}');
  }
} catch(e) {
  console.log("Is a block");
}
var add=function(a, b){return a + b}

  • عادي function add(){}

try {
  // typeof will simply return "undefined" if the variable does not exist
  if (typeof add !== "undefined") {
    add(1, 1); // just to prove it
    console.log("Not a block");
  }else if(add===undefined){ // this throws an exception if add doesn't exist
    console.log('Behaves like var add=function(a,b){return a+b}')
  }
} catch(e) {
  console.log("Is a block");
}
function add(a, b){
  return a + b;
}

  • وظيفة

try {
  // typeof will simply return "undefined" if the variable does not exist
  if (typeof add !== "undefined") {
    add(1, 1); // just to prove it
    console.log("Not a block");
  }else if(add===undefined){ // this throws an exception if add doesn't exist
    console.log('Behaves like var add=function(a,b){return a+b}')
  }
} catch(e) {
  console.log("Is a block");
}
(function () {
    function add(a, b){
      return a + b;
    }
})();

  • بيان (مثل if, else, for, while, try/catch/finally, switch, do/while, with)

try {
  // typeof will simply return "undefined" if the variable does not exist
  if (typeof add !== "undefined") {
    add(1, 1); // just to prove it
    console.log("Not a block");
  }else if(add===undefined){ // this throws an exception if add doesn't exist
    console.log('Behaves like var add=function(a,b){return a+b}')
  }
} catch(e) {
  console.log("Is a block");
}
{
    function add(a, b){
      return a + b;
    }
}

  • السهم وظيفة مع var add=function()

try {
  // typeof will simply return "undefined" if the variable does not exist
  if (typeof add !== "undefined") {
    add(1, 1); // just to prove it
    console.log("Not a block");
  }else if(add===undefined){ // this throws an exception if add doesn't exist
    console.log('Behaves like var add=function(a,b){return a+b}')
  }
} catch(e) {
  console.log("Is a block");
}
(() => {
    var add=function(a, b){
      return a + b;
    }
})();

  • السهم وظيفة مع function add()

try {
  // typeof will simply return "undefined" if the variable does not exist
  if (typeof add !== "undefined") {
    add(1, 1); // just to prove it
    console.log("Not a block");
  }else if(add===undefined){ // this throws an exception if add doesn't exist
    console.log('Behaves like var add=function(a,b){return a+b}')
  }
} catch(e) {
  console.log("Is a block");
}
(() => {
    function add(a, b){
      return a + b;
    }
})();

في جافا سكريبت هناك طريقتان لإنشاء وظائف:

  1. وظيفة الإعلان:

    function fn(){
      console.log("Hello");
    }
    fn();
    

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

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

  2. وظيفة التعبير:

    var fn=function(){
      console.log("Hello");
    }
    fn();
    

    جافا سكريبت لديها وظائف من الدرجة الأولى, وهذا هو إنشاء وظيفة تعيين إلى متغير تماما مثل إنشاء سلسلة أو رقم تعيين إلى متغير.هنا fn متغير يتم تعيينه على وظيفة.والسبب في هذا هو مفهوم وظائف الكائنات في جافا سكريبت.fn هو لافتا إلى مثيل كائن من الدالة أعلاه.علينا تهيئة وظيفة تعيين إلى متغير.ليس تنفيذ وظيفة وتعيين النتيجة.

المرجع: وظيفة جافا سكريبت إعلان الجملة:فار fn = وظيفة() {} مقابل وظيفة fn() {}

كل طرق مختلفة من تحديد وظيفة.الفرق هو كيف المتصفح يفسر والأحمال في سياق التنفيذ.

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

functionOne();
var functionOne = function() {
    // Some code
};

والسبب هو أن في السطر الأول لا تعيين قيمة functionOne ، وبالتالي هو غير معروف.نحن نحاول أن نسميها بوصفها وظيفة ، وبالتالي نحن على خطأ.

على السطر الثاني نحن تعيين مرجع مجهول وظيفة functionOne.

الحالة الثانية هو من وظيفة الإعلانات التي الأحمال قبل أي يتم تنفيذ التعليمات البرمجية.حتى إذا كنت لا تحب التالية أنك لن تحصل على أي خطأ إعلان الأحمال قبل تنفيذ التعليمات البرمجية.

functionOne();
function functionOne() {
   // Some code
}

عن الأداء:

إصدارات جديدة من V8 أدخلت عدة تحت غطاء محرك السيارة تحسينات و كذلك SpiderMonkey.

هناك تقريبا لا فرق الآن بين التعبير و الإعلان.
وظيفة التعبير يبدو أن أسرع الآن.

كروم 62.0.3202 Chrome test

فايرفوكس 55 Firefox test

كروم كناري 63.0.3225 Chrome Canary test


Anonymous وظيفة التعبير يبدو أن يكون الأداء أفضل ضد Named وظيفة التعبير.


فايرفوكس Firefox named_anonymous كروم كناري Chrome canary named_anonymous كروم Chrome named_anonymous

فهي مشابهة جدا مع بعض الاختلافات الصغيرة, الأول هو المتغير الذي أوكل إلى مجهول وظيفة (وظيفة الإعلان) و الثاني هو بالطريقة العادية لإنشاء وظيفة في جافا سكريبت(مجهول وظيفة الإعلان) ، سواء وقد الاستخدام ، من سلبيات و إيجابيات:

1.وظيفة التعبير

var functionOne = function() {
    // Some code
};

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

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

2.إعلان وظيفة

function functionTwo() {
    // Some code
}

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

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

أيضا, إذا كنت بحاجة إلى مزيد من المعلومات حول كيفية رفع يعمل في جافا سكريبت ، زيارة الرابط أدناه:

https://developer.mozilla.org/en-US/docs/Glossary/Hoisting

هذه هي اثنين فقط من الطرق الممكنة إعلان وظائف في الطريقة الثانية ، يمكنك استخدام وظيفة قبل الإعلان.

new Function() يمكن استخدامها لتمرير جسم الدالة في سلسلة.وبالتالي هذا يمكن أن تستخدم لخلق ديناميكية وظائف.أيضا تمرير السيناريو دون تنفيذ البرنامج النصي.

var func = new Function("x", "y", "return x*y;");
function secondFunction(){
   var result;
   result = func(10,20);
   console.log ( result );
}

secondFunction()
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top