1

I am currently learning JavaScript through my institution and I am reading about how in JavaScript, functions are objects and how it has a prototype (don't know what that is since the lesson never explained what prototype is). Coming from a background in Java, you might understand how confusing this is to me. I decided to search Google for any references on how functions are objects and keep seeing that you can write a constructor like this:

function Person(first, last, age, eyecolor) {
    this.firstName = first;
    this.lastName = last;
    this.age = age;
    this.eyeColor = eyecolor;
}

But I know that a regular function is written as such:

function multiplyNumbers(a, b) {
    return a * b;
}

So how does JavaScript know when I am making a regular function and when I am making a constructor if they are written pretty much the same way?

Alexiz Hernandez
  • 609
  • 2
  • 9
  • 31
  • You may find this useful. [https://stackoverflow.com/questions/40922531/how-to-check-if-a-javascript-function-is-a-constructor](https://stackoverflow.com/questions/40922531/how-to-check-if-a-javascript-function-is-a-constructor) – Farzad Yousefzadeh Dec 19 '17 at 23:22
  • The keyword `new` – zer00ne Dec 20 '17 at 00:33
  • If you call Person without `new` in a global context then `this` will point to `window` and as a result the properties like `firstName` will become global variables. – david25272 Dec 20 '17 at 03:09

2 Answers2

3

It doesn't. Any function declared using the function keyword or constructor within a class body can be called as a constructor by preceding the call with new. Unless the function explicitly returns an object, the value returned by the call is a new object created by the call. The new object can be referred to inside the constructor function as this.

Object instances created by a function (by calling it as a constructor using the new keyword) have their prototype chain initialized to the value of the function object's prototype property.

A function object's prototype property is created when the function or class is declared or a function or a class expression is evaluated. The value of the prototype property can be altered if the keyword used was function but can't be changed for class declarations/expressions. However properties of the prototype object can be modified in both cases and are subsequently inherited by object instances.

Arrow functions do not support being called as constructors - they have no prototype property.

Happy learning about "how does JavaScript prototypal inheritance work"!


P.S.

There is a convention of starting class and constructor function names with an upper-case letter to distinguish them from "regular" functions, but there is no syntactical requirement to do so.

Regular functions (called without new) can have a this value that depends on how the function was defined and called. "How is the value of this set within JavaScript functions" is a topic you may wish to look up separately.

traktor
  • 17,588
  • 4
  • 32
  • 53
0

Creating functions by the function keyword was the only way to do it in older versions of Javascript, and the ambiguity of method vs class has been a longstanding problem in the language. Modern implementations of Javascript, however, allow a little more distinction.

For classes created with the class keyword, the constructor method must be invoked with new and cannot be called like a normal function:

class MyClass{
    constructor(){
        alert('Hello, world!')
    }
}
const hi=new MyClass() // works
MyClass() // throws an error
MyClass.prototype.constructor() // throws an error

Arrow functions, class methods, and method definitions in objects (and generator functions, async functions, and async generator functions, but those are a little advanced for now) all cannot be invoked with new and must be called.

const myArrow=()=>alert('Hello, world'!)
const myObject={
    myDef(){
        alert('Hello, world!')
    }
}
class MyClass{
    myClassMethod(){
        alert('Hello, world!')
    }
}
const myInstance=new MyClass()

myArrow() // good
myObject.myDef() // good
myInstance.myClassMethod() // good

new myArrow() // error
new myObject.myDef() // error
new myInstance.myClassMethod() // error

I prefer to think of the function keyword as being akin to private within a module, and only exposing classes and methods to outside code. Whatever I expose can be called or new'd, but not both.

Ryan Hanekamp
  • 558
  • 4
  • 6