TypeError: ... is not a function - javascript

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?

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);

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.

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.

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.

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

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());

Related

How to invoke the method myFunction to return (name) i've tried many ways but it doesn't work

Below is what am talking about
class User {
constructor(name) {
this.name = name;
}
myFunction() {
return function() {
return this.name;
}
}
}
let kk = new User("kk");
let speak = kk.myFunction();
speak();
I'm getting this error:
Uncaught TypeError: Cannot read property 'name' of undefined
You should use this.name instead, and the function should not return a function
class User {
constructor(name) {
this.name = name;
}
myFunction() {
alert(this.name);
return this.name;
}
}
let user = new User("jj").myFunction();
console.log(user)
EDIT:
The question you edited now is different from the original question you posted. This one needs a currying solution:
class User {
constructor(name) {
this.name = name;
}
myFunction() {
let name = this.name;
return function() {
return name;
}
}
}
let kk = new User("kk");
let speak = kk.myFunction();
console.log(speak());
You can use an arrow function (() => {}) which won't have it's own binding of this, instead the this value of the enclosing lexical scope is used (your class in this case).
class User {
constructor(name) {
this.name = name;
}
myFunction() {
return () => this.name;
}
}
const speak = new User("kk").myFunction();
console.log(speak());

Why myObject.function() throwing 'is not a function' error? (trying to learn functional instantiation)

I am trying to create a class using a function and giving it some props and a method. If I do the same thing in C# in class-based way and call the mothod this will work fine but in JS it gives me an error. My question is why it behaves in a different way.
code snippet:
function Animal (name) {
let animal = {}
animal.name = name;
animal.eat = function (){
console.log(`${this.name} is eating`)
}
}
let myAnimal = new Animal('dog');
console.log(myAnimal.eat()); //Uncaught TypeError: myAnimal.eat is not a function at proto.js:11
This would be the prototypical way to achieve that in JavaScript:
function Animal(name) {
this.name = name;
}
Animal.prototype.eat = function() {
console.log(`${this.name} is eating`)
}
new Animal('Pooch').eat();
Or with the introduction of classes (since ECMAScript 2015):
class Animal {
constructor(name) {
this.name = name;
}
eat() {
console.log(`${this.name} is eating`)
}
}
new Animal('Pooch').eat();
well if Animal is going to act as a constructor of your sort of class, then you would need to write it like a proper constructor, i.e. drop the let animal = {} bit, and just set properties on this:
function Animal (name) {
this.name = name;
this.eat = function (){
console.log(`${this.name} is eating`)
}
}
let myAnimal = new Animal('dog');
myAnimal.eat();
now this approach has the downside of creating a new function eat() for each instance of Animal instead of binding an existing function eat() to each instance, which is what happens normally with classes. that you can achieve by this:
function Animal (name) {
this.name = name;
}
Animal.prototype.eat = function (){
console.log(`${this.name} is eating`)
}
let myAnimal = new Animal('dog');
myAnimal.eat();
which is actually the proper way people used to define classes in javascript before class was introduced.
however, you can also drop the whole class-like concept, and just have an Animal() function that gives out an object with desired properties:
function Animal (name) {
let animal = {};
animal.name = name;
animal.eat = function (){
console.log(`${this.name} is eating`)
}
return animal;
}
let myAnimal = Animal('dog');
myAnimal.eat();
note how in this approach you have let myAnimal = Animal('dog') instead of let myAnimal = new Animal('dog'), as Animal() is no longer a constructor.
reminder: this is an explanation of how you can instantiate objects with a function, and by no means the recommended way of defining classes in javascript. in older environments, the prototype approach is the recommended way, for newer environments, just use class.
Go with Robby's approach above. For correcting your code, you missed a statement return animal; :)
function Animal (name) {
let animal = {}
animal.name = name;
animal.eat = function (){
console.log(`${this.name} is eating`)
}
return animal;
}
let myAnimal = new Animal('dog');
console.log(myAnimal.eat());

Javascript Object.Prototype vs Object.anything

I'm trying to wrap my head around the JavaScripts prototype object and after some testing I saw that setting Object.prototype to parent Object.prototype or setting it to parent Object.a can seemingly yield the same results.
Below is some code to explain this better.
function Person(name) {
this.name = name;
}
Person.a = {};
Person.a.getName = function(){
return this.name;
}
Person.prototype.getName = function(){
return this.name;
}
function Male(name) {
this.gender = "male";
this.name = name;
return this;
}
function Female(name) {
this.gender = 'female';
this.name = name;
return this;
}
Male.prototype = Person.a;
Female.prototype = Person.prototype;
var m = new Male("levi");
var f = new Female("cho");
f.getName(); //cho
m.getName(); //levi
I think I'm missing a main component of how the prototype object works but I'm not sure what.
Any help would be really greatly appreciated.

JavaScript Callback/this confusion with require.js / objects

I try to use the following structure in my app: https://gist.github.com/jonnyreeves/2474026
I try to register some callback inside my constructor. I made an example using jquery, actually it's leaflet maps, but the difference shouldn't matter.
function Person() {
this.name = "abc";
$("#something").onSomeEvent(function() {
this.name = "cde";
});
}
How do I properly reference my object-property name, inside the callback?
You can use something like this:
function Person() {
this.name = "abc";
$("#something").onSomeEvent(function() {
this.name = "cde";
}.bind(this));
}
function Person() {
var self = this;
self.name = "abc";
$("#something").onSomeEvent(function() {
//this is right if you need
self.name = "cde";
});
}
you can use $('#someting') with right this.
if you use bind to solve the problem,in the callback this is wrong.
Use bind, which is not supported in older IEs, or jquerys proxy
function Person() {
this.name = "abc";
$("#something").onSomeEvent(function() {
this.name = "cde";
}.bind(this));
}
function Person() {
this.name = "abc";
$("#something").onSomeEvent($.proxy(function() {
this.name = "cde";
},this));
}

Working with javascript prototype inheritance

Why does this work....
function Person(name) {
this.name = name;
}
Person.prototype.speak = function() {
alert(this.name);
}
var person = new Person("fred");
person.speak();
But not this..
function Person(name) {
this.name = name;
speak = function() {
alert(this.name);
}
var person = new Person("fred");
person.speak();
I am not understanding how inheritance works, or the javascript "prototype-chain".
Thanks.
function Person(name) {
this.name = name;
speak = function() {
alert(this.name);
}
should be
function Person(name) {
this.name = name;
this.speak = function () {
alert(this.name);
};
}
Actually it's variable scope that you're not understanding.
function Person(name) {
this.name = name;
speak = function() {
alert(this.name);
}
}
By omitting var before speak = ... here you've created a global variable named speak, not a variable within Person's scope. In a browser global variables are attached to the global object, window, so your code is equivalent to:
function Person( name ) {
this.name = name;
window.speak = function() { alert( this.name ); }
}
Douglas Crockford has written some related material about variable scope in prototypal inheritance that you should find enlightening.

Categories

Resources