Jerry Ji
Jerry Ji

Reputation: 386

TypeError: ... is not a function

My JavaScript code in NodeJS results in:

TypeError: ninja.changeName is not a function

Following is my code:

function Ninja(name){
  this.name = name;

  var changeName = function(name2) {
    this.name = name2;
  }
}

var ninja = new Ninja("John");
ninja.changeName("Bob");
console.log(ninja.name);

What's wrong with the code?

Upvotes: 1

Views: 31906

Answers (6)

Clijsters
Clijsters

Reputation: 4256

Another approach to make your function public available would be to first declare it private (Some prefer to use an underscore, like usual in .Net):

 function Ninja(name) {
   this._name = name;

   var _changeName = function(name) {
     this._name = name;
   }
 }

And then export it using return. Some might know this from the classical Java boilerplate Getters and Setters, where fields are declared private by default and Methods make them available:

function Ninja(name) {
    this._name = name;

    var _changeName = function (name) {
        this._name = name;
    }

    return {
        changeName: _changeName,
        getName: function () {return _name;}
    }
}

...And now, use the object:

var ninja = new Ninja("John");
ninja.changeName("Bob");
console.log(ninja.getName());

Upvotes: 0

Manjunath Davanam
Manjunath Davanam

Reputation: 305

function Ninja(name){
      this.name = name;

    return {
     changeName : function(name2) {
        this.name = name2;
     }
   }
}

In your code changeName is not exposed if you want to access the private data you can try with the above snippet

Upvotes: 0

Jim Wright
Jim Wright

Reputation: 6058

You are assigning a function to a variable. This isn't the same as setting a function in the objects prototypal inheritance structure and the variable changeName is only in scope within the context of Ninja.

You can assign the function to this.changeName (important that you're binding to this) like the following:

function Ninja(name){
  this.name = name;

  this.changeName = function(name2) {
    this.name = name2;
  }
}

Or you could use prototypes:

function Ninja(name){
  this.name = name;
}
Ninja.prototype.changeName = function(name2) {
  this.name = name2;
}

Although these approaches look fairly similar, the difference is very important. The first approach creates a new function for every Ninja created. The second approach will use the same function for each object. To look into the reason to use prototypal inheritance, there are various blog posts scattered around the internet.

Upvotes: 3

usmany
usmany

Reputation: 144

You are declaring the changeName as a variable but not binding it with the 'Ninja', So I believe instead of using var, it should this. So the code becomes like this.

function Ninja(name){
this.name = name;

  this.changeName = function(name2) {
    this.name = name2;
  }
}

Hope it helps.

Upvotes: 0

31piy
31piy

Reputation: 23859

var changeName will just create a reference to a function which will be lost once the function is done executing.

You must assign the function as a property of the Ninja function instead:

function Ninja(name) {
  this.name = name;

  this.changeName = function(name2) {
    this.name = name2;
  }
}

var ninja = new Ninja("John");
ninja.changeName("Bob");
console.log(ninja.name);

Upvotes: 8

Suresh Atta
Suresh Atta

Reputation: 121998

var changeName = function(name2) {
    this.name = name2;
  }

You are declaring a function but not attaching that to the object.

It should be

   this.changeName = function(name2) {
    this.name = name2;
  }

So that the property changeName as a function attached to the object.

Upvotes: 3

Related Questions