Liquid Core
Liquid Core

Reputation: 1

Prototype with this keyword is not giving the expected result

In javascript, why this? And for the hell of me, I can't find anything explaining it

Say

var ATest = function(atom, electron)
{
    this.atom = atom;
    this.electron = electron;
}
ATest.prototype.atom = 'emptyAtomA';
ATest.prototype.electron = 1;

I come from C# and this prototype thing is like default constructor values for javascript objects

so, i try this in Chrome console:

var ATestVariable = new ATest();
ATestVariable.atom
//Result->undefined
ATestVariable.electron
//Result->undefined

And this is strange for me, so I try in the global context (don't know, maybe using this has produced some weird assignemnt...)

this.atom
//Result->undefined
this.electron
//Result->undefined
window.atom
//Result->undefined

Nothing here too.

Now, if I try

var BTest = function(Atom, Electron)
{
    atomB = Atom;
    electronB = Electron;
}
BTest.prototype.atom = 'emptyAtomB';
BTest.prototype.electron = 12;

And then I do

var BTestVariable = new BTest();
BTestVariable.atom
//Result->"emptyAtomB"
BTestVariable.electron
//Result -> 12

This is what I get and what I would expect in both cases.

What is happening?

Upvotes: 1

Views: 44

Answers (2)

Code Maniac
Code Maniac

Reputation: 37755

You're not passing any parameter to constructor when you're calling new ATest, so the value assigned to this.atom and this.electron turns out to be undefined

var ATest = function(atom, electron)
{
    this.atom = atom;
    this.electron = electron;
}

// when values not passed to constructor
var ATestVariable = new ATest();
console.log(ATestVariable)


// when values passed to constructor
var BTestVariable = new ATest(1, 'some value');
console.log(BTestVariable)

Not let's talk about values added to prototype, the values are are ATest internal prototype so you need to get access values using that

var ATest = function(atom, electron)
{
    this.atom = atom;
    this.electron = electron;
}
ATest.prototype.atom = 'emptyAtomA';
ATest.prototype.electron = 1;

let a = new ATest()

console.log(Object.getPrototypeOf(a).atom)
console.log(a.__proto__.atom)

Upvotes: 0

CertainPerformance
CertainPerformance

Reputation: 370689

When you do

var ATest = function(atom, electron)
{
    this.atom = atom;
    this.electron = electron;
}
ATest.prototype.atom = 'emptyAtomA';
ATest.prototype.electron = 1;

The first and second parameters passed to the constructor will be assigned to properties of the instance (this) no matter what. If you do not pass any parameters, then the values of the standalone variables atom and electron will be undefined, so the instance ends up having own properties atom and electron whose values are undefined.

The instance still has an internal prototype object, and that internal prototype has property values emptyAtomB and 12, but because the instance has own properties with the same name, they overshadow the properties on the internal prototype.

var ATest = function(atom, electron)
{
    this.atom = atom;
    this.electron = electron;
}
ATest.prototype.atom = 'emptyAtomA';
ATest.prototype.electron = 1;

var ATestVariable = new ATest();

console.log(ATestVariable.atom);
console.log(Object.getPrototypeOf(ATestVariable).atom);

It sounds like you may be wanting to check to see if the arguments are defined first:

var ATest = function(atom, electron)
{
    if (atom !== undefined) {
        this.atom = atom;
    }
    if (electron !== undefined) {
        this.electron = electron;
    }
}

When you do

var BTest = function(Atom, Electron)
{
    atomB = Atom;
    electronB = Electron;
}

you're assigning the parameters to global variables atomB and electronB. This is not desirable, and will throw an error in strict mode.

Of course, it would be best to simply always pass all expected arguments to the constructor every time, if that's what your script expects:

var ATest = function(...args)
{
    if (args.length !== 2) {
        throw new Error('Two arguments required: atom and electron');
    }
    const [atom, electron] = args;
    this.atom = atom;
    this.electron = electron;
}

Upvotes: 1

Related Questions