1

i'm new to JS and got the following problem:

Why is this not working / what is this code doing?

var Test = {};
Test.prop = "test property";

Test.Class1 = function () {
}

Test.Class1.prototype = {
    m1: function() {
        console.log(this.prop);
    }
}

Test.Class1.m1();

My understanding of this code would be:

  1. creating a new object called Test
  2. adding the property prop to Test
  3. creating a new object called Class1 in Test
  4. adding a method m1 to Class1
  5. calling the m1 method of Class1 in Test

4 Answers 4

1

In JavaScript, even the prototype property of a function is an object. Prior to creating an object whose prototype is the one you've defined, Test1.Class1.prototype is just a regular object. Basically it works the same way as the following code snippet:

var Test1 = { prototype { m1: function() {} } };
// You're trying to call an undefined function!
Test.m1();

// This is fine
Test1.prototype.m1();

In the other hand, when you use the new operator, you're creating a new object whose prototype is the one set to the constructor function. And here starts the magic:

var Test1 = function() {};
Test1.prototype = {
    doStuff: function() {}
};

var object1 = new Test1();
// This works!
object1.doStuff();

When you access a property, JavaScript's runtimes inspect the object to find out if there's a function called doStuff, otherwise it looks for it on the object's prototype, otherwise it looks on the prototype of the prototype and so on...

Actually new operator is a syntactic sugar. ECMA-Script 5 introduced Object.create which makes everything more clear:

var Test1 = {
    doStuff: function() {
    }
};

// The first parameter of Object.create is
// the object that's going to be the prototype of
// Test1 object!
var object1 = Object.create(Test1);
// This works too!
object1.doStuff();

Probably you should check this other Q&A: How does JavaScript .prototype work?

1

You need to create an instance of the prototype before you're able to use its methods:

var instance = new Test.Class1();
console.log(instance.m1());

Even as such, Test.prop is not part of the instance, and will not be accessible to m1

Edit: Here's a working example:

var test = function() {
  this.prop = "A property";
}

test.prototype.m1 = function() {
  console.log(this.prop);
}

var instance = new test();
console.log(instance.m1());
1

prototype chaining only works for instances created with the new operator.

Otherwise you will have to explicitly call prototype to access the method.

let testClass = new Test.Class1();

testClass.m1();

Also since you are trying to access the prop property.

Test.Class1.prototype = {
    m1: function() {
        console.log(this.prop);
    }
}

The call site is Test.Class1, the prop should be part of Test.Class1 and not on Test

1
  • Not only. What about Object.create :D Commented Feb 17, 2017 at 21:09
1

I changed up the names of things, but this should work.

var Person = function(){
    this.message = "Hello, world!";
};

Person.prototype = Object.create(Object.prototype);
Person.prototype.constructor = Person;

Person.prototype.greet = function(){
    console.log(this.message);
    alert(this.message);
}; 

var tom = new Person();
tom.greet();
0

Not the answer you're looking for? Browse other questions tagged or ask your own question.