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

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

兩種方式是:

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

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


当前回答

我更喜欢将函数定义为变量:

let first = function(x){
   return x[0];
}

而不是:

function first(){
    ....
}

因为我可以在定义函数时使用表达式和装饰器,例如:

let safe = function(f){
  try {f()...}
}
let last = safe(function(x){return x[0]}).

此外,在 ES6 中,它更短:

 let last = x => x[0]
 ...........
 function last(x){
     return x[0];
 }
......

let last = safe(x => x[0]);

其他回答

二是定义函数的不同方式,区别在于浏览器如何解释并将其加载到执行背景中。

第一個案例是函數表達,只有當翻譯者達到這個代碼線時才會充電,因此,如果你這樣做,你會發現函數一不是函數的錯誤。

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

原因在于,在第一行中,没有值被分配到函数One,因此它是不定义的,我们试图称之为函数,因此我们得到一个错误。

在第二行中,我们将匿名函数的参考归分为函数One。

第二个案例是功能声明,在任何代码执行之前加载,所以如果你喜欢下一个,你不会得到任何错误,因为声明加载,在代码执行之前。

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

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

变量

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

您不能在函数声明上使用.bind() 方法,但您可以在函数表达式上使用。

功能宣言:

函数 x() { console.log(this) }.bind('string') x()

功能表达:

var x = 函数() { console.log(this) }.bind('string') x()

名称功能 vs. 匿名功能

第一函数合成是匿名函数表达式:

var functionOne = function() {
  // do something...
};

但是,第二个是功能宣言:

function functionTwo () {
  // do something...
}

兩者之間的主要區別是函數名稱,因為匿名函數沒有呼叫的名稱. 匿名函數是快速且容易宣告的,許多圖書館和工具往往鼓勵這種愚蠢的代碼風格. 然而,匿名函數有一些缺點:

可读性:匿名函数忽略了一个名称,可能会导致更少可读的代码。 解密: 匿名函数没有名称,可以使解密更困难。

名称函数表达式

為您的功能表達提供一個名稱,非常有效地解決所有這些缺點,並且沒有實際的缺點。

setTimeout(function timeHandler() { // <-- look, a name here!
  console.log("I've waited 1 second");
}, 1000);

名称 IIFEs(即时启发功能表达)

(function IIFE(str) { // <-- look, always name IIFEs!
  console.log(str); // "Hello!"
})('Hello!');

对于一个变量的函数,这个函数的名称,在这种情况下,不太常见,可能会导致混乱,在这种情况下,箭头函数可能是一个更好的选择。

当原始忍者物体被移除时,测试失败(第13页)

function assert(predicate, message) { if(!predicate) { throw new Error(message); } } 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?" ); }

function assert(predicate, message) { if(!predicate) { throw new Error(message); } } 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." ); console.log(samurai.yell(4));