简体   繁体   中英

Best way to define a function?

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

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

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

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

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.

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 .

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.

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.

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

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

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

  1. Foo is 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, Foo is likely intended to be an instantiated object, which precludes it from being behaving like a namespace.

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

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

This question and answers is 7 years old and is very outdated. This answer includes new syntax for versions of ES5 , ES6 , and compatible with 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")

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

Anonymous callback.

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

 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. eg a func that you will 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

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. 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:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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