First of all, I don't want to add methods to Function.prototype. Doing that would make them available for all functions and that's not what I'm looking for.
In JavaScript you can create objects with custom prototypes like this:
function CustomObj() {}
CustomObj.prototype = {};
CustomObj.prototype.sayFoo = function () { return 'foo' };
var myCustomObj = new CustomObj(); //=> returns an object: {}
myCusomObj.sayFoo(); //=> 'foo'
You can also create array-like objects with custom prototypes like this:
function CustomArr() {}
CustomArr.prototype = [];
CustomObj.prototype.sayFoo = function () { return 'foo' };
var myCustomArr = new CustomArr(); //=> returns an ordered object: []
myCustomArr.sayFoo(); //=> 'foo'
What I'd like to do is use some kind of constructor to create a function with its own custom prototype in the same way. However, the following does not work:
function CustomFn() {}
CustomFn.prototype = function () {};
CustomFn.prototype.sayFoo = function () { return 'foo' };
var myCustomFn = new CustomFn(); //=> PROBLEM! returns an object: {}
myCustomFn.sayFoo(); //=> 'foo'
// ^^ Here, the prototype was applied but the output was not a function.
myCustomFn(); //=> TypeError: object is not a function
So is there any way to accomplish what I'm trying to do?
UPDATE
Maybe there's another way I could be asking this question that would make it a little clearer.
There's a problem with the idea of a closure:
function makeFn() {
var output = function () { /* do some stuff */ };
output.foo = function () { /* do some stuff */ };
return output;
}
var specialFn = makeFn();
Essentially, this technique gives me what I want. However, the problem is that every time I call makeFn, output.foo has to be created as a totally independent function that takes up its own memory. Gross. So I could move that method out of the closure:
var protoMethods = {
"foo" : function () { /* do some stuff */ }
};
function makeFn() {
var output = function () { /* do some stuff */ };
for (var i in protoMethods) {
Object.prototype.hasOwnProperty.call(protoMethods, i) &&
(output[i] = protoMethods[i]);
}
return output;
}
var specialFn = makeFn();
But now I have to manually do an iteration every time I call makeFn which would be less efficient than if I could just assign protoMethods to be the prototype of output. So, with this new update, any ideas?
It is a tricky thing indeed, more complicated than it should be if the language was designed well...
Basically, you just can't do it cleanly in current versions. Objects other than functions can not be callable.
In future Javascript versions, you can do it with a "proxy" object that can define a "call" handler. But it is still way too complicated and contrived in my opinion.
Another way to go about it is to make your object a real function, not a custom object. Then try to set its __proto__, which is non-standard yet but works in most modern browsers, except Opera and IE 8 or less. Also maybe set its constructor property for faking instanceof checks... such hacks are quite tricky though and results will vary a lot with environments.
The following example works fine on my Firefox:
http://jsfiddle.net/Q3422/2/
function MyFun() {
if (!this || this==window) {
return new MyFun();
}
var f = function() {
return "thanks for calling!";
}
f.__proto__ = MyFun.prototype;
f.constructor = MyFun;
return f;
}
MyFun.prototype = {
foo: function() {
return "foo:" + this();
},
__proto__: Function.prototype
};
var f = new MyFun();
alert("proto method:"+f.foo()); // try our prototype methods
alert("function method:"+f.call()); // try standard function methods
alert("function call:"+f()); // try use as a function
alert('typeof:' + typeof f); // "function", not "object". No way around it in current js versions
alert('is MyFun:' + (f instanceof MyFun)); // true
alert('is Function:' + (f instanceof Function)); // true
Just wanted to add that you should not be worried about "copying" functions to each instance of your objects. The function itself is an object, so is never really copied, nor is it recompiled or anything. It does not waste memory, except for the function object reference itself and any closure variables.
Iterating over the prototype to copy it should not concern you as well, I guess you will not have a gazillion methods.
So your own last solution is probably the best if you need to support environments where proto is not settable, and you are not worried that your prototype might get extended after some objects already got created and they may not pick up the changes.
You're at the heart of what inheritance in JavaScript is all about. Yes, since prototypes are objects, you'll want to set the prototype of CustomFn to an object instead of a function.
But that object can come from another function:
function ParentFn() {}
function CustomFn() {}
CustomFn.prototype = Object.create(ParentFn.prototype);
CustomFn.prototype.sayFoo = fun ...
If you don't have ES5 or a polyfill:
CustomFn.prototype = (function() {
function F(){}
F.prototype = ParentFn.prototype;
return new F();
}());
Some may tell you just to do the following but the above way is better:
CustomFn.prototype = new ParentFn();
I tried that too, when working on V library. I wanted to override the Function constructor to enforce a restricted syntax of constructor functions, that I'm calling "class functions" (and I'm confident to do so).
Answer is no, using the new operator you can only create new "object"s, but not new "function object"s.
However you can use a constructor function both as a constructor and as a function!
var CustomFn = function () {
if (this instanceof CustomFn) {
// here we are 'new CustomFn()'
}
else {
// here we are 'CustomFn()' or 'CustomFn.call()'
}
};
Or as I believe is the better concept, to do the function in first place and then let the constructor go:
var CustomFn = function () {
if (!(this instanceof CustomFn)) { // functioning
// here we are 'CustomFn()' or 'CustomFn.call()'
return new CustomFn(); // or return undefined or throw
}
// constructing
// here we are 'new CustomFn()'
// BaseCustomFn.call(this);
};
With respect to JS, what's the difference between the two? I know methods are associated with objects, but am confused what's the purpose of functions? How does the syntax of each of them differ?
Also, what's the difference between these 2 syntax'es:
var myFirstFunc = function(param) {
//Do something
};
and
function myFirstFunc(param) {
//Do something
};
Also, I saw somewhere that we need to do something like this before using a function:
obj.myFirstFunc = myFirstFunc;
obj.myFirstFunc("param");
Why is the first line required, and what does it do?
Sorry if these are basic questions, but I'm starting with JS and am confused.
EDIT: For the last bit of code, this is what I'm talking about:
// here we define our method using "this", before we even introduce bob
var setAge = function (newAge) {
this.age = newAge;
};
// now we make bob
var bob = new Object();
bob.age = 30;
// and down here we just use the method we already made
bob.setAge = setAge;
To answer your title question as to what is the difference between a 'function' and a 'method'.
It's semantics and has to do with what you are trying to express.
In JavaScript every function is an object. An object is a collection of key:value pairs. If a value is a primitive (number, string, boolean), or another object, the value is considered a property. If a value is a function, it is called a 'method'.
Within the scope of an object, a function is referred to as a method of that object. It is invoked from the object namespace MyObj.theMethod(). Since we said that a function is an object, a function within a function can be considered a method of that function.
You could say things like “I am going to use the save method of my object.” And "This save method accepts a function as a parameter.” But you generally wouldn't say that a function accepts a method as a parameter.
Btw, the book JavaScript Patterns by Stoyan Stefanov covers your questions in detail, and I highly recommend it if you really want to understand the language. Here's a quote from the book on this subject:
So it could happen that a function A, being an object, has properties and methods, one of which happens to be another function B. Then B can accept a function C as an argument and, when executed, can return another function D.
There is a slight difference -
Method : Method is a function when object is associated with it.
var obj = {
name : "John snow",
work : function someFun(paramA, paramB) {
// some code..
}
Function : When no object is associated with it , it comes to function.
function fun(param1, param2){
// some code...
}
Many answers are saying something along the lines that a method is what a function is called when it is defined on an object.
While this is often true in the way the word is used when people talk about JavaScript or object oriented programming in general (see here), it is worth noting that in ES6 the term method has taken on a very specific meaning (see section 14.3 Method Definitions of the specs).
Method Definitions
A method (in the strict sense) is a function that was defined through the concise method syntax in an object literal or as a class method in a class declaration / expression:
// In object literals:
const obj = {
method() {}
};
// In class declarations:
class MyClass {
method() {}
}
Method Specificities
This answer gives a good overview about the specificities of methods (in the strict sense), namely:
methods get assigned an internal [[HomeObject]] property which allows them to use super.
methods are not created with a prototype property and they don't have an internal [[Construct]] method which means that they cannot be called with new.
the name of a method does not become a binding in the method's scope.
Below are some examples illustrating how methods (in the strict sense) differ from functions defined on objects through function expressions:
Example 1
const obj = {
method() {
super.test; // All good!
},
ordinaryFunction: function ordinaryFunction() {
super.test; // SyntaxError: 'super' keyword unexpected here
}
};
Example 2
const obj = {
method() {},
ordinaryFunction: function ordinaryFunction() {}
};
console.log( obj.ordinaryFunction.hasOwnProperty( 'prototype' ) ); // true
console.log( obj.method.hasOwnProperty( 'prototype' ) ); // false
new obj.ordinaryFunction(); // All good !
new obj.method(); // TypeError: obj.method is not a constructor
Example 3
const obj = {
method() {
console.log( method );
},
ordinaryFunction: function ordinaryFunction() {
console.log( ordinaryFunction );
}
};
obj.ordinaryFunction() // All good!
obj.method() // ReferenceError: method is not defined
A method is a property of an object whose value is a function. Methods are called on objects in the following format: object.method().
//this is an object named developer
const developer = {
name: 'Andrew',
sayHello: function () {
console.log('Hi there!');
},
favoriteLanguage: function (language) {
console.log(`My favorite programming language is ${language}`);
}
};
// favoriteLanguage: and sayHello: and name: all of them are proprieties in the object named developer
now lets say you needed to call favoriteLanguage propriety witch is a function inside the object..
you call it this way
developer.favoriteLanguage('JavaScript');
// My favorite programming language is JavaScript'
so what we name this: developer.favoriteLanguage('JavaScript');
its not a function its not an object? what it is? its a method
Your first line, is creating an object that references a function. You would reference it like this:
myFirstFunc(param);
But you can pass it to another function since it will return the function like so:
function mySecondFunction(func_param){}
mySecondFunction(myFirstFunc);
The second line just creates a function called myFirstFunc which would be referenced like this:
myFirstFunc(param);
And is limited in scope depending on where it is declared, if it is declared outside of any other function it belongs to the global scope. However you can declare a function inside another function. The scope of that function is then limited to the function its declared inside of.
function functionOne(){
function functionTwo(){}; //only accessed via the functionOne scope!
}
Your final examples are creating instances of functions that are then referenced though an object parameter. So this:
function myFirstFunc(param){};
obj.myFirst = myFirstFunc(); //not right!
obj.myFirst = new myFirstFunc(); //right!
obj.myFirst('something here'); //now calling the function
Says that you have an object that references an instance of a function. The key here is that if the function changes the reference you stored in obj.myFirst will not be changed.
While #kevin is basically right there is only functions in JS you can create functions that are much more like methods then functions, take this for example:
function player(){
this.stats = {
health: 0,
mana: 0,
get : function(){
return this;
},
set : function( stats ){
this.health = stats.health;
this.mana = stats.mana;
}
}
You could then call player.stats.get() and it would return to you the value of heath, and mana. So I would consider get and set in this instance to be methods of the player.stats object.
A function executes a list of statements example:
function add() {
var a = 2;
var b = 3;
var c = a + b;
return c;
}
1) A method is a function that is applied to an object example:
var message = "Hello world!";
var x = message.toUpperCase(); // .toUpperCase() is a built in function
2) Creating a method using an object constructor. Once the method belongs to the object you can apply it to that object. example:
function Person(first, last, age, eyecolor) {
this.firstName = first;
this.lastName = last;
this.age = age;
this.eyeColor = eyecolor;
this.name = function() {return this.firstName + " " + this.lastName;};
}
document.getElementById("demo").innerHTML = person.fullName(); // using the
method
Definition of a method: A method is a property of an object that is a function. Methods are defined the way normal functions are defined, except that they have to be assigned as the property of an object.
var myFirstFunc = function(param) {
//Do something
};
and
function myFirstFunc(param) {
//Do something
};
are (almost) identical. The second is (usually) just shorthand. However, as this jsfiddle (http://jsfiddle.net/cu2Sy/) shows, function myFirstFunc will cause the function to be defined as soon as the enclosing scope is entered, whereas myFirstFunc = function will only create it once execution reaches that line.
As for methods, they have a this argument, which is the current object, so:
var obj = {};
obj.func = function( ) {
// here, "this" is obj
this.test = 2;
}
console.log( obj.test ); // undefined
obj.func( );
console.log( obj.test ); // 2
The exact syntax you showed is because you can also do this:
function abc( ) {
this.test = 2;
}
var obj = {};
obj.func = abc;
obj.func( ); // sets obj.test to 2
but you shouldn't without good reason.
ecma document
4.3.31method :
function that is the value of a property
NOTE When a function is called as a method of an object, the object is
passed to the function as its this value.
It is very clear: when you call a function if it implicitly has a this (to point an object) and if you can't call the function without an object, the function deserves to name as method.
I'm working on a project that involves constructing functions from other functions. I had the idea of writing a class to simplify things but I haven't been able to get it to work without resorting to using __proto__.
Here's basically what my vision is.
function MyFunction () {
// ...
}
var myFn = new MyFunction();
myFn(); // executes without error
myFn instanceof MyFunction; // returns true
The following code does just that using __proto__
function MyFunction () {
var fn = function () { return 'hello'; };
fn.__proto__ = this;
return fn;
}
var myFn = new MyFunction();
alert( myFn() ); // hello
alert( myFn instanceof MyFunction ); // true
Here's something I've tried using valueOf
function MyFunction () {
this.fn = function () { return 'hello'; };
this.valueOf = function () { return this.fn; };
}
var myFn = new MyFunction();
alert( myFn instanceof MyFunction ); // true
alert( myFn.valueOf()() ); // hello
alert( myFn() ); // error
And here's something else extending the function to contain all the properties of MyFunction.
function MyFunction () {
this.foo = 'hello'
var fn = function () { return 'hello'; };
for ( var i in this ) {
fn[ i ] = this[ i ];
}
return fn;
}
var myFn = new MyFunction();
alert( myFn() ); // hello
alert( myFn.foo ); // hello
alert( myFn instanceof MyFunction ); // false
I don't want to use __proto__ because it's non-standard. Also, this was kind of a freak idea, I'd really like to get it to work, but if it's not possible I'll live. But I guess my question is, is what I'd like to do possible?
Fascinating idea. I don't believe you can do it with standard ECMAScript yet, not even using ES5.
ES5 gives us better access to and control over the prototype, including providing a means of setting the prototype when creating objects (without having to go through constructor functions) with Object.create, but you can't construct functions via that mechanism. And that's what you would have to do, because instanceof uses the abstract spec [[HasInstance]] method, which is currently only implemented by functions, and the function implementation of it works by seeing if the object's underyling prototype ([[Proto]]) is === to the function's prototype property. The only standard way to set the object's underlying prototype is to create it via new MyFunction or via Object.create, and neither mechanism creates a function object.
ES.next may make this possible. There's a proposal that's been promoted to "harmony" status (so, fairly advanced) for a "set prototype operator", <|, which is intended to solve many of the problems currently solved via __proto__. One of the things it's for is "Setting the prototype of a function to something other than Function.prototype". Using it (in its current form), your MyFunction would look something like this:
function MyFunction () {
return MyFunction.prototype <| function () { return 'hello'; };
}
MyFunction.prototype = Object.create(Function.prototype);
That last bit is to make it that MyFunction.prototype is an object with the prototype Function.prototype, so that functions constructed via MyFunction have call, apply, bind, etc.
How can this object be rewritten so you don't need to declare it with "new"?
var Lang = new function(){
this.get = function(str, trans){
if(TRANSLATE[str]){
var str = TRANSLATE[str][LANG];
if(count_obj(trans) > 0){
for(var key in trans){
str = str.replace('%'+key+'%', trans[key]);
}
}
}
return str;
};
};
To something like this:
var Lang = {
get : function(){}
};
You wrote the solution to your own question in the question...this is a perfectly valid way to create an object in javascript:
var Lang = {
get: function(str, trans){
if(TRANSLATE[str]){
var str = TRANSLATE[str][LANG];
if(count_obj(trans) > 0){
for(var key in trans){
str = str.replace('%'+key+'%', trans[key]);
}
}
}
return str;
};
};
If you want private variables, the usual way to do that is to create a function with local variables that return the object with those variables encapsulated in a closure like so:
var Lang = (function() {
var p1; // private variable
var p2; // another private variable
return {
getP1: function () {
return p1;
},
setP1: function(value) {
p1 = value;
}
};
})();
Note that the function that creates the object you want is executed right away and returns the object with two private variables captured in the closure. Those variables will not be accessible from outside the object.
Patterns for Enforcing new
As mentioned already, constructors are still just functions but invoked with new.
What
happens if you forget new when you invoke a constructor? This is not going to cause
syntax or runtime errors but might lead to logical errors and unexpected behavior.
That’s because when you forget new, this inside the constructor will point to the global
object. (In browsers this will point to window.)
When your constructor has something like this.member and you invoke the constructor
without new, you’re actually creating a new property of the global object called
member and accessible through window.member or simply member. This behavior is highly
undesirable, because you know you should always strive for keeping the global namespace
clean.
// constructor
function Waffle() {
this.tastes = "yummy";
}
// a new object
var good_morning = new Waffle();
console.log(typeof good_morning); // "object"
console.log(good_morning.tastes); // "yummy"
// antipattern:
// forgotten `new`
var good_morning = Waffle();
console.log(typeof good_morning); // "undefined"
console.log(window.tastes); // "yummy"
Self-Invoking Constructor
To address the drawback of the previous pattern and have prototype properties available
to the instance objects, consider the following approach. In the constructor you
check whether this is an instance of your constructor, and if not, the constructor invokes
itself again, this time properly with new:
function Waffle() {
if (!(this instanceof Waffle)) {
return new Waffle();
}
this.tastes = "yummy";
}
Waffle.prototype.wantAnother = true;
// testing invocations
var first = new Waffle(),
second = Waffle();
console.log(first.tastes); // "yummy"
console.log(second.tastes); // "yummy"
console.log(first.wantAnother); // true
console.log(second.wantAnother); // true
Another general-purpose way to check the instance is to compare with
arguments.callee instead of hard-coding the constructor name.
if (!(this instanceof arguments.callee)) {
return new arguments.callee();
}
This pattern uses the fact that inside every function, an object called arguments is created
containing all parameters passed to the function when it was invoked. And arguments
has a property called callee, which points back to the function that was called. Be
aware that arguments.callee is not allowed in ES5’s strict mode, so it’s best if you limit
its future use and also remove any instances should you find them in existing code.
“JavaScript Patterns, by Stoyan Stefanov (O’Reilly). Copyright 2010 Yahoo!, Inc., 9780596806750.”
just leave the "new" out, rest is the same. :)
var Lang = function(){
...
}
Edit: example copy-paste from firebug, "dsa" is just an object, "dsaFunc" is a function, but you can do the same with them:
>>> var dsa = {};
undefined
>>> dsa.get = function(a){ return a+1;}
function()
>>> dsa.get(2)
3
>>> var dsaFunc = function(){};
undefined
>>> dsaFunc.get = function(a){ return a+1;}
function()
>>> dsaFunc.get(2)
3
Given a function:
function x(arg) { return 30; }
You can call it two ways:
result = x(4);
result = new x(4);
The first returns 30, the second returns an object.
How can you detect which way the function was called inside the function itself?
Whatever your solution is, it must work with the following invocation as well:
var Z = new x();
Z.lolol = x;
Z.lolol();
All the solutions currently think the Z.lolol() is calling it as a constructor.
As of ECMAScript 6, this is possible with new.target
new.target will be set as true if the function is called with new (or with Reflect.construct, which acts like new), otherwise it's undefined.
function Foo() {
if (new.target) {
console.log('called with new');
} else {
console.log('not called with new');
}
}
new Foo(); // "called with new"
Foo(); // "not called with new"
Foo.call({}); // "not called with new"
NOTE: This is now possible in ES2015 and later. See Daniel Weiner's answer.
I don't think what you want is possible [prior to ES2015]. There simply isn't enough information available within the function to make a reliable inference.
Looking at the ECMAScript 3rd edition spec, the steps taken when new x() is called are essentially:
Create a new object
Assign its internal [[Prototype]] property to the prototype property of x
Call x as normal, passing it the new object as this
If the call to x returned an object, return it, otherwise return the new object
Nothing useful about how the function was called is made available to the executing code, so the only thing it's possible to test inside x is the this value, which is what all the answers here are doing. As you've observed, a new instance of* x when calling x as a constructor is indistinguishable from a pre-existing instance of x passed as this when calling x as a function, unless you assign a property to every new object created by x as it is constructed:
function x(y) {
var isConstructor = false;
if (this instanceof x // <- You could use arguments.callee instead of x here,
// except in in EcmaScript 5 strict mode.
&& !this.__previouslyConstructedByX) {
isConstructor = true;
this.__previouslyConstructedByX = true;
}
alert(isConstructor);
}
Obviously this is not ideal, since you now have an extra useless property on every object constructed by x that could be overwritten, but I think it's the best you can do.
(*) "instance of" is an inaccurate term but is close enough, and more concise than "object that has been created by calling x as a constructor"
1) You can check this.constructor:
function x(y)
{
if (this.constructor == x)
alert('called with new');
else
alert('called as function');
}
2) Yes, the return value is just discarded when used in the new context
NOTE: This answer was written in 2008, when javascript was still in ES3 from 1999. A lot of new functionality has been added since then, so now better solutions exists. This answer is kept for historical reasons.
The benefit of the code below is that you don't need to specify the name of the function twice and it works for anonymous functions too.
function x() {
if ( (this instanceof arguments.callee) ) {
alert("called as constructor");
} else {
alert("called as function");
}
}
Update
As claudiu have pointed out in a comment below, the above code doesn't work if you assign the constructor to the same object it has created. I have never written code that does that and have newer seen anyone else do that eighter.
Claudius example:
var Z = new x();
Z.lolol = x;
Z.lolol();
By adding a property to the object, it's possible to detect if the object has been initialized.
function x() {
if ( (this instanceof arguments.callee && !this.hasOwnProperty("__ClaudiusCornerCase")) ) {
this.__ClaudiusCornerCase=1;
alert("called as constructor");
} else {
alert("called as function");
}
}
Even the code above will break if you delete the added property. You can however overwrite it with any value you like, including undefined, and it still works. But if you delete it, it will break.
There is at this time no native support in ecmascript for detecting if a function was called as a constructor. This is the closest thing I have come up with so far, and it should work unless you delete the property.
Two ways, essentially the same under the hood. You can test what the scope of this is or you can test what this.constructor is.
If you called a method as a constructor this will be a new instance of the class, if you call the method as a method this will be the methods' context object. Similarly the constructor of an object will be the method itself if called as new, and the system Object constructor otherwise. That's clear as mud, but this should help:
var a = {};
a.foo = function ()
{
if(this==a) //'a' because the context of foo is the parent 'a'
{
//method call
}
else
{
//constructor call
}
}
var bar = function ()
{
if(this==window) //and 'window' is the default context here
{
//method call
}
else
{
//constructor call
}
}
a.baz = function ()
{
if(this.constructor==a.baz); //or whatever chain you need to reference this method
{
//constructor call
}
else
{
//method call
}
}
Checking for the instance type of the [this] within the constructor is the way to go. The problem is that without any further ado this approach is error prone. There is a solution however.
Lets say that we are dealing with function ClassA(). The rudimentary approach is:
function ClassA() {
if (this instanceof arguments.callee) {
console.log("called as a constructor");
} else {
console.log("called as a function");
}
}
There are several means that the above mentioned solution will not work as expected. Consider just these two:
var instance = new ClassA;
instance.classAFunction = ClassA;
instance.classAFunction(); // <-- this will appear as constructor call
ClassA.apply(instance); //<-- this too
To overcome these, some suggest that either a) place some information in a field on the instance, like "ConstructorFinished" and check back on it or b) keep a track of your constructed objects in a list. I am uncomfortable with both, as altering every instance of ClassA is way too invasive and expensive for a type related feature to work. Collecting all objects in a list could provide garbage collection and resource issues if ClassA will have many instances.
The way to go is to be able to control the execution of your ClassA function. The simple approach is:
function createConstructor(typeFunction) {
return typeFunction.bind({});
}
var ClassA = createConstructor(
function ClassA() {
if (this instanceof arguments.callee) {
console.log("called as a function");
return;
}
console.log("called as a constructor");
});
var instance = new ClassA();
This will effectively prevent all attempts to trick with the [this] value. A bound function will always keep its original [this] context unless you call it with the new operator.
The advanced version gives back the ability to apply the constructor on arbitrary objects. Some uses could be using the constructor as a typeconverter or providing an callable chain of base class constructors in inheritance scenarios.
function createConstructor(typeFunction) {
var result = typeFunction.bind({});
result.apply = function (ths, args) {
try {
typeFunction.inApplyMode = true;
typeFunction.apply(ths, args);
} finally {
delete typeFunction.inApplyMode;
}
};
return result;
}
var ClassA = createConstructor(
function ClassA() {
if (this instanceof arguments.callee && !arguments.callee.inApplyMode) {
console.log("called as a constructor");
} else {
console.log("called as a function");
}
});
actually the solution is very possible and simple... don't understand why so many words been written for such a tiny thing
UPDATE: thanks to TwilightSun the solution is now completed, even for the test Claudiu suggested! thank you guys!!!
function Something()
{
this.constructed;
if (Something.prototype.isPrototypeOf(this) && !this.constructed)
{
console.log("called as a c'tor"); this.constructed = true;
}
else
{
console.log("called as a function");
}
}
Something(); //"called as a function"
new Something(); //"called as a c'tor"
demonstrated here: https://jsfiddle.net/9cqtppuf/
Extending Gregs solution, this one works perfectly with the test cases you provided:
function x(y) {
if( this.constructor == arguments.callee && !this._constructed ) {
this._constructed = true;
alert('called with new');
} else {
alert('called as function');
}
}
EDIT: adding some test cases
x(4); // OK, function
var X = new x(4); // OK, new
var Z = new x(); // OK, new
Z.lolol = x;
Z.lolol(); // OK, function
var Y = x;
Y(); // OK, function
var y = new Y(); // OK, new
y.lolol = Y;
y.lolol(); // OK, function
There is no reliable way to distinguish how a function is called in JavaScript code.1
However, a function call will have this assigned to the global object, while a constructor will have this assigned to a new object. This new object cannot ever be the global object, because even if an implementation allows you to set the global object, you still haven't had the chance to do it.
You can get the global object by having a function called as a function (heh) returning this.
My intuition is that in the specification of ECMAScript 1.3, constructors that have a defined behavior for when called as a function are supposed to distinguish how they were called using this comparison:
function MyClass () {
if ( this === (function () { return this; })() ) {
// called as a function
}
else {
// called as a constructor
}
}
Anyway, anyone can just use a function's or constructor's call or apply and set this to anything. But this way, you can avoid "initializing" the global object:
function MyClass () {
if ( this === (function () { return this; })() ) {
// Maybe the caller forgot the "new" keyword
return new MyClass();
}
else {
// initialize
}
}
1. The host (aka implementation) may be able to tell the difference, if it implements the equivalent to the internal properties [[Call]] and [[Construct]]. The former is invoked for function or method expressions, while the latter is invoked for new expressions.
In my testing for http://packagesinjavascript.wordpress.com/ I found the test if (this == window) to be working cross-browser in all cases, so that's the one I ended up using.
-Stijn
Until I saw this thread I never considered that the constructor might be a property of an instance, but I think the following code covers that rare scenario.
// Store instances in a variable to compare against the current this
// Based on Tim Down's solution where instances are tracked
var Klass = (function () {
// Store references to each instance in a "class"-level closure
var instances = [];
// The actual constructor function
return function () {
if (this instanceof Klass && instances.indexOf(this) === -1) {
instances.push(this);
console.log("constructor");
} else {
console.log("not constructor");
}
};
}());
var instance = new Klass(); // "constructor"
instance.klass = Klass;
instance.klass(); // "not constructor"
For most cases I'll probably just check instanceof.
From John Resig:
function makecls() {
return function(args) {
if( this instanceof arguments.callee) {
if ( typeof this.init == "function")
this.init.apply(this, args.callee ? args : arguments)
}else{
return new arguments.callee(args);
}
};
}
var User = makecls();
User.prototype.init = function(first, last){
this.name = first + last;
};
var user = User("John", "Resig");
user.name
If you're going hackish, then instanceof is the minimum solution after new.target as by other answers. But using the instanceof solution it would fail with this example:
let inst = new x;
x.call(inst);
Combining with #TimDown solution, you can use ES6's WeakSet if you want compatibility with older ECMAScript versions to prevent putting properties inside instances. Well, WeakSet will be used in order to allow unused objects be garbage collected. new.target won't be compatible in the same source code, as it is a ES6's syntax feature. ECMAScript specifies identifiers cannot be one of the reserved words, and new is not an object, anyways.
(function factory()
{
'use strict';
var log = console.log;
function x()
{
log(isConstructing(this) ?
'Constructing' :
'Not constructing'
);
}
var isConstructing, tracks;
var hasOwnProperty = {}.hasOwnProperty;
if (typeof WeakMap === 'function')
{
tracks = new WeakSet;
isConstructing = function(inst)
{
if (inst instanceof x)
{
return tracks.has(inst) ?
false : !!tracks.add(inst);
}
return false;
}
} else {
isConstructing = function(inst)
{
return inst._constructed ?
false : inst._constructed = true;
};
}
var z = new x; // Constructing
x.call(z) // Not constructing
})();
ECMAScript 3's instanceof operator of is specified as:
11.8.6 The instanceof operator
--- The production RelationalExpression: RelationalExpression instanceof ShiftExpression is evaluated
as follows:
--- 1. Evaluate RelationalExpression.
--- 2. Call GetValue(Result(1)).
--- 3. Evaluate ShiftExpression.
--- 4. Call GetValue(Result(3)).
--- 5. If Result(4) is not an object, throw a TypeError exception.
--- 6. If Result(4) does not have a [[HasInstance]] method, throw a TypeError exception.
--- 7. Call the [[HasInstance]] method of Result(4) with parameter Result(2).
--- 8. Return Result(7).
15.3.5.3 [[HasInstance]] (V)
--- Assume F is a Function object.
--- When the [[HasInstance]] method of F is called with value V, the following steps are taken:
--- 1. If V is not an object, return false.
--- 2. Call the [[Get]] method of F with property name "prototype".
--- 3. Let O be Result(2).
--- 4. If O is not an object, throw a TypeError exception.
--- 5. Let V be the value of the [[Prototype]] property of V.
--- 6. If V is **null**, return false.
--- 7. If O and V refer to the same object or if they refer to objects joined to each other (13.1.2), return true.
--- 8. Go to step 5.
And that means it'll be recursing the left hand side value after going to its prototype until it is not an object or until it is equal to the prototype of the right hand side object with the specified [[HasInstance]] method. What means it'll check if left hand side is an instance of the right hand side, consuming all internal prototypes of the left hand side though.
function x() {
if (this instanceof x) {
/* Probably invoked as constructor */
} else return 30;
}
maybe I`m wrong but (at the cost of a parasite) the following code seems like a solution:
function x(arg) {
//console.debug('_' in this ? 'function' : 'constructor'); //WRONG!!!
//
// RIGHT(as accepted)
console.debug((this instanceof x && !('_' in this)) ? 'function' : 'constructor');
this._ = 1;
return 30;
}
var result1 = x(4), // function
result2 = new x(4), // constructor
Z = new x(); // constructor
Z.lolol = x;
Z.lolol(); // function
Although this thread is ancient, I'm surprised that nobody has mentioned that under strict mode ('use strict') a function's default this value is undefined, instead of set to global/window as before, so to check if new is not used simply test for falsey value of !this
- EG:
function ctor() { 'use strict';
if (typeof this === 'undefined')
console.log('Function called under strict mode (this == undefined)');
else if (this == (window || global))
console.log('Function called normally (this == window)');
else if (this instanceof ctor)
console.log('Function called with new (this == instance)');
return this;
}
If you test that function as-is, you will get undefined as this value, due to the 'use strict' directive at the start of the function. Of course, if already has strict mode on then it won't change if you remove the 'use strict' directive, but otherwise if you remove it the this value will be set to window or global.
If you use new to call the function then the this value will match the instanceof check (although if you checked the other things, then instance is last option so this check is not needed, and to be avoided if you want to inherit instances anyway)
function ctor() { 'use strict';
if (!this) return ctor.apply(Object.create(ctor.prototype), arguments);
console.log([this].concat([].slice.call(arguments)));
return this;
}
This will log the this value and any arguments you pass to the function to console, and return the this value. If the this value is falsey then it creates a new instance using Object.create(ctor.prototype) and uses Function.apply() to re-call the constructor with the same params but with correct instance as this. If the this value is anything other than falsey then it is assumed to be a valid instance and returned.
I believe the solution is to turn your Constructor function into a wrapper of the real Constructor function and its prototype Constructor if required. This method will work in ES5 from 2009 and also work in strict mode. In the code window below I have an example using the module pattern, to hold the real constructor and its prototype's constructor, in a closure, which is accessible through scope within the constructor(wrapper). This works because no property is added to the "this" keyword within the Constructor(wrapper) and the Constructor(wrapper).prototype is not set, so is Object by default; thus the array returned from Object.getpropertyNames will have a length equal to 0, if the new keyword has been used with the Constructor(wrapper). If true then return new Vector.
var Vector = (function() {
var Vector__proto__ = function Vector() {
// Vector methods go here
}
var vector__proto__ = new Vector__proto__();;
var Vector = function(size) {
// vector properties and values go here
this.x = 0;
this.y = 0;
this.x = 0;
this.maxLen = size === undefined? -1 : size;
};
Vector.prototype = vector__proto__;
return function(size){
if ( Object.getOwnPropertyNames(this).length === 0 ) {
// the new keyword WAS USED with the wrapper constructor
return new Vector(size);
} else {
// the new keyword was NOT USED with the wrapper constructor
return;
};
};
})();
Tim Down I think is correct. I think that once you get to the point where you think you need to be able to distinguish between the two calling modes, then you should not use the "this" keyword. this is unreliable, and it could be the global object, or it could be some completely different object. the fact is, that having a function with these different modes of activation, some of which work as you intended, others do something totally wild, is undesirable. I think maybe you're trying to figure this out because of that.
There is an idiomatic way to create a constructor function that behaves the same no matter how it's called. whether it's like Thing(), new Thing(), or foo.Thing(). It goes like this:
function Thing () {
var that = Object.create(Thing.prototype);
that.foo="bar";
that.bar="baz";
return that;
}
where Object.create is a new ecmascript 5 standard method which can be implemented in regular javascript like this:
if(!Object.create) {
Object.create = function(Function){
// WebReflection Revision
return function(Object){
Function.prototype = Object;
return new Function;
}}(function(){});
}
Object.create will take an object as a parameter, and return a new object with that passed in object as its prototype.
If however, you really are trying to make a function behave differently depending on how it's called, then you are a bad person and you shouldn't write javascript code.
If you don't want to put a __previouslyConstructedByX property in the object - because it pollutes the object's public interface and could easily be overwritten - just don't return an instance of x:
function x() {
if(this instanceof x) {
console.log("You invoked the new keyword!");
return that;
}
else {
console.log("No new keyword");
return undefined;
}
}
x();
var Z = new x();
Z.lolol = x;
Z.lolol();
new Z.lolol();
Now the x function never returns an object of type x, so (I think) this instanceof x only evaluates to true when the function is invoked with the new keyword.
The downside is this effectively screws up the behaviour of instanceof - but depending on how much you use it (I don't tend to) that may not be a problem.
If you're goal is for both cases to return 30, you could return an instance of Number instead of an instance of x:
function x() {
if(this instanceof x) {
console.log("You invoked the new keyword!");
var that = {};
return new Number(30);
}
else {
console.log("No new");
return 30;
}
}
console.log(x());
var Z = new x();
console.log(Z);
Z.lolol = x;
console.log(Z.lolol());
console.log(new Z.lolol());
I had this same problem when I tried to implement a function that returns a string instead of an object.
It seems to be enough to check for the existence of "this" in the beginning of your function:
function RGB(red, green, blue) {
if (this) {
throw new Error("RGB can't be instantiated");
}
var result = "#";
result += toHex(red);
result += toHex(green);
result += toHex(blue);
function toHex(dec) {
var result = dec.toString(16);
if (result.length < 2) {
result = "0" + result;
}
return result;
}
return result;
}
Anyway, in the end I just decided to turn my RGB() pseudoclass into an rgb() function, so I just won't try to instantiate it, thus needing no safety check at all. But that would depend on what you're trying to do.
function createConstructor(func) {
return func.bind(Object.create(null));
}
var myClass = createConstructor(function myClass() {
if (this instanceof myClass) {
console.log('You used the "new" keyword');
} else {
console.log('You did NOT use the "new" keyword');
return;
}
// constructor logic here
// ...
});
On the top of the question, below code will auto-fix the issue in case function is called without new.
function Car() {
if (!(this instanceof Car)) return new Car();
this.a = 1;
console.log("Called as Constructor");
}
let c1 = new Car();
console.log(c1);
This can achieved without using ES6 new.target. You can run your code in strict mode and in this case value of this will be undefined if called without new otherwise it will be empty object.
Example::
"use strict"
function Name(){
console.log(this)
if(this){
alert("called by new")
}
else
alert("did not called using new")
}
new Name()
Use this instanceof arguments.callee (optionally replacing arguments.callee with the function it's in, which improves performance) to check if something is called as a constructor. Do not use this.constructor as that can be easily changed.