0

I've got a wrapper class (singleton) like so:

'use strict'

var _ = require('lodash')

var SDK = {
    isInitialized: false,
    isSharedInstance: true,
    initSharedInstance: function() {
        var args = Array.prototype.slice.call(arguments)
        var self = this
        if (self.isInitialized) {
            console.log('SDK shared instance is already initialized')
            return self
        }
        var SDKClient = require('./lib/client')
        console.log('parent', args)
        var client = Function.prototype.bind.apply(SDKClient, args)
        _.assign(self, client)
        Object.setPrototypeOf(self, new client())
        self.isInitialized = true
        self.isSharedInstance = true
        self.SDKQuery = require('./lib/query')
    }
}

SDK.init = SDK.initSharedInstance
module.exports = SDK

To an SDK client class:

'use strict'

var _ = require('lodash')

var defaultOptions = {
    baseUrl: 'url'
}

var UsergridClient = function() {
    var self = this

    self.isSharedInstance = false

    var args = Array.prototype.slice.call(arguments)
    console.log('child', args)
    var options = _.isPlainObject(args[0]) ? args[0] : {}
    if (args.length === 2) {
        self.orgId = args[0]
        self.containerId = args[1]
    }

    _.defaults(self, options, helpers.config, defaultOptions)

    return self
}

Using this suggestion, it look like I should be able to do:

var client = Function.prototype.bind.apply(SDKClient, args)
_.assign(self, client)
Object.setPrototypeOf(self, new client())

But for some reason when I log it out, you'll see:

SDK.init('org', 'container')

// parent [ 'org', 'container' ]
// child [ 'container' ]

What's stranger still, is that when I only pass one argument, child logs out as an empty array.

What's wrong with this solution? How can I correctly pass the complete args array to the singleton's initialization of the SDK client? My guess is that it's some missing (or extra) argument in the bind.apply() call, but I can't figure out what.

Community
  • 1
  • 1
brandonscript
  • 68,675
  • 32
  • 163
  • 220

2 Answers2

1

The post you linked says that

new Something(a, b, c)

is equivalent to

new (Function.prototype.bind.apply(Something, [null, a, b, c]))

Notice the null! You still need to bind the function to something - something that will subsequently be ignored when the function is used with new, but something to pass nonetheless.

You should use

var args = [null];
args.push.apply(args, arguments);
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • Ha, now I get it. Thanks! Ended up using `var client = Function.prototype.bind.apply(SDKClient, args.unshift(null))` for conciseness. – brandonscript Mar 08 '16 at 22:08
  • @remus: `unshift` returns the length, not the array; you can't use that in an expression. I guess the way to go would be `bind.apply(constructor, [null].concat(slice.call(arguments)))`, but that's ugly. – Bergi Mar 08 '16 at 22:11
0

apply() using to pass args in array []. So to pass your args using apply() you need to put it in array.

apply(context,[arg1,arg2,...]

You can use call() - it is doing what you want to do.

call(context, arg1, arg2,...]
alexey
  • 1,381
  • 9
  • 19