Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

A function and an object at the same time?

Tags:

javascript

Is it possible that after creating a function variable you can actually assign properties to it as if it's a regular object? This is what I did:

var example = function(a, b){
    console.log(a, b);
}
example.someProperty = 'hi there';

Then I typed these lines in the browser console:

example('Hello', 'world') // Hello world
example.someProperty // hi there

So now basically the 'example' var acts as a function and as an object at the same time. This raised some questions for me, one of which is why, and another one - is there a way to do this by creating an object literal, because I can't think of such way.

like image 824
arhonthhh Avatar asked Oct 13 '15 08:10

arhonthhh


People also ask

Can a function be in an object?

Well, it's because functions are not just objects, they are Function objects, meaning that besides being able to assign properties and methods to them, they also have properties and methods already defined by the built-in Function object.

Are functions and objects the same?

An object is a collection of functions and data. A function is a collection of commands and data. When a bunch of functions work together to perform a certain task we may call this community of functionality an object.

What is an object function called?

In computer programming, a function object is a construct allowing an object to be invoked or called as if it were an ordinary function, usually with the same syntax (a function parameter that can also be a function). Function objects are often called functors.

Are functions associated with an object?

A method, like a function, is a set of instructions that perform a task. The difference is that a method is associated with an object, while a function is not.


1 Answers

So now basically the 'example' var acts as a function and as an object at the same time.

It doesn't act as a function and an object, it is a function and an object. Functions are objects in JavaScript.

This raised some questions for me, one of which is why

Fundamentally because that's what Eich decided to do in those 10 days in May 1995. Why he decided that is something only he can answer, but there have been many languages through the years that also see no reason to treat functions as something special and different. Presumably he was influenced by those. It's incredibly handy and flexible that functions are proper objects. For instance:

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

I can use the variable f to refer to foo because foo is an object. In many languages, such as Java, it's a real pain to do that (though Java is a bit better now thanks to its recently-added lambdas).

Since functions are objects, they have a prototype, which means I can add features to all functions. For instance: I find it quite handy to be able to take a function and "bake in" (or "curry") arguments:

// A simple function
function foo(a, b) {
    console.log("a is " + a);
    console.log("b is " + b);
}

// Create a new one that, when called, will call the original passing in
// 1 as the first argument and then passing in any further arguments,
// preserving the `this` it was called with
var f = foo.curry(1);

// Call it
f(2); // "a is 1" / "b is 2"

Since JavaScript doesn't have a curry function (it has bind, which is similar, but interferes with this), I can add one:

var slice = Array.prototype.slice;
Object.defineProperty(Function.prototype, "curry", {
    value: function() {
        var f = this;
        var args = slice.call(arguments);
        return function() {
            return f.apply(this, args.concat(slice.call(arguments)));
        };
    }
});

And voilà, now I can use curry on any function:

var slice = Array.prototype.slice;
Object.defineProperty(Function.prototype, "curry", {
  value: function() {
    var f = this;
    var args = slice.call(arguments);
    return function() {
      return f.apply(this, args.concat(slice.call(arguments)));
    };
  }
});

// A simple function
function foo(a, b) {
  snippet.log("a is " + a);
  snippet.log("b is " + b);
}

// Create a new one that, when called, will call the original passing in
// 1 as the first argument and then passing in any further arguments,
// preserving the `this` it was called with
var f = foo.curry(1);

// Call it
f(2); // "a is 1" / "b is 2"
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="//tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

is there a way to do this by creating an object literal

No, the only way to create a function is to start out with a function. You can't take a non-function object and turn it into a function.

like image 97
T.J. Crowder Avatar answered Oct 11 '22 07:10

T.J. Crowder