我最近开始保持别人的JavaScript代码,我正在修复错误,添加功能,也试图更新代码并使其更加一致。

以前的开发人员使用了两种方式来宣布功能,我无法解决是否有原因。

兩種方式是:

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

使用这两种不同的方法的原因是什么?每个方法的优点和缺点是什么?可以用一种方法做些什么,不能用另一种方法做些什么?


当前回答

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

其次,可以结合两种风格:

var xyz = function 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;

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

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);
  // ...
}

在上面的例子中,我们可以用外部名称做同样的事情,但它会太不多(而且更慢)。

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

// 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(){};

function abc(){};

它取决于背景,可能会让你猜测它实际上在哪里定义,特别是在 eval()的情况下 - 答案是: 它取决于浏览器。

其他回答

在代码维护成本方面,所谓的功能更受欢迎:

无论它们在哪里被宣布(但仍然受到范围限制)。 更抵抗错误,如条件启动(你仍然可以过度排序,如果你愿意)。 代码变得更可读,通过分配地方功能分开的范围功能。 通常在范围内,功能先行,其次是局部功能的声明。

我怀疑更多关于名称功能的PROS正在追踪,而被列为名称功能的优势是匿名功能的缺点。

历史上,匿名函数出现,因为JavaScript作为语言无法列出名为函数的会员:

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

一个函数声明和一个函数表达,在一个变量行为被定义后,相同。

基本上,所有函数声明和变量声明都被插入到声明发生函数的顶部(这就是为什么我们说JavaScript具有函数范围)。

当一个函数声明被拍摄时,函数体“跟随”,因此当函数体被评估时,变量将立即与函数对象联系起来。当一个变量声明被拍摄时,启动不会跟随,而是“左后面”。变量在函数体的开始时被启动到未定义,并将在其原始位置分配一个值。

一些例子......

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

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

函数内所宣布的变量/函数在页面内是全球性的,可以访问该页面中的任何地方.函数内所宣布的变量/函数具有本地范围. 也就是说,它们在函数体内可用/可用,它们不在函数体外可用。

变量

JavaScript 被称为顺利打字语言,这意味着 JavaScript 变量可以保留任何数据类型的值,JavaScript 会自动根据运行时间提供的值/字体来改变变量类型。

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';
}

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();

JavaScript 被解释为

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();


ES5 Constructor 功能类:使用 Function.prototype.bind 创建的功能对象

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

ArrowFunction : ArrowParameters => ConciseBody. const fn = (item) => {返回项目 & 1? 'Odd' : 'Even'; }; console.log( fn(2) ); // Even console.log( fn(3) ); // Odd

函数One = 函数() {} 定义在运行时间,函数Two() {} 定义在部分时间。

// Run-Time function declaration 
functionOne(); // Calling functionOne function here will give an Error
var functionOne = function () {
  // Some code
};

// Parse-Time function declaration 
functionTwo(); // Calling functionTwo function will not give an Error
function functionTwo() {
  // Some code...
}

此分類上一篇: Run-time vs Parse-time javascript run-time vs parse-time

如果你使用这些功能来创建对象,你会得到:

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