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

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

兩種方式是:

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

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


当前回答

在其他答案中没有提到的另一个区别是,如果您使用匿名函数

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

用它作为一个建筑师

var one = new functionOne();

Function.name 是非标准的,但由 Firefox、Chrome、其他 Webkit 衍生浏览器和 IE 9+ 支持。

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

可以以 two.constructor.name 的字符串获取建筑师的名称。

其他回答

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

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

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

"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)

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

名称函数表达式

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

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

配件功能启动器(ES5+)

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"

您还可以使用 Object.defineProperty、Object.defineProperties 和 Object.create 更不熟悉的第二个论点创建附件功能。

Arrow 功能表达式(ES2015+)

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

看到 n => n * 2 隐藏在地图() 呼叫? 这是一个函数。

关于箭头功能的一些事情:

他們沒有自己的這一點. 相反,他們關閉了他們所定義的背景的這一點. (他們也關閉了論點,在相關的情況下,超級.) 這意味著他們內在的這一點是相同的這一點,在那裡他們是創造的,並且不能改變。

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

如果您正在做一个单一表达式以上,请使用 {} 和一个明确的回报(如果您需要返回值),如正常:

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

对象初步化方法宣言(ES2015+)

var o = {
    foo() {
    }
};

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

ES2015为我们提供类合成,包括声明的建筑师和方法:

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

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

谈到全球背景,这两种说法和函数声明最终将为全球对象创造一个不可分割的财产,但两者的价值可以被夸张。

两种方式之间的微妙区别在于,当变量定位过程运行(在实际代码执行之前)时,与 var 所宣布的所有标识符将以未定义的标识符开始,并且由 FunctionDeclaration 所使用的标识符将从那时起可用,例如:

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

 function test () {}
 test = null;

你的两个例子之间的另一个显而易见的区别是,第一个函数没有名字,而第二个函数有它,这在解体时可能非常有用(即检查一个呼叫板)。

此外,未透露的任务在严格模式下在 ECMAScript 5 上投下参考错误。

必须读一读:

名称 函数表达 解密

兩個函數之間的另一個區別是函數One 可以用作可持有多個函數的變量,而函數Two 持有某些代碼區塊,在呼叫時全部執行。

   var functionOne = (function() {
      return {

         sayHello: function(){
                console.log('say hello')

         },
         redirectPage:function(_url){
                window.location.href = _url;
         }

      }
})();

您有一个选项,该函数将被称为. e.g 函数One.sayHello 或函数One. redirectPage. 如果您呼叫函数Two 那么整个代码块将被执行。

第一個(函數 doSomething(x))應該是對象評分的一部分。

你可能想知道什么是函数声明和函数表达式。

function foo() {
    return 3;
}

ECMA 5(13.0)定义合成为函数识别器(FormalParameterListopt ) { 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) 定义合成为函数 Identifieropt ( FormalParameterListopt ) { FunctionBody }

名称功能 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!');

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