javascript 定义函数的最佳方式?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3274225/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-25 00:43:39  来源:igfitidea点击:

Best way to define a function?

javascriptweb-applications

提问by Timmy

I'm always learned to define a function in JavaScript like this:

我总是学会在 JavaScript 中像这样定义一个函数:

function myFunction(arg1, arg2) { ... }

However, I was just reading Google's guide to Javascript, it mentioned I should define methods like this:

然而,我只是在阅读谷歌的 Javascript 指南,它提到我应该定义这样的方法:

Foo.prototype.bar = function() { ... };

Question: Is "Foo" in the example an Object, or is it a namespace? Why isn't the Google example the following code (which doesn't work):

问题:示例中的“Foo”是一个对象,还是一个命名空间?为什么 Google 示例不是以下代码(不起作用):

prototype.bar = function() { ... };

UPDATE: In case it helps to know, all of my JavaScript will be called by the users browser for my web-application.

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

回答by Sasha Chedygov

Your two examples are not functionally equivalent. The first example simply defines a function (probably a global one, unless you define it inside another function). The second example extends the prototype of a constructor. Think of it as adding a method to the class Foo.

您的两个示例在功能上并不等效。第一个例子简单地定义了一个函数(可能是一个全局函数,除非你在另一个函数中定义它)。第二个示例扩展了构造函数的原型。将其视为向类添加方法Foo

Unless you're building a JavaScript library, my suggestion would be to use neither and use some kind of namespace system. Create a single global object that acts as a namespace through which you can access all your functions.

除非您正在构建 JavaScript 库,否则我的建议是两者都不使用,而使用某种命名空间系统。创建一个作为命名空间的全局对象,您可以通过它访问所有功能。

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

Then:

然后:

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

If you want to emulate classes in JavaScript, you would define the "class" as a function (the function itself being the constructor) and then add methods through the prototypeproperty.

如果你想在 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() { /*...*/ }
};

Then:

然后:

var bar = new Foo();
console.log(bar.a); // 5
bar.doSomething();
// etc...

回答by Justin Johnson

I'm always learned to define a function in JavaScript like this: function myFunction(arg1, arg2) { ... }

我总是学会在 JavaScript 中像这样定义一个函数: function myFunction(arg1, arg2) { ... }

There are two ways to define a function. Either as a function declaration

定义函数有两种方式。要么作为函数声明

function foo(...) {
    ...
}

Or as a function expression

或者作为函数表达式

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

Readmorehere.

在这里阅读更多

However, I was just reading Google's guide to Javascript, it mentioned I should define methods like this: Foo.prototype.bar = function() { ... };

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

This is specifically related to method creation for objects, not just normal, stand-alone functions. Assuming you have the base object declaration:

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

var Foo = function() {
    ...
};

Just like any other assignment, to assign a function to an object's property, you must use an assignment expression. You can do this two ways. The succinct and common way (as suggested by Google's reference)

就像任何其他赋值一样,要将函数赋值给对象的属性,您必须使用赋值表达式。你可以通过两种方式做到这一点。简洁而通用的方式(如谷歌的参考所建议的那样)

Foo.prototype.bar = function() {};

Or, if you want to continue to use the declarative form of defining functions

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

function bar() {
    ...
};
Foo.prototype.bar = bar;

This is normally more verbose than necessary, but may be useful in situations where you want to assign the same method to multiple object prototypes.

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

Question: Is "Foo" in the example an Object, or is it a namespace? Why isn't the Google example the following code (which doesn't work): prototype.bar = function() { ... };

问题:示例中的“Foo”是一个对象,还是一个命名空间?为什么 Google 示例不是以下代码(不起作用):prototype.bar = function() { ... };

  1. Foois an object. Although the concept can be expressed through the use of static objects, as I've shown in my answer to your other question, there is no such thing as namespaces in JavaScript. Further, especially in the example code given, Foois likely intended to be an instantiated object, which precludes it from being behaving like a namespace.

  2. Of course it doesn't work: prototypehas not been defined as an object (unless, of course, you define it as such). The prototypepropertyexists on every object (a function is also an object), which is why you can do Foo.prototype.bar = ...;. Readmorehere.

  1. Foo是一个对象。虽然这个概念可以通过使用静态对象来表达,但正如我在对您的另一个问题的回答中所展示的,JavaScript 中没有命名空间这样的东西。此外,特别是在给出的示例代码中,Foo很可能是一个实例化的对象,这使其无法像命名空间一样运行。

  2. 当然它不起作用:prototype还没有被定义为一个对象(当然,除非你这样定义它)。该prototype属性存在于每个对象上(一个函数也是一个对象),这就是为什么你可以做Foo.prototype.bar = ...;. 在这里阅读更多

回答by Blindman67

=====> 2017 Update <=====

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

This question and answers is 7 years oldand is very outdated. This answer includes new syntax for versions of ES5, ES6, and compatible with ES7.

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



Best way to define a function?

定义函数的最佳方式?

There is no one "Best" way to define a function. How you define the function is dependent on the intended use and lifetime of the function.

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

Global functions

全局函数

Defined as a statement with the function token followed by the function name with lowercase camelcase

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

function functionName (arguments) {
    // function body
}

is preferable over the function expression...

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

var functionName = function (arguments) {
     // function body
}

...as the assignment to the variable of the function does not occur until the defining line is executed. Unlike the prefered method which is available immediately after parsing before any code is executed.

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

const functionName = function(arguments){/*function body*/}
var functionName = function functionName(arguments){/*function body*/}
var functionName = function functionAltName(arguments){/*function body*/}

Function objects

函数对象

As a function statement with uppercase camelcase function name

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

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

Anonymous function expression.

匿名函数表达式。

A common practice is to create object via an immediately invoked function that has no name (and is hence anonymous)

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

;(function (arguments) { /*function body*/ } ("argument val"))

Or

或者

;(function(arguments){ /*function body*/ })("argument val")

NOTEthe inclusion of the ;befor the function. This is very important as the open "(" will prevent automatic semicolon insertion on any code above the function.

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

Immediately invoked function expression.

立即调用函数表达式。

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

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

As a varor block scopedconst, let

作为一个var或块作用域constlet

Anonymous callback.

匿名回调。

With ES6 you should use the arrow function syntax rather than anonymous function expressions.

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

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

Function as properties.

函数作为属性。

Using the object declaration function shorthand syntax.

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

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

// called 
myObj.functionName("arg");

is preferable over

优于

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

Or via function object declarations

或者通过函数对象声明

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

Functions as prototypes

作为原型的函数

function MyObj (arguments) {
      MyObj.prototype.functionName = function(arguments) { /*function body*/ }
}

or

或者

function MyObj (arguments) {}
MyObj.prototype.functionName = function(arguments) { /*function body*/ }

or

或者

MyObj.prototype = {
    functionName(arguments) { /*function body*/ }
}

回答by Sky Sanders

Defining a prototype function is useful when creating constructors or 'classes' in JavaScript. e.g. a func that you will new

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

var MyClass = function(){};
MyClass.prototype.doFoo = function(arg){ bar(arg); }

but is of no use in plain old library functions e.g.

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

function doPopup(message){ /* create popup */};

There are several benefits of using a prototype function including but not limited to

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

  • speed
  • memory usage
  • extensibility
  • 速度
  • 内存使用情况
  • 可扩展性

But, again, this is in the context of creating constructors for instantiable 'classes'

但是,同样,这是在为可实例化的“类”创建构造函数的上下文中

HTH

HTH

回答by balupton

It works like so:

它的工作原理是这样的:

(function(){ // create an isolated scope
    // My Object we created directly
    var myObject = {
        a: function(x,y) {
            console.log('a');
        },
        b: function(x,y) {
            console.log('b');
            this.a(x,y);
        }
    };
})();

(function(){ // create an isolated scope

    // Create a Object by using a Class + Constructor
    var myClass = function(x,y) {
        console.log('myClass: constructor');
        this.b(x,y);
    };
    myClass.prototype = {
        a: function(x,y) {
            console.log('myClass: a');
        },
        b: function(x,y) {
            console.log('myClass: b');
            this.a(x,y);
        }
    };

    // Define a function that should never inherit
    myClass.c = function(x,y) {
        console.log('myClass: c');
        this.a(x,y);
    };

    // Create Object from Class
    var myObject = new myClass();
    // Will output:
    // myClass: constructor
    // myClass: b
    // myClass: a

    // Define a function that should never inherit
    myObject.d = function(x,y) {
        console.log('myObject: d');
        this.a(x,y);
    };

    // Test the world is roung
    console.log(typeof myClass.c, 'should be undefined...');
    console.log(typeof myClass.d, 'should be function...');
})();

(function(){ // create an isolated scope
    // If you are using a framework like jQuery, you can obtain inheritance like so

    // Create a Object by using a Class + Constructor
    var myClass = function(x,y) {
        console.log('myClass: constructor');
        this.b(x,y);
    };
    myClass.prototype = {
        a: function(x,y) {
            console.log('myClass: a');
        },
        b: function(x,y) {
            console.log('myClass: b');
            this.a(x,y);
        }
    };

    // Create new Class that inherits
    var myOtherClass = function(x,y) {
        console.log('myOtherClass: constructor');
        this.b(x,y);
    };
    $.extend(myOtherClass.prototype, myClass.prototype, {
        b: function(x,y) {
            console.log('myOtherClass: b');
            this.a(x,y);
        }
    });

    // Create Object from Class
    var myOtherObject = new myOtherClass();
    // Will output:
    // myOtherClass: constructor
    // myOtherClass: b
    // myClass: a
})();

(function(){ // create an isolated scope
    // Prototypes are useful for extending existing classes for the future
    // Such that you can add methods and variables to say the String class
    // To obtain more functionality
    String.prototype.alert = function(){
        alert(this);
    };
    "Hello, this will be alerted.".alert();
    // Will alert:
    // Hello, this will be alerted.
})();

Edit: Fixed code so that it will actually run in your browser if you copy and paste :-)

编辑:修复了代码,以便在您复制和粘贴时它实际上会在您的浏览器中运行:-)

回答by Dan Breslau

Foo is both an Object and a namespace. See this question.

Foo 既是一个对象又是一个命名空间。看到这个问题

Using objects as namespaces prevents name collisions. That's always a good idea, but especially when you're developing and/or using shared libraries.

使用对象作为命名空间可以防止名称冲突。这总是一个好主意,但尤其是在您开发和/或使用共享库时。

If you don't expect to be making multiple Foo objects (and so don't need the object-oriented style), you could create your functions as methods on a singleton object:

如果您不希望创建多个 Foo 对象(因此不需要面向对象的样式),则可以将函数创建为单例对象上的方法:

var Foo = {}
Foo.bar = function() { ... }

or

或者

var Foo = {
    bar: function() {...},
    quux: function() {...}
};

You'd then simply call the function as:

然后,您只需将函数调用为:

Foo.bar()

(This kind of declaration is roughly equivalent to a static method in C++ or Java.)

(这种声明大致相当于 C++ 或 Java 中的静态方法。)