Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why are some JavaScript constructors not functions?

Clarification:
"JavaScript constructor" should be more properly be written as "javascript constructor" to emphasize that the constructors considered are not just the native JavaScript language constructors, such as Object, Array, Function, etc. but also others, extrinsic to the JavaScript language definition but intrinsic to a browser, such as XMLHttpRequest, The word "JavaScript" is meant to indicate these constructors are expressed and accessed using JavaScript.

some references:

  • Using a Constructor Function in Working with Objects - MDN Docs
  • "constructor
    Specifies the function that creates an object's prototype"
    in Object - MDN Docs
  • an example: "... calling the Worker() constructor ..."
    Worker - MDN Docs
  • What are the predefined primitive constructors?
  • Where are constructors such as, `new Image()` and `new Option()`, documented?
  • Where is the Documentation for all of the Javascript HTML Element Constructors?

Rhetorically, there are references to constructor functions but NOT constructor objects!

(Facetiously, this is because Objects ARE functions, and Functions are objects!
Why in JavaScript is a function considered both a constructor and an object?
More specifically, objects, or is that obj-eggs?, ARE, ignoring literal instances, instantiations of functions and functions are Object instances of Functions. It is arguable that functions are fundamental to the existence of objects as evidenced by the fact
7. Functions
      precedes
8. Working with Objects
in the MDN docs JavaScript Guide. That section 8, I object!, provides the details needed to create objects using constructors and function instantiations!)

Why are constructors that interface the DOM not functions?

javascript:
  alert([
    "using browser environment:  \n"+window.navigator.userAgent,
     Option, Image, Audio,
       Storage, XMLHttpRequest, Worker, FileReader,
   ] . join("\n\n"));

shows us:

using browser environment:
Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.3) Gecko/20100423 Ubuntu/10.04 (lucid) Firefox/3.6.3

[object Option]

[object Image]

[object Audio]

[object Storage]

[object XMLHttpRequest]

[object Worker]

[object FileReader]

but ...

javascript:
  alert([
             XPCNativeWrapper,
  ].join("\n\n"));

(which produces

function XPCNativeWrapper() { [native code] }

)

and JavaScript language constructors ARE functions.

javascript:
  alert([
    "using browser environment:  \n"+window.navigator.userAgent,
             Array, Boolean, Date, Function,
               Number, Object, RegExp, String,
                 Error, Iterator,
  ].join("\n\n"));

gives us:

using browser environment:
Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.3) Gecko/20100423 Ubuntu/10.04 (lucid) Firefox/3.6.3

function Array() { [native code] }

function Boolean() { [native code] }

function Date() { [native code] }

function Function() { [native code] }

function Number() { [native code] }

function Object() { [native code] }

function RegExp() { [native code] }

function String() { [native code] }

function Error() { [native code] }

function Iterator() { [native code] }

like image 933
Ekim Avatar asked Aug 08 '11 20:08

Ekim


People also ask

What is difference between constructor and function in JavaScript?

Using functions for creating objects is fairly common in Javascript, so Javascript provides shortcut that lets you write functions for creating objects. These special functions are called Constructor functions. Constructors are functions that lets you populate the object which you need to create.

What makes a function a constructor in JavaScript?

A constructor is a special function that creates and initializes an object instance of a class. In JavaScript, a constructor gets called when an object is created using the new keyword. The purpose of a constructor is to create a new object and set values for any existing object properties.

Can a function have constructor in JS?

Function objects created with the Function constructor are parsed when the function is created. This is less efficient than creating a function with a function expression or function declaration and calling it within your code, because such functions are parsed with the rest of the code.

How do you assign a function to a variable with a JavaScript constructor?

// using constructor function function Person () { this.name = 'Sam' } let person1 = new Person(); let person2 = new Person(); // adding new property to person1 person1.


2 Answers

First:

Objects ARE functions

No, the are not:

> a = function() {}
  function () {}
> a instanceof Object
  true
> b = {}
  Object
> b instanceof Function
  false

The toString method (which is what gets called when you do string concatenation) is not a reliable way to get information about an object. If I use typeof, I get the following:

using browser environment:  
Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:5.0.1) Gecko/20100101 Firefox/5.0.1

function

function

function

object

function

function

function

So you see, most of them, apart form Storage, are actually functions (why it does not work for Storage, I don't know).

Also keep in mind that the DOM interface can behave differently than native JavaScript objects.

On the other hand, in Chrome the toString method gives this:

[object Function] 

[object Function] 

[object Function] 

function Storage() { [native code] } 

function XMLHttpRequest() { [native code] } 

function Worker() { [native code] } 

function FileReader() { [native code] }
like image 156
Felix Kling Avatar answered Sep 24 '22 15:09

Felix Kling


When you alert those values the browser engine is alerting value.toString() so we are talking about why does Function.prototype.toString behave in a strange manner.

The ES5.1 specification states :

15.3.4.2 Function.prototype.toString ( ) An implementation-dependent representation of the function is returned. This representation has the syntax of a FunctionDeclaration.

Note in particular that the use and placement of white space, line terminators, and semicolons within the representation String is implementation-dependent.

The toString function is not generic; it throws a TypeError exception if its this value is not a Function object. Therefore, it cannot be transferred to other kinds of objects for use as a method.

Clearly ES5 states that toString returns an implementation specific string.

If you read the ES Harmony proposals page it states :

function to string – greater specification for problematic Function.prototype.toString (markm, allen)

Here are some more resources :

  • ES:Harmony proposal for Function.prototype.toString
  • ES:Harmonye strawman proposal for Function.prototype.toString
  • ES-discuss mail archive about Function.prototype.toString

Basically it's a known issue that toString on function objects (and especially host objects that are also functions) is undefined behaviour. The TC39 committee is already working on standardizing this.

As you can see the host objects are proposed to be standardized in strawman so it's in the air whether that makes it into ES6. However function objects living in ECMA land should have a standardized toString method in ES6 as defined on the harmony proposals page.

like image 24
Raynos Avatar answered Sep 23 '22 15:09

Raynos