3

I am a C++/Java developer that has been tasked with a javascript project and I cannot seem to figure this issue out.

I am working with a javascript file that defines a namespace by direct assignment as described here

So here is my attempt at an overly simplified example namespace

// testns.js
var ns = { }
ns.val = -1;

ns.setVal = function(newVal) {
    this.val = newVal;
}

And here is what I would like to do

//myScript.js
function testNamespaceInstances()
{
    var nsInstance1 = ns;
    nsInstance1.setVal(1);

    var nsInstance2 = ns;
    nsInstance2.setVal(2);

    console.log("nsInstance1.val: " + nsInstance1.val);
    console.log("nsInstance2.val: " + nsInstance2.val);
}

That function will output

nsInstance1.val: 2
nsInstance2.val: 2

Is there anything I can do without modifying the testns.js file that the namespace is declared in so that the function will output

nsInstance1.val: 1
nsInstance2.val: 2

Edit: Added some more details to the example code. I would also like to note I am attempting to simplify a more complex javascript file that I am working with

0

6 Answers 6

3

Just create a second namespace (object, really): nsInstance2 = {}; -- the problem here is that both nsInstance1 and nsInstance2 are pointing to the same object, so naturally, if you change the properties of one, it'll be reflected in the other.

Sign up to request clarification or add additional context in comments.

Comments

3

Complex data types in JavaScript are copied as references, so your nsInstance1 and nsInstance2 variables merely point to the namespace object - they do not copy or instantiate it.

To instantiate it, the namespace must be declared as a function, not an object literal, and referenced with the new keyword. Only functions can be used in instantiation in JavaScript.

function NS() {}
var ns1 = new NS();
var ns2 = new NS();

4 Comments

Thanks for the answer, I agree that this is the way to go, unfortunately I am trying to accomplish this without modifying the contents of the nstest.js file.
You're welcome. In that case, you're going to have to re-think things because object literals cannot be instantiated.
@Utkanos, what about Object.create?
@katspaugh - sure, worth a mention, but I don't tend to suggest it as I assume OPs need support for IE <= 8.
1

You could do the following:

var ns = function() {
    return {};
};

and

function testNamespaceInstances() {
    var nsInstance1 = new ns;
    nsInstance1.val = 1;

    var nsInstance2 = new ns;
    nsInstance2.val = 2;

    console.log("nsInstance1.val: " + nsInstance1.val);
    console.log("nsInstance2.val: " + nsInstance2.val);
}

jsFiddle example

Comments

1

First, there are no namespaces in JavaScript. {} is just an object literal, the same as new Object().

Second, you don't instantiate objects by giving them several references. You can instantiate an object with Object.create:

var nsInstance1 = Object.create(ns);
var nsInstance2 = Object.create(ns);

3 Comments

@michaelok, whenever you have to type a dot before a symbol – it's not a namespace but a fake. We need portable scope, like import * from module in Python.
Good point, thanks for the explanation. This article and the post by Kevin Dangoor also clarified the issue "JavaScript needs a standard way to include other modules and for those modules to live in discreet namespaces. There are easy ways to do namespaces, but there’s no standard programmatic way to load a module (once!)."
0
//myScript.js
Object.prototype.clone = function() {
  var newObj = (this instanceof Array) ? [] : {};
  for (var i in this) {
    if (i == 'clone') continue;
    if (this[i] && typeof this[i] == "object") {
      newObj[i] = this[i].clone();
    } else newObj[i] = this[i]
  } return newObj;
};

function testNamespaceInstances()
{
    var nsInstance1 = ns.clone();
    nsInstance1.val = 1;

    var nsInstance2 = ns.clone();
    nsInstance2.val = 2;

    console.log("nsInstance1.val: " + nsInstance1.val);
    console.log("nsInstance2.val: " + nsInstance2.val);
}

Comments

0

Since your are taking ns at a global scope, you can just directly assign values to it like-

//testns.js

var ns = { }
ns.val = -1;

function testNamespaceInstances()
{
    ns.val1=1;
    ns.val2=2;

    console.log("ns.val1: " + ns.val1);
    console.log("ns.val2: " + ns.val2);
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.