Reputation: 1
I've 3 objects like these:
class Person {
constructor(name, age) {
this._name = name;
this._age = age;
}
}
let Add = function (a, b) {
return a + b
};
let Math = {
multiply: function (x, y) {
return x * y
}
};
As you can see
, Person
is a class, Add
and Math.multiply
are functions.
My question: How to classify class
and functions
in this case?
My question comes from: Person
looks like a function, like this:
let Person = function (name, age) {
this._name = name;
this._age = age;
};
Also, there are no problems if I declare an object to get new instance of Add
function:
let result = new Add(2, 3); // this is allowed although it just needn't
new operator says:
The new operator creates an instance of a user-defined object type or of one of the built-in object types that has a constructor function.
All of 3 cases, Person
, Add
and Math.multiply
are constructors. So:
let person = new Person('Hermione', 18); // allowed
let result = new Add(2, 3); // allowed
result = new Math.multiply(2, 2); // allowed
Then, because all of them are constructors, it's so difficult to classify class
and function
(for me).
Is there a way to achieve that?
Upvotes: 3
Views: 460
Reputation: 1074595
I think your question stems from quite understandable confusion: Despite the class
syntax, JavaScript doesn't have classes as distinct from functions like some class-based OOP languages do (Java, C#, C++). class
syntax creates a function and associated properties on the object referenced by that function's prototype
property. It's not a separate thing. See below the bar for more.
Further, JavaScript didn't originally make any distinction between normal functions and constructor functions; it was purely a matter of how you used used them (e.g., via new
or calling them directly). As of ES2015 which introduced both class
syntax and arrow functions, the language is moving toward distinguishing different kinds of functions (the ones created via class
will throw an error if you call them without new
; arrow functions will throw an error if you do call them via new
).
If your goal is to look at Person
in code and know whether it was created with class
or function
without calling it, the only way to do that is to convert it to a string and look at the result. The specification requires that Function.prototype.toString
return a string that...
...must have the syntax of a FunctionDeclaration, FunctionExpression, GeneratorDeclaration, GeneratorExpression, ClassDeclaration, ClassExpression, ArrowFunction, MethodDefinition, or GeneratorMethod depending upon the actual characteristics of the object.
So for instance, if I've used class Foo { }
, then Foo.toString()
has to return a class
declaration or expression, whereas if I've used function Foo { }
instead, it must return a function
declaration or expression. So you could work it out with a regular expression.
In a comment you've asked zerkms
But in javascript I can use
Add
andMath.multiply
as classes. Is it better if I can use a function like a class? No, it isn't.
It completely depends on how Add
and X.multiply
(I really wouldn't shadow the built-in Math
object) are defined: It may well make sense to call them via new
. It's not uncommon for an object property to be a reference to a constructor function:
let Nifty = {
Stuff: class {
constructor(name) {
this.name = name;
}
}
};
let x = new Nifty.Stuff("Coolness");
console.log(x.name); // "Coolness"
or
// Better not to do this, but it's allowed
let Nifty = {
Stuff: function(name) {
this.name = name;
}
};
let x = new Nifty.Stuff("Coolness");
console.log(x.name); // "Coolness"
Re class
creating functions: That's literally what it does:
class Foo {
}
console.log(typeof Foo); // "function"
In fact, this:
class Foo {
}
roughly translates to
let Foo = function() {
if (!(this instanceof Foo)) { // This check isn't quite right, but it's close
throw new TypeError("Class constructor Foo cannot be invoked without 'new'");
}
};
and
class Foo {
constructor(name) {
this.name = name;
}
sayHello() {
console.log(`Hi, my name is ${name}!`);
}
}
roughly translates to
let Foo = function(name) {
if (!(this instanceof Foo)) { // This check isn't quite right, but it's close
throw new TypeError("Class constructor Foo cannot be invoked without 'new'");
}
this.name = name;
};
Foo.prototype.sayHello = function sayHello() {
console.log("Hi, my name is " + name + "!");
}
};
Upvotes: 8