Get class methods from a javascript function - javascript

Let's say I have a function, and I need to check if it has a class method of a certain name. For example:
function Foo() {
this.bar = function() {
console.log("I am bar!");
}
}
And I want to check if the Foo class actually has the bar method.
I can create a new instance of Foo and then check it, I was just wondering if there was a better way to do this.

I can create a new instance of Foo and then check it, I was just wondering if there was a better way to do this.
No, not if the method is added in the constructor as in your example. There's nothing to check until you create an instance. (Well, except the source code of the constructor function, as Pointy points out in a comment.)
If it were defined on Foo.prototype, it would be a different matter:
function Foo() {
}
Foo.prototype.bar = function() {
console.log("I am bar!");
};
Then you could check by looking for Foo.prototype.bar.
Side note: Calling them "class methods" is likely to confuse people. In class-based OOP, a "class method" is usually one that's not specific to instances, as opposed to being one that's specific to instances but defined by the class. And of course, JavaScript doesn't have class-based OOP (it has prototypical OOP instead, even as of ES6 which adds more class-like trappings).

There is no method until you do:
var x = new Foo();
So, you will have to do that and then test:
if (typeof x.bar === "function")
If your code was using the prototype for the bar method, then you could test the prototype directly without constructing an object, but since the method is only created inside the constructor, you have to run the constructor in order to see it.

TJ Crowder is correct in that you cannot examine the constructor to examine if the "class" Foo has a certain method. However, you can do this:
function Foo() { /* Constructor */ }
Foo.prototype.bar = function() { /* Whatever you want */ }
Then to test, you can simply do typeof Foo.prototype.bar === "function".
There are various advantages and disadvantages to this approach. (See Use of 'prototype' vs. 'this' in JavaScript?). If you really need to test if a certain constructor's instances will inherit a method, you can use the prototype approach.

Related

When to use Object.prototype / JavaScript instance methods

JavaScript defines Object.prototype as a way to define methods or properties for class-like objects.
A big problem that exists when using Object.prototype is the incorrect behavior when a method is invoked via a callback as this will have the invoking context.
function Foo() {}
Foo.prototype.resize() {
console.log(this);
}
var foo = new Foo();
window.on('resize', foo.resize);
So to work around this limitation we can do the following.
function Foo2() {
function resize() {
console.log(self);
}
var self = this;
this.resize = resize;
}
var foo2 = new Foo2();
window.on('resize', foo2.resize);
Given the above situation, it seems like it's better to always define class-like objects in example 2.
Thus, when should we use the Object.prototype facilities? I mean, you cannot know a priori how your methods will be called, and most certainly you would want the correct this context reference when invoked.
Supporting context: I thought of this question as it seems like you are creating instance methods using Object.prototype. However, as illustrated, you are not. You are simply creating methods that have no "real" connection to their instance. Hence the need to use closure to create an instance-bound method. Furthermore, this question was thought of after reading this excellent explanation of this.
Your confusion comes from the fact that you view JavaScript objects as having methods like in OOP languages. And so you believe they should have fixed context, since methods in OOP languages usually use "early binding" and so they are bound to the correct context. It's different in JavaScript. It's sort of "late binding", when the context of the function - this - is determined when the function is executed. To me, it's beneficial to see methods as simply object properties pointing to a function, that indeed can be executed in different contexts. For example, we could have something like this:
function resize() {
console.log(this);
}
resize.call(window);
resize.call(custom);
If you want, certainly you can achieve "early binding" using bind for example:
function O() {
this.resize = function() {}.bind(this);
}
var o = new O();
But that limits re-usability of the object methods. For example, this wouldn't be possible:
Array.prototype.slice.call(arguments)
You can read here for some suggestions on why methods are not bound even in ES6.
Prototypes are not static methods, they are created to enable memory efficient code reuse. As JLRishe pointed out, the biggest advantage of prototypes is memory usage reduction, since you can define one instance of a function on prototype, and have convenient access to it as object property that have the prototype in their prototype chain. But the prototype is just for convenience. Here is the example with resize without prototype:
// here only one instance of `resize` function is created
function resize() {
console.log(this);
}
var o1 = {
resize: resize
}
var o2 = {
resize: resize
}
You are simply creating methods that have no "real" connection to
their instance.
Correct, here is the example of a prototype with "methods" later to be used with different contexts:
var prototype = {
resize: function() {
console.log(this);
}
}
var o1 = {
resize: resize
}
Object.setPrototypeOf(o1, prototype);
var o2 = {
resize: resize
}
Object.setPrototypeOf(o2, prototype);
I think JavaScript was built with idea in mind that functions are first-class objects, not that objects should have methods with correctly bound context.
Static methods are usually implemented as properties on function constructors, like this:
function SomeObjectConstructor() {}
SomeObjectConstructor.someStaticMethod = function() {}
I think that directly binding an object's method to an event handler, while possible, is a shortcut you want to avoid.
window.on('resize', function () {
foo.resize();
});
Even though it's more verbose, I think writing your handlers like this is clearer and wont affect the context of this in your Object.prototype methods.
As stated in one of the comments, using the object's prototype is more efficient than defining methods for each instance of your object.

What harm can omitting prototype.constructor cause when inheriting? [duplicate]

Trying to bend by head around Javascript's take on OO...and, like many others, running into confusion about the constructor property. In particular, the significance of the constructor property, as I can't seem to make it have any effect. E.g.:
function Foo(age) {
this.age = age;
}
function Bar() {
Foo.call(this, 42);
this.name = "baz";
}
Bar.prototype = Object.create(Foo.prototype);
var b = new Bar;
alert(b.constructor); // "Foo". That's OK because we inherit `Foo`'s prototype.
alert(b.name); // "baz". Shows that Bar() was called as constructor.
alert(b.age); // "42", inherited from `Foo`.
In the above example, the object b seems to have had the right constructor called (Bar) – and it inherits the age property from Foo. So why do many people suggest this as a necessary step:
Bar.prototype.constructor = Bar;
Clearly, the right Bar constructor was called when constructing b, so what impact does this prototype property have? I am curious to know what practical difference it actually makes to have the constructor property set 'correctly'—as I can't see it having any affect on which constructor is actually called after an object is created.
Step one is to understand what constructor and prototype are all about. It's not difficult, but one has to let go of "inheritance" in the classical sense.
The constructor
The constructor property does not cause any particular effects in your program, except that you can look at it to see which function was used in conjunction with the operator new to create your object. If you typed new Bar() it will be Bar and you typed new Fooit will be Foo.
The prototype
The prototype property is used for lookup in case the object in question does not have the property asked for. If you write x.attr, JavaScript will try to find attr among x's attributes. If it cant find it, it will look in x.__proto__. If it's not there either, it will look in x.__proto__.__proto__ and so on as long as __proto__ is defined.
So what is __proto__and what has it got to do with prototype? Shortly put, prototype is for "types" while __proto__ is for "instances". (I say that with quotation marks because there's not really any difference between types and instances). When you write x = new MyType(), what happens (among other things) is that x.__proto___ is set to MyType.prototype.
The question
Now, the above should be all you need to derive what your own example means, but to try and answer your actual question; "why write something like":
Bar.prototype.constructor = Bar;
I personally have never seen it and I find it a little silly, but in the context you've given it will mean that the Bar.prototype-object (created by using new Foo(42)) will pose as have being created by Bar rather than Foo. I suppose the idea is some make something similar to C++/Java/C#-like languages where a type-lookup (the constructor property) will always yield the most specific type rather than the type of the more generic object further up in the prototype-chain.
My advice: don't think very much about "inheritance" in JavaScript. The concepts of interfaces and mixins makes more sense. And don't check objects for their types. Check for the required properties instead ("if it walks like a duck and quacks like a duck, it's a duck").
Trying to force JavaScript into a classical inheritance model, when all that it has is the prototype-mechanism as described above, is what causes the confusion. The many people that suggested to manually set the constructor-property probably tried to do just that. Abstractions are fine, but this manual assignment of the constructor property is not very idiomatic usage of JavaScript.
September 2020 Update
The answer below is from the days of ECMAScript 3 and the first sentence is no longer true because since ECMAScript 6, the constructor property is used in a few places. However, I think the overall gist still applies. Thanks to T. J. Crowder for pointing that out in the comments, and please read his answer for a fuller picture of the current situation.
Original answer
The constructor property makes absolutely no practical difference to anything internally. It's only any use if your code explicitly uses it. For example, you may decide you need each of your objects to have a reference to the actual constructor function that created it; if so, you'll need to set the constructor property explicitly when you set up inheritance by assigning an object to a constructor function's prototype property, as in your example.
one case to use constructor:
this is one of the common realization of inheritance:
Function.prototype.extend = function(superClass,override) {
var f = new Function();
f.prototype = superClass.prototype;
var p = this.prototype = new f();
p.constructor = this;
this.superclass = superClass.prototype;
...
};
this new f() would not call the constructor of superClass,so when you create a subClass,maybe you need call the superClass at first,like this:
SubClass = function() {
SubClass.superClass.constructor.call(this);
};
so the constructor property make sense here.
The previous answers here say (in various ways) that the value of the constructor property isn't used by anything in JavaScript itself. That was true when those answers were written, but ES2015 and onward have started using constructor for things.
The constructor property of the prototype property of a function is meant to point back to the function so that you can ask an object what constructed it. It's set up automatically as part of creating a traditional function object or a class constructor object (details).
function TraditionalFunction() {
}
console.log(TraditionalFunction.prototype.constructor === TraditionalFunction); // true
class ExampleClass {
}
console.log(ExampleClass.prototype.constructor === ExampleClass); // true
Arrow functions don't have a prototype property, so they don't have prototype.constructor.
For years the JavaScript specification only said that the constructor property would be there and have that value (a link back to the function) by default. But starting in ES2015, that changed, and various operations in the specification now actually use the constructor property, such as this, this, this, and this.
So when setting up constructor functions that build inheritance chains, it's best to ensure that the constructor property is referring to the appropriate function. See my answer here for examples, etc.
One of the use cases when you would want the prototype.constructor property to survive prototype property reassignment is when you define a method on the prototype that produces new instances of the same type as the given instance. Example:
function Car() { }
Car.prototype.orderOneLikeThis = function() { // Clone producing function
return new this.constructor();
}
Car.prototype.advertise = function () {
console.log("I am a generic car.");
}
function BMW() { }
BMW.prototype = Object.create(Car.prototype);
BMW.prototype.constructor = BMW; // Resetting the constructor property
BMW.prototype.advertise = function () {
console.log("I am BMW with lots of uber features.");
}
var x5 = new BMW();
var myNewToy = x5.orderOneLikeThis();
myNewToy.advertise(); // => "I am BMW ..." if `BMW.prototype.constructor = BMW;` is not
// commented; "I am a generic car." otherwise.
The constructor property points to the constructor that was used to create the object instance. If you typed 'new Bar()' it will be 'Bar' and you typed 'new Foo()' it will be 'Foo'.
But if you set the prototype without setting the constructor, you would get something like this:
function Foo(age) {
this.age = age;
}
function Bar() {
this.name = "baz";
}
Bar.prototype = new Foo(42);
var one = new Bar();
console.log(one.constructor); // 'Foo'
var two = new Foo();
console.log(two.constructor); // 'Foo'
To set the constructor actually to the constructor that was used to create the object, we need to set the constructor as well while setting prototype as follows:
function Foo(age) {
this.age = age;
}
function Bar() {
this.name = "baz";
}
Bar.prototype = new Foo(42);
Bar.prototype.constructor = Bar;
var one = new Bar();
console.log(one.constructor); // 'Bar'
var two = new Foo();
console.log(two.constructor); // 'Foo'

Will defining functions within the constructor consume more memory than attaching it to prototype?

This would presumably be the safest way (Case A):
var myClass = function() { };
myClass.prototype = {
doSomething : function() { alert('Something'); }
};
This is the alternative (Case B):
var myClass = function() {
this.doSomething = function() { alert('Something'); };
};
I'm under the impression that by doing this as shown in Case B, doSomething would be a member, and the function would be defined once for each myClass object I instantiate so that it will exist 100 times in memory for 100 instances, whereas in Case A the function will only exist in one place in memory and different instances will merely reference the prototype.
Am I understanding this correctly?
As a bonus question: When doing it as in Case B, chrome developer gives me intellisense for doSomething, but I must expand __proto__ for an instance to see it. How come it doesn't show up on the object itself? That is, why doesn't prototype members show on the object, but get stuck back down on __proto__? I would have preferred if the __proto__ stack would get flattened and show up on the object directly. Is there another Case that will allow this to happen?
Firstly, in case B, you are merely creating a global function, not attaching it to the instance. You meant:
this.doSomething = function() { }
Secondly, the first will be faster. Though I can't find the link now, jQuery honcho John Resig did a detailed blog post on this showing speed tests on prototypal inheritance of methods vs. methods declared on the instance. Inheritance was notably faster.
In terms of ethos, I've always much favoured inheritance. This is the place for reusable, cross-instance functionality. Adding it to each instance has the sole benefit of allowing you to declare methods inside a single, convenient closure, in your constructor, but that's it.
If this is your reason for liking pattern B, it's possible to do this whilst still a) having the methods inherited; b) not redeclaring them at every instantiation.
function SomeClass() {
if (!SomeClass.prototype.someMethod) {
SomeClass.prototype.someMethod = function() {}
}
}
This will slightly slow down the initial instantiation, though, as it is responsible for setting up the prototype - not really the job of an instantiation process.
There is also a programmatical difference to be aware of between your two cases:
function SomeClass(name) {}
SomeClass.prototype.someMethod = function() {};
var instance = new SomeClass();
console.log(!!instance.someMethod); //true
console.log(instance.hasOwnProperty('someMethod')); //false
The last line is false because the method is inherited, not owned by the instance. With your pattern B, this will resolve to true.
Correct: defining methods in the prototype will create 1 function object, and every instance will reference that 1 function. Defining it in the constructor creates a new function for each instance
Your code needs some work. The way you're defining the constructor, the doSomething function is defined as a global add var to counter that. This still doesn't set doSomething as a property though, it's just a function declared within the scope of the constructor (closure). This is why it doesn't show up in your instance as a method: the function is not attached to this, but even when fix this issue like so, you're still creating new function objects for each instance:
function MyConstructor()//capitalize constructors - conventions are important
{
var someMethod = function(){/*..*/};
this.someMethod = someMethod;
}
Utkanos pointed out what the implications of inheritance and prototype methods are (.hasOwnProperty), and he's absolutely right in that respect (+1). I'd just like to add that the hasOwnProperty method returning false is a trivial matter. Generally speaking, when iterating over an object, and checking which properties and methods are set, and which are not. What you want in most cases are properties, not the methods. So it's in fact better to set them at the prototype level:
for(var name in obj)
{
if (obj.hasOwnProperty(name))
{
//do stuff, here the methods are set # prototype level
}
if (obj.hasOwnPrototype(name) && typeof obj[name] !== 'function')
{
//same stuff, but requires extra check when methods are assigned by constructor
}
}

What is the significance of the Javascript constructor property?

Trying to bend by head around Javascript's take on OO...and, like many others, running into confusion about the constructor property. In particular, the significance of the constructor property, as I can't seem to make it have any effect. E.g.:
function Foo(age) {
this.age = age;
}
function Bar() {
Foo.call(this, 42);
this.name = "baz";
}
Bar.prototype = Object.create(Foo.prototype);
var b = new Bar;
alert(b.constructor); // "Foo". That's OK because we inherit `Foo`'s prototype.
alert(b.name); // "baz". Shows that Bar() was called as constructor.
alert(b.age); // "42", inherited from `Foo`.
In the above example, the object b seems to have had the right constructor called (Bar) – and it inherits the age property from Foo. So why do many people suggest this as a necessary step:
Bar.prototype.constructor = Bar;
Clearly, the right Bar constructor was called when constructing b, so what impact does this prototype property have? I am curious to know what practical difference it actually makes to have the constructor property set 'correctly'—as I can't see it having any affect on which constructor is actually called after an object is created.
Step one is to understand what constructor and prototype are all about. It's not difficult, but one has to let go of "inheritance" in the classical sense.
The constructor
The constructor property does not cause any particular effects in your program, except that you can look at it to see which function was used in conjunction with the operator new to create your object. If you typed new Bar() it will be Bar and you typed new Fooit will be Foo.
The prototype
The prototype property is used for lookup in case the object in question does not have the property asked for. If you write x.attr, JavaScript will try to find attr among x's attributes. If it cant find it, it will look in x.__proto__. If it's not there either, it will look in x.__proto__.__proto__ and so on as long as __proto__ is defined.
So what is __proto__and what has it got to do with prototype? Shortly put, prototype is for "types" while __proto__ is for "instances". (I say that with quotation marks because there's not really any difference between types and instances). When you write x = new MyType(), what happens (among other things) is that x.__proto___ is set to MyType.prototype.
The question
Now, the above should be all you need to derive what your own example means, but to try and answer your actual question; "why write something like":
Bar.prototype.constructor = Bar;
I personally have never seen it and I find it a little silly, but in the context you've given it will mean that the Bar.prototype-object (created by using new Foo(42)) will pose as have being created by Bar rather than Foo. I suppose the idea is some make something similar to C++/Java/C#-like languages where a type-lookup (the constructor property) will always yield the most specific type rather than the type of the more generic object further up in the prototype-chain.
My advice: don't think very much about "inheritance" in JavaScript. The concepts of interfaces and mixins makes more sense. And don't check objects for their types. Check for the required properties instead ("if it walks like a duck and quacks like a duck, it's a duck").
Trying to force JavaScript into a classical inheritance model, when all that it has is the prototype-mechanism as described above, is what causes the confusion. The many people that suggested to manually set the constructor-property probably tried to do just that. Abstractions are fine, but this manual assignment of the constructor property is not very idiomatic usage of JavaScript.
September 2020 Update
The answer below is from the days of ECMAScript 3 and the first sentence is no longer true because since ECMAScript 6, the constructor property is used in a few places. However, I think the overall gist still applies. Thanks to T. J. Crowder for pointing that out in the comments, and please read his answer for a fuller picture of the current situation.
Original answer
The constructor property makes absolutely no practical difference to anything internally. It's only any use if your code explicitly uses it. For example, you may decide you need each of your objects to have a reference to the actual constructor function that created it; if so, you'll need to set the constructor property explicitly when you set up inheritance by assigning an object to a constructor function's prototype property, as in your example.
one case to use constructor:
this is one of the common realization of inheritance:
Function.prototype.extend = function(superClass,override) {
var f = new Function();
f.prototype = superClass.prototype;
var p = this.prototype = new f();
p.constructor = this;
this.superclass = superClass.prototype;
...
};
this new f() would not call the constructor of superClass,so when you create a subClass,maybe you need call the superClass at first,like this:
SubClass = function() {
SubClass.superClass.constructor.call(this);
};
so the constructor property make sense here.
The previous answers here say (in various ways) that the value of the constructor property isn't used by anything in JavaScript itself. That was true when those answers were written, but ES2015 and onward have started using constructor for things.
The constructor property of the prototype property of a function is meant to point back to the function so that you can ask an object what constructed it. It's set up automatically as part of creating a traditional function object or a class constructor object (details).
function TraditionalFunction() {
}
console.log(TraditionalFunction.prototype.constructor === TraditionalFunction); // true
class ExampleClass {
}
console.log(ExampleClass.prototype.constructor === ExampleClass); // true
Arrow functions don't have a prototype property, so they don't have prototype.constructor.
For years the JavaScript specification only said that the constructor property would be there and have that value (a link back to the function) by default. But starting in ES2015, that changed, and various operations in the specification now actually use the constructor property, such as this, this, this, and this.
So when setting up constructor functions that build inheritance chains, it's best to ensure that the constructor property is referring to the appropriate function. See my answer here for examples, etc.
One of the use cases when you would want the prototype.constructor property to survive prototype property reassignment is when you define a method on the prototype that produces new instances of the same type as the given instance. Example:
function Car() { }
Car.prototype.orderOneLikeThis = function() { // Clone producing function
return new this.constructor();
}
Car.prototype.advertise = function () {
console.log("I am a generic car.");
}
function BMW() { }
BMW.prototype = Object.create(Car.prototype);
BMW.prototype.constructor = BMW; // Resetting the constructor property
BMW.prototype.advertise = function () {
console.log("I am BMW with lots of uber features.");
}
var x5 = new BMW();
var myNewToy = x5.orderOneLikeThis();
myNewToy.advertise(); // => "I am BMW ..." if `BMW.prototype.constructor = BMW;` is not
// commented; "I am a generic car." otherwise.
The constructor property points to the constructor that was used to create the object instance. If you typed 'new Bar()' it will be 'Bar' and you typed 'new Foo()' it will be 'Foo'.
But if you set the prototype without setting the constructor, you would get something like this:
function Foo(age) {
this.age = age;
}
function Bar() {
this.name = "baz";
}
Bar.prototype = new Foo(42);
var one = new Bar();
console.log(one.constructor); // 'Foo'
var two = new Foo();
console.log(two.constructor); // 'Foo'
To set the constructor actually to the constructor that was used to create the object, we need to set the constructor as well while setting prototype as follows:
function Foo(age) {
this.age = age;
}
function Bar() {
this.name = "baz";
}
Bar.prototype = new Foo(42);
Bar.prototype.constructor = Bar;
var one = new Bar();
console.log(one.constructor); // 'Bar'
var two = new Foo();
console.log(two.constructor); // 'Foo'

What's the recommended way to declare fields of a class in JavaScript?

Is it better to declare fields of a class in this way:
function MyClass() {
this.aMethod = function() {
// code
}
}
Or this way:
function MyClass() {
}
MyClass.prototype.aMethod = function() {
// code
}
Any why?
Thanks in advance.
The prototypal method, because it's more efficient as it adds the function to the prototype meaning any objects created with the constructor automatically get that method, while the former/first way those methods have to be created for each and every little object you make individually.
Though really it depends on what you're doing with the method. If you don't need it to be a public method then you may opt with this.method or a function statement.
As #meder said, the prototypal approach is the preferred way, since the the methods are declared in the constructor's prototype, but the first approach you show us is useful to implement private members, for example:
function MyClass() {
var privateValue = 'secret';
function privateMethod() { }
this.aMethod = function() {
// privateValue and privateMethod are accessible here.
return privateValue;
}
}
var foo = new MyClass();
foo.aMethod(); // "secret"
foo.privateValue; // undefined !
That's what Crockford calls a privileged method, because this method has access to all the identifiers created in the lexical scope of the constructor (a closure is created).
It depends on the usage. Use the first method when you are going to use the method frequently; the second, when you are going to make rare use of it. The reason is that when the object is created with the constructor, prototypal methods are not loaded, they are only loaded when called, which will save you some performance.

Categories

Resources