定义函数的最佳方法是什么?

Tim*_*mmy 13 javascript web-applications

我总是学会在JavaScript中定义一个函数,如下所示:

function myFunction(arg1, arg2) { ... }
Run Code Online (Sandbox Code Playgroud)

但是,我刚刚阅读了谷歌的Javascript指南,它提到我应该定义这样的方法:

Foo.prototype.bar = function() { ... };
Run Code Online (Sandbox Code Playgroud)

问题:示例中的"Foo"是Object,还是名称空间?为什么Google示例不是以下代码(不起作用):

prototype.bar = function() { ... };
Run Code Online (Sandbox Code Playgroud)

更新:如果它有助于了解,我的所有JavaScript都将由用户浏览器调用我的Web应用程序.

Sas*_*gov 8

你的两个例子在功能上并不相同.第一个示例只是定义一个函数(可能是全局函数,除非您在另一个函数中定义它).第二个例子扩展了构造函数的原型.可以把它想象为向班级添加方法Foo.

除非您正在构建JavaScript库,否则我的建议是既不使用也不使用某种命名空间系统.创建一个充当命名空间的全局对象,通过该命名空间可以访问所有功能.

var MyObject = {
    utils: {
        someUtil: function() {},
        anotherUtil: function() {}
    },
    animation: {
        // A function that animates something?
        animate: function(element) {}
    }
};
Run Code Online (Sandbox Code Playgroud)

然后:

// Assuming jQuery, but insert whatever library here
$('.someClass').click(function() {
    MyObject.animation.animate(this);
});
Run Code Online (Sandbox Code Playgroud)

如果要在JavaScript中模拟类,可以将"类"定义为函数(函数本身是构造函数),然后通过prototype属性添加方法.

function Foo() {
    // This is the constructor--initialize any properties
    this.a = 5;
}
// Add methods to the newly defined "class"
Foo.prototype = {
    doSomething: function() { /*...*/ },
    doSomethingElse: function() { /*...*/ }
};
Run Code Online (Sandbox Code Playgroud)

然后:

var bar = new Foo();
console.log(bar.a); // 5
bar.doSomething();
// etc...
Run Code Online (Sandbox Code Playgroud)


Jus*_*son 7

我总是学会在JavaScript中定义一个函数,如下所示: function myFunction(arg1, arg2) { ... }

有两种方法可以定义函数.作为函数声明

function foo(...) {
    ...
}
Run Code Online (Sandbox Code Playgroud)

或者作为函数表达式

var foo = function() {
    ...
};
Run Code Online (Sandbox Code Playgroud)

在这里阅读更多 .

但是,我刚刚阅读了谷歌的Javascript指南,它提到我应该定义这样的方法: Foo.prototype.bar = function() { ... };

这特别与对象的方法创建有关,而不仅仅是普通的独立函数.假设您有基础对象声明:

var Foo = function() {
    ...
};
Run Code Online (Sandbox Code Playgroud)

与任何其他赋值一样,要将函数赋值给对象的属性,必须使用赋值表达式.你可以用两种方法做到这一点.简洁而通用的方式(根据Google的参考建议)

Foo.prototype.bar = function() {};
Run Code Online (Sandbox Code Playgroud)

或者,如果您想继续使用定义函数的声明形式

function bar() {
    ...
};
Foo.prototype.bar = bar;
Run Code Online (Sandbox Code Playgroud)

这通常比必要的更冗长,但在您希望将相同方法分配给多个对象原型的情况下可能很有用.

问题:示例中的"Foo"是Object,还是名称空间?为什么Google示例不是以下代码(不起作用):prototype.bar = function() { ... };

  1. Foo是一个对象.尽管这个概念可以通过静态对象的使用来表达,正如我在回答你的另一个问题时所表明的那样,JavaScript中没有名称空间.此外,特别是在给出的示例代码中,Foo可能意图是实例化对象,这使得它不能像命名空间那样行为.

  2. 当然它不起作用:prototype尚未定义为对象(当然,除非您将其定义为对象).该prototype 属性存在于每个对象上(函数也是一个对象),这就是你可以做到的原因Foo.prototype.bar = ...;. 在这里阅读 更多 .


Bli*_*n67 6

======> 2017 更新 <=====

这个问答已经7年了,已经很过时了。这个答案包括ES5、ES6版本的新语法,并与ES7兼容。


定义函数的最佳方式?

没有一种定义函数的“最佳”方法。如何定义函数取决于函数的预期用途和生命周期。

全局函数

定义为带有函数标记的语句,后跟带有小写驼峰的函数名称

function functionName (arguments) {
    // function body
}
Run Code Online (Sandbox Code Playgroud)

比函数表达式更可取...

var functionName = function (arguments) {
     // function body
}
Run Code Online (Sandbox Code Playgroud)

...因为在执行定义行之前不会发生对函数变量的赋值。与在执行任何代码之前解析后立即可用的首选方法不同。

const functionName = function(arguments){/*function body*/}
var functionName = function functionName(arguments){/*function body*/}
var functionName = function functionAltName(arguments){/*function body*/}
Run Code Online (Sandbox Code Playgroud)

函数对象

作为带有大写驼峰函数名的函数语句

function MyObjectFunction (arguments) {
    /*function body*/
    // if this function is called with the new token
    // then it exits with the equivalent return this;
}

const obj = new MyObjectFunction(foo);
Run Code Online (Sandbox Code Playgroud)

匿名函数表达式。

一种常见的做法是通过一个没有名称(因此是匿名的)立即调用的函数来创建对象

;(function (arguments) { /*function body*/ } ("argument val"))
Run Code Online (Sandbox Code Playgroud)

或者

;(function(arguments){ /*function body*/ })("argument val")
Run Code Online (Sandbox Code Playgroud)

注意包含;before 函数。这非常重要,因为打开的“(”将阻止在函数上方的任何代码上自动插入分号。

立即调用函数表达式。

const functionResult = (function (arguments) {
      /*function body*/
      return functionResult;
}());

const functionResult = (function (arguments) {
      /*function body*/
      return functionResult;
})();
Run Code Online (Sandbox Code Playgroud)

作为一个var或块作用域const,let

匿名回调。

在 ES6 中,您应该使用箭头函数语法而不是匿名函数表达式。

 myArray.forEach((item,i) => {/*function body*/});
 myArray.filter(item => !item);
 setTimeout(() => {/*function body*/}, 1000);
Run Code Online (Sandbox Code Playgroud)

函数作为属性。

使用对象声明函数的速记语法。

var myObj = {
    functionName (arguments) {/*function body*/},
}

// called 
myObj.functionName("arg");
Run Code Online (Sandbox Code Playgroud)

优于

var myObj = {
    functionName : function (arguments) {/*function body*/},
}
Run Code Online (Sandbox Code Playgroud)

或者通过函数对象声明

function MyObjectFunction(arguments){
     this.propertyFunction = function(arguments) { /*function body*/ }
     // or arrow notation is fine
     this.propertyFunction = (argument) => { /*function body*/ };
}
Run Code Online (Sandbox Code Playgroud)

作为原型的函数

function MyObj (arguments) {
      MyObj.prototype.functionName = function(arguments) { /*function body*/ }
}
Run Code Online (Sandbox Code Playgroud)

或者

function MyObj (arguments) {}
MyObj.prototype.functionName = function(arguments) { /*function body*/ }
Run Code Online (Sandbox Code Playgroud)

或者

MyObj.prototype = {
    functionName(arguments) { /*function body*/ }
}
Run Code Online (Sandbox Code Playgroud)


Sky*_*ers 2

在 JavaScript 中创建构造函数或“类”时,定义原型函数非常有用。例如你会的一个函数new

var MyClass = function(){};
MyClass.prototype.doFoo = function(arg){ bar(arg); }
Run Code Online (Sandbox Code Playgroud)

但在普通的旧库函数中没有用,例如

function doPopup(message){ /* create popup */};
Run Code Online (Sandbox Code Playgroud)

使用原型函数有几个好处,包括但不限于

  • 速度
  • 内存使用情况
  • 可扩展性

但是,这又是在为可实例化“类”创建构造函数的背景下

华泰