wordorf
wordorf

Reputation: 13

function returning function as property

I know that it's sometimes handy to make functions return other functions so that you don't have to repeat yourself, increase modularity, etc.
But what's the point in this snippet(one of many) here from the three.js library?

Object.assign( Matrix4.prototype, {

...

    applyToBufferAttribute: function () {

        var v1 = new Vector3();

        return function applyToBufferAttribute( attribute ) {

            for ( var i = 0, l = attribute.count; i < l; i ++ ) {

                v1.x = attribute.getX( i );
                v1.y = attribute.getY( i );
                v1.z = attribute.getZ( i );

                v1.applyMatrix4( this );

                attribute.setXYZ( i, v1.x, v1.y, v1.z );

            }

            return attribute;

        };

    }(),

...

} );

The 'inlined' applyToBufferAttribute doesn't get reused anywhere else.

Upvotes: 1

Views: 62

Answers (2)

mathk
mathk

Reputation: 8143

This is how you "hide" a variable to the outer scope.

v1 is no longer visible outside of your module and you make sure that nobody will tamper it.

Typically the return function is a closure that close over the v1 variable.

An alternative would be to make a full fledge object and make v1 readonly but you often wont bother to make such object. So it a quick handy way to encapsulate some variable.

A second alternative would be the add v1 to the return object.

function applyToBufferAttribute() {
    if (!this.v1) {
        this.v1 = new Vector3();
    }
    ...
 }

But this also have the issue of making v1 visible outside and make code more fragile.

Upvotes: 0

Amadan
Amadan

Reputation: 198436

The returned function becomes the method, yes. The purpose of wrapping it into an IIFE is to hide the v1 variable, making it what C would call "static variable": no matter how many Matrix4 objects you make, no matter how many times you invoke applyToBufferAttribute, there will be only one instance of v1, and it will not be accessible except inside the applyToBufferAttribute function.

The purpose of that, we can only guess at, but probably avoiding allocation and deallocation costs for that Vector3 object, assuming applyToBufferAttribute gets called with some frequency. Given that three.js is a WebGL library, every little bit of optimisation helps.

Upvotes: 1

Related Questions