flying sheep
flying sheep

Reputation: 8962

Partial application of JavaScript methods: how to retain th meaning of “this”

In JavaScript, it’s pretty easy to define a partial application method for functions:

Function.prototype.partial = function partial() {
    var fn = this
    var args = Array.prototype.slice.call(arguments)

    return function() {
        var newArgs = Array.prototype.slice.call(arguments)
        return fn.apply(this, args.concat(newArgs))
    }
}

It works well for functions:

var biggerThanFive = Math.max.partial(5)
assert biggerThanFive(x) === Math.max(5, x)

But the resulting function’s “this” doesn’t stay the same as the original’s:

function Test() {
    this.name = 'test'
}

Test.prototype.a = function(b) {
    return [this.name, b]
}

var test = new Test()

test.a('x') // ['test','x']

var b = test.a.partial('y')
b() // [undefined,'y']

This can be fixed by manually binding the resulting function back to its original bound object:

var c = test.a.partial('z').bind(test)
c() //['test','z']

How to do this from within the Function.prototype.partial definition? test.a objiously knows that its “this” is “test”, so How can i access this knowledge?


What i learned from Esailija:

JavaScript doesn’t determine what “this” is inside a function at any other point than at calling time. var d = [].concat isn’t different from var d = Array.prototype.concat, and calling d() will call it on the global object because there’s nothing “on the left of it”.

Upvotes: 2

Views: 140

Answers (1)

Esailija
Esailija

Reputation: 140236

You can't.

You can do this with the built-in .bind method though, which is what you would eventually arrive at and settle with:

var b = test.a.bind(test, 'y')
b() 
//["test", "y"]

Upvotes: 1

Related Questions