function myClass(a,b,c) {
this.alertMyName=function(){alert(instancename)}
{...}
}
and then
foo = myClass(a,b,c);
boo = myClass(a,b,c);
foo.alertMyName(); //it should alert 'foo'
boo.alertMyName(); //it should alert 'boo'
In practice I'll need it for class that is creating a lot of html objects to prefix their ID's to differentiate them from same object created by another instance of this class.
I Couldn't find a solution on Stack Overflow so here is a solution I found from ronaldcs on dforge.net:
http://www.dforge.net/2013/01/27/how-to-get-the-name-of-an-instance-of-a-class-in-javascript/
myObject = function () {
this.getName = function () {
// search through the global object for a name that resolves to this object
for (var name in window)
if (window[name] == this)
return name;
};
};
Try it Out:
var o = new myObject();
alert(o.getName()); // alerts "o"
You could bring it in as a parameter:
function myClass(name, a, b, c) {
this.alertMyName = function(){ alert(name) }
}
foo = new myClass('foo', a, b, c);
Or assign it afterwards:
function myClass(a, b, c) {
this.setName = function(name) {
this.name = name;
}
this.alertMyName = function(){
alert(this.name)
}
}
foo = new myClass( a,b,c);
foo.setName('foo');
Further to David's answer, variables in javascript have a value that is either a primitive or a reference to an object. Where the value is a reference, then the thing it references has no idea what the "name" of the variable is.
Consider:
var foo = new MyThing();
var bar = foo;
So now what should foo.alertMyName() return? Or even:
(new MyThing()).alertMyName();
If you want instances to have a name, then give them a property and set its value to whatever suits.
Related
I can get the Class name of the Class with the code below:
function MyClass() {
return 42;
}
var obj = new MyClass();
console.log(obj.constructor.name);
But how to get the name of the variable?
You can't.
Consider:
function MyClass() {
return 42;
}
var obj = new MyClass();
var ob2 = obj;
var ob3 = obj;
There are now three variables all with the same value. Which one would you get if it was possible?
There's no reverse relationship between a variable and its value in JavaScript.
This question defeats itself to a great extent. The use case for this is usually when you scan an object for certain key/value pairs. And even in the event that you want to foster through all global/window variables, you can still do:
for(var obj_name in window) {
if(window.hasOwnProperty && !window.hasOwnProperty(obj_name)) continue;
console.log(obj_name);
if(window[obj_name]) console.log(window[obj_name]);
}
Try this
function MyClass() {
return 42;
}
var obj = new MyClass();
var name = /function (.{1,})\(/;
var results = (name).exec(obj.constructor);
if(results)
{
console.log(results[1])
}
Here is a simple example of what I want :
var ConstBuilder = function() {
var constructor = function() {} ;
constructor.prototype = {} ;
return constructor ;
} ;
ConstBuilder.prototype = {
add : function(name, value) {
this.prototype[name] = value ;
}
} ;
var A = new ConstBuilder() ;
A.add('test', function() {
console.log('test') ;
}) ;
var a = new A() ;
a.test() ;
This code will fail as A is not an instance of ConstBuilder (because A comes from a returned var constructor = function() {} and won't have the methods defined in its prototype (add).
But this would be useful to modify the super constructor's prototype to have things like :
ConstBuilder.prototype.remove = function(name) {
delete this.prototype[name] ;
} ;
A.remove('test') ;
a.test ; // undefined
Is there a way to have a function as an instance of another ? So this function may implicitely "inherit" all the methods defined in its constructor's prototype.
Or if you have other suggestions, I aim to build modulable constructors - as instances with prototypes are.
Please make sure you have understood the difference between the .prototype property and the internal inheritance-prototype.
The code will fail as A is not an instance of ConstBuilder. Is there a way to have a function as an instance of another?
A is, as every constructor needs to be, a Function. So if you just define your add and remove methods on the Function.prototype, it will work:
Function.prototype.add = function(name, value) {
this.prototype[name] = value;
};
Function.prototype.remove = function(name) {
delete this.prototype[name];
};
function A() {}
A.add('test', function(){console.log('test');});
var a = new A();
a.test(); // test
A.remove('test');
a.test; // undefined
There is no possibility however to let a function inherit from something else than Function.prototype - see Can a JavaScript object have a prototype chain, but also be a function?. If you don't want to modify the native Function.prototype object, you still can use the mixin pattern:
var Constr = (function() {
function add(name, value) {
this.prototype[name] = value;
}
function remove(name) {
delete this.prototype[name];
}
return function mixin(c) {
c.add = add;
c.remove = remove;
return c;
};
})();
var A = Constr(function() {…});
A.add("test", …);
var a = new A();
a.test(); // test
I aim to build modulable constructors
You could use the builder pattern, as you just have seem to tried.
function ConstBuilder() {
this.prototype = {};
};
ConstBuilder.prototype = {
add: function(name, value) {
this.prototype[name] = value;
},
remove: function(name) {
delete this.prototype[name];
},
getConstructor: function() {
var constructor = function() {};
constructor.prototype = this.prototype;
this.prototype.constructor = constructor;
return constructor;
}
};
var A = new ConstBuilder().add('test', function() {
console.log('test');
}).getConstructor();
var a = new A();
a.test(); // test
To remove functions later, you would need to save a reference to the builder.
I think that you are looking for an example of how to do JavaScript's "prototypical inheritance". When JavaScript looks for a property on an object, it first checks the object itself. Next it checks the prototype. However, since everything in JavaScript is an object and the prototype is an object
function Root(){}
Root.prototype.fromRoot = function() { console.log("I'm on Root's prototype."); };
function Child(){}
Child.prototype = new Root();
Child.prototype.fromChild = function() { console.log("I'm on Child's prototype."); };
var r = new Root();
var c = new Child();
r.fromRoot(); // works
c.fromRoot(); // works
c.fromChild(); // works
r.fromChild(); // fails
function a (x,y,construct)
{
if (!construct) return;
this.x=x;
this.y=y;
}
a.prototype.methoda=function ()
{
return x+y;
}
function b (x,y,d,e)
{
a.call (this,x,y,true) //--- this would inherit all own Objects and Properties of a and become own properties of b
this.d=d;
this.e=e;
}
b.prototype=new a (); //--- this would only inherit the prototype, construct becomes false and isnt worked through, which if not would result in adding propertiy x and y to prototype instead of directly to instance of b,
b.prototype.constructor=b;
var test=new b (1,2,3,4);
b.methoda ();
second way
function a (x,y)
{
if (arguments.callee.doNotConstruct) return;
this.x=x;
this.y=y;
}
a.prototype.methoda=function ()
{
return x+y;
}
function b (x,y,d,e)
{
a.call (this,x,y) //--- this would inherit all own Objects and Properties of a and become own properties of b
this.d=d;
this.e=e;
}
a.doNotConstruct=true;
b.prototype=new a (); //--- this would only inherit the prototype, construct becomes false and isnt worked through, which if not would result in adding propertiy x and y to prototype instead of directly to instance of b,
a.doNotConstruct=false;
b.prototype.constructor=b;
var test=new b (1,2,3,4);
b.methoda ();
put this in a function
function prototypeInheritance (inheritor,parent)
{
parent.doNotConstruct=true;
inheritor=new parent ();
inheritor.prototype.constructor=inheritor;
inheritor.parent=parent;
parent.doNotConstruct=false;
}
you can call the parent property with (arguments.callee.parent) in the inheritor constructor and you can check doNotConstruct with arguments.callee.doNotConstruct in the parent constructor
I am trying to understand what is going on here:
if (!Object.create) {
Object.create = (function () {
var F = function(){};
return function (o) {
if (arguments.length !== 1) {
throw new Error('Object.create implementation only accepts one parameter.');
}
F.prototype = o;
return new F();
};
}());
}
what does F.prototype mean... How does returning a function work
These are two separate questions. The concept of a prototype and what it means is separate from the concept of returning functions. I will do my best to try and explain.
What does F.prototype mean?
Javascript does not support inheritance in the classical sense, but rather uses prototype inheritance to pass object properties from one function to another.
All Javascript objects contain a prototype field by default. The prototype field is always initially set to the base Object object. (You can create a new instance of Object by doing
var x = new Object() or by doing var x = {}.) You can create objects that set the prototype to another object thereby gaining access to their methods and properties that are placed on the prototype.
Let's walk through an example to illustrate.
Consider you create a constructor to create a Bird object.
function Bird(name) {
var me = this;
this.name = name;
this.flying = false;
this.fly = function() { me.flying = true; };
}
Bird.prototype.fly = function() { this.flying = true; }
Bird.prototype.land = function() { this.flying = false; }
If we look at the details of this object (which you can do using console.dir(obj), or by using Chrome developer tools):
Now consider you want to create another bird object that implements the Object Bird. You would do something like this.
function Duck(name) {
this.name = name;
this.quack = function() {
console.log("quack");
}
}
If you look at the details of this object you see:
Now if you want to make the duck fly, you do not have a method on it yet. You need to set the prototype of Duck to be Bird. You do that by doing something like this:
function Duck(name) {
this.name = name;
this.quack = function() {
console.log("quack");
}
}
Duck.prototype = new Bird();
Now when you look at the details of the object you will see that the prototype is now set to bird.
In short prototypes are used to provide code reuse among objects. Programmers coming from object oriented backgrounds can use prototypes to provide the same mechanisms as inheritance. Mozilla has a good article that goes into more depth.
How does returning a function work?
Javascript is a functional programming language. One of the principles of the functional programming paradigm is the existence function as first class objects. Among other things this means that functions are treated the same as any other object.
A function returning a function means nothing different then a function that returns a string.
function getString() {
return "I am a string";
}
You can use the result of this function in whatever way you choose. A function that returns a function is the same way.
function getFunctionToGetSomethingImportant() {
return function() {
return "I am something important";
}
}
Now when you want to get a function that returns a function that does something important you can do this:
var x = getFunctionToGetSomethingImportant();
x();
Despite these use cases having little value, using functions as first class objects is incredibly valuable. Functions can be treated like other objects which means they can be passed into other functions as parameters (a concept called higher order functions).
function filter(list, function(element) {
return element < 0;
});
The function filter takes as its second parameter a function that takes an element parameter. An implementation of filter would loop through each element in list and apply the function given as the second paramater. This is one example of many important use cases of functions as first class objects. This wiki article contains more information.
Initialy F is empty function and new F() returns empty object, i.e {}
after
F.prototype = o
F as class gets properties of the object o
for example if o={a:1}, then new F() returns {a:1}
this is the same like you define F as
F = function(){
this.a = 1;
}
but in your example you can create new object based on the class of object o passed to the create() function
function dostuff() {
return function () {console.log('hello')}
}
f = dostuff();
f();
--output:--
hello
.
Array.prototype.greet = function() {console.log('hello')};
[1, 2, 3].greet();
--output:--
hello
.
function Dog(name) {
this.name = name;
this.speak = function() {console.log('Ruff, ruff!') };
}
mydog = new Dog("Joey")
console.log(mydog.name);
mydog.speak();
--output:--
Joey
Ruff, ruff!
.
function Dog() {
}
Dog.prototype.speak = function() {console.log("Ruff, ruff!")};
mydog = new Dog();
mydog.speak();
--output:--
Ruff, ruff!
.
function Dog() {
}
var obj = {
name: "Joey",
speak: function() {console.log("Ruff, ruff!")}
}
Dog.prototype = obj;
mydog = new Dog();
console.log(mydog.name);
mydog.speak();
--output:--
Joey
Ruff, ruff!
obj.jump = function() {console.log("Look at me jump!")};
mydog.jump();
--output:--
Look at me jump!
.
var F = function() {
};
var o = {
"greet": function() {console.log('hello')}
};
F.prototype = o;
f = new F();
f.greet();
--output:--
hello
According to Douglas Crockford I could use something like http://javascript.crockford.com/prototypal.html (with a little bit of tweaking)... but I am interested in jQuery way of doing it. Is it good practice using $.extend ?
I have 4 classes :
var A = function(){ }
A.prototype = {
name : "A",
cl : function(){
alert(this.name);
}
}
var D = function(){}
D.prototype = {
say : function(){
alert("D");
}
}
var B = function(){} //inherits from A
B.prototype = $.extend(new A(), {
name : "B"
});
var C = function(){} //inherits from B and D
C.prototype = $.extend(new B(), new D(), {
name : "C"
});
var o = new C();
alert((o instanceof B) && (o instanceof A) && (o instanceof C)); //is instance of A, B and C
alert(o instanceof D); //but is not instance of D
So, i can call every method, property ... from A, B, C and D. Problem comes, when I want to test if o is instance of D? How can I overcome this problem?
Is it good practice using $.extend
$.extend is useful for singletons but for prototypes is not ideal.
Using Object.create (or Crockford's polyfill) you can easily create classes like this. I'm using $.extend to simply process the properties and give them default values and the module pattern to keep it well organized. Hope this helps:
// Helper that makes inheritance work using 'Object.create'
Function.prototype.inherits = function(parent) {
this.prototype = Object.create(parent.prototype);
};
var Person = (function PersonClass() {
var _defaults = {
name: 'unnamed',
age: 0
};
function Person(props) {
$.extend(this, props, _defaults);
}
Person.prototype = {
say: function() {
return 'My name is '+ this.name;
}
};
return Person;
}());
var Student = (function StudentClass(_super) {
Student.inherits(_super); // inherit prototype
var _defaults = {
grade: 'untested'
};
function Student(props) {
_super.apply(this, arguments); // call parent class
$.extend(this, props, _defaults);
}
Student.prototype.say = function() {
return 'My grade is '+ this.grade;
};
return Student;
}(Person));
var james = new Student({ name: 'James', grade: 5 });
console.log(james instanceof Student); // true
console.log(james instanceof Person); // true
An object has only one prototype, so you cannot make it an instance of two other types with one call.
$.extend(new B(), new D(), ... creates an object that is an instance of B. Then all properties of D are copied to the newly created object. But the object will still be an instance of B.
Using $.extend is neither good nor bad per se. But you are bound to jQuery, which makes your code less reusable. And you have to be aware of the fact that $.extend overwrites properties with the same name, which might or might not be what you want.
Is it possible in javascript to have a variable that is not able to access out side the class's functions, but is able to be accessed by classes that inherit it? I.E:
class1 has protected var x = 4;
class2 inherits class1;
class2.prototype.getVar = function(){return /* parent, uber, super, whatever */ this.x;};
var cl2 = new class2();
console.log(cl2.x) // undefined
console.log(cl2.getVar()) // 4
No. Prototypal inheritance is limited to properties of objects.
Variables within the constructor are only available to other code in that variable scope.
You could probably come up with something like...
function cls1() {
var a = 'foo';
this.some_func = function() {
alert(a);
};
}
function cls2() {
cls1.apply(this, arguments);
var cls1_func = this.some_func;
var b = 'bar'
this.some_func = function() {
cls1_func.apply(this, arguments);
alert(b);
};
}
var x = new cls2;
x.some_func(); // alert "foo" alert "bar"
Or to make it more specific to your pseudo code...
function class1() {
var x = 4;
this.getVar = function() {
return x;
};
}
function class2() {
class1.apply(this, arguments);
var cls1_get_var = this.getVar;
this.getVar = function() {
return cls1_get_var.apply(this, arguments);
};
}
class2.prototype = Object.create( class1.prototype );
var cl2 = new class2;
console.log(cl2.x) // undefined
console.log(cl2.getVar()) // 4
I think you need to use a closure to achieve what your trying to do. Something like this:
Class1 = function() {
var x = 4;
return {
getVar: function() {
return x;
}
}
} ();// executes the function immediately and returns an
//an object with one method - getVar. Through closure this method
//still has access to the variable x
Class2 = function() { };// define a constructor function
Class2.prototype = Class1;//have it inherit from Class1
Cl2 = new Class2();//instantiate a new instance of Class2
console.log(Cl2.x);//this is undefined
console.log(Cl2.getVar());//this outputs 4
This is one of the neat things about javascript in that you can achieve the same things in javascript as you would in a class based language without all the extra key words. Douglas Crockford (always good to consult about javascript) explains prototypal inheritance here
Edit:
Just had a second look at your question.If you want newly created methods in your class to access the variable in the base class then you would have to call the getVar method within your own method.Like such:
Class2 = function() {
this.getVar2 = function() {
return this.getVar();
}
};
console.log(Cl2.getVar2()) //outputs 4