简体   繁体   English

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

[英]Best way to define a function?

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? 问题 :示例中的“Foo”是Object,还是名称空间? Why isn't the Google example the following code (which doesn't work): 为什么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应用程序。

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. 除非您正在构建JavaScript库,否则我的建议是既不使用也不使用某种命名空间系统。 Create a single global object that acts as a namespace through which you can access all your functions. 创建一个充当命名空间的全局对象,通过该命名空间可以访问所有功能。

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 prototype property. 如果要在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...

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

Read more here . 在这里 阅读 更多

However, I was just reading Google's guide to Javascript, it mentioned I should define methods like this: Foo.prototype.bar = function() { ... }; 但是,我刚刚阅读了谷歌的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) 简洁而通用的方式(根据Google的参考建议)

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? 问题:示例中的“Foo”是Object,还是名称空间? Why isn't the Google example the following code (which doesn't work): prototype.bar = function() { ... }; 为什么Google示例中没有以下代码(不起作用): prototype.bar = function() { ... };

  1. Foo is an object. Foo是一个对象。 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. 尽管这个概念可以通过静态对象的使用来表达,正如我在回答你的另一个问题时所表明的那样,JavaScript中没有名称空间。 Further, especially in the example code given, Foo is likely intended to be an instantiated object, which precludes it from being behaving like a namespace. 此外,特别是在给出的示例代码中, Foo可能旨在成为实例化对象,这使其无法像命名空间那样运行。

  2. Of course it doesn't work: prototype has not been defined as an object (unless, of course, you define it as such). 当然它不起作用: prototype尚未定义为对象(当然,除非您将其定义为对象)。 The prototype property exists on every object (a function is also an object), which is why you can do Foo.prototype.bar = ...; prototype 属性存在于每个对象上(函数也是一个对象),这就是为什么你可以做Foo.prototype.bar = ...; . Read more here . 在这里 阅读 更多

=====> 2017 Update <===== =====> 2017年更新<=====

This question and answers is 7 years old and is very outdated. 这个问题和答案是7岁 ,非常过时。 This answer includes new syntax for versions of ES5 , ES6 , and compatible with ES7 . 此答案包括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 定义为带有函数标记的语句,后跟带有小写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 作为带有大写camelcase函数名的函数语句

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

NOTE the inclusion of the ; 注意包含; befor the function. 这个功能。 This is very important as the open "(" will prevent automatic semicolon insertion on any code above the function. 这非常重要,因为打开“(”将阻止在函数上方的任何代码上插入自动分号。

Immediately invoked function expression. 立即调用函数表达式。

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

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

As a var or block scoped const , 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*/ }
}

Defining a prototype function is useful when creating constructors or 'classes' in JavaScript. 在JavaScript中创建构造函数或“类”时,定义原型函数很有用。 eg a func that you will new 例如,你将是new

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

but is of no use in plain old library functions eg 但在普通的旧图书馆功能中没有用处,例如

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

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 :-) 编辑:修复代码,以便在您复制并粘贴时它将实际在您的浏览器中运行:-)

Foo is both an Object and a namespace. Foo既是Object又是命名空间。 See this question . 看到这个问题

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中的静态方法。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM