Confused Constructor in JavaScipts

April 12, 2012, Tags: javascripts

Introduction

I can not quite remember what happened when invoking new over a function. While I’m looking at function init at jQuery source, the concern comes to me again.

Fourtunaly I think the answer at this1 thread turns out to be a quite clear explanation.

Just three things according to that answer.

  1. Creates a new object. Its type is object.
  2. Sets this new object’s internal, inaccessible, [[prototype]] property to be the constructor function’s external, accessible, prototype object. Refer to line 11 at sample.
  3. Executes the constructor function, using the new object whenever this is mentioned.

Regarding #2, we might have question like

  1. What is constuctor function’s prototype object?
  2. What is the [[prototype]]?

The answer are

  1. Function’s prototype property is automatically created which in turn has a constructor property pointing back to the function. Refer to line 4 at sample
  2. Basically [[prototype]] is used for prototype chain. Find details at here2 and Ecma-2623.

Therefore if we change the prototype property of the function before new, the [[prototype]] of instances afterwards is vary accordingly. Refer to line 19 at sample

Sample

  • tested at google chrome 18 and pay close attention to comments.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

var fn1 = function () { this.name = "fn1"; }

fn1.prototype          // Object { constructor: function () { this.name = "fn1"; }
                       //        , __proto__: Object }

fn1.__proto__          // function Empty() {}


var x1 = new fn1();
x1.__proto__ === fn1.prototype  // True

x1.__proto__           // Object { constructor: function () { this.name = "fn1"; }
                       //        , __proto__: Object }
x1.constructor         // function () { this.name = "fn1"; }


fn1.prototype = {'location': 'sea'}

var y1 = new fn1();
x1.__proto__ === fn1.prototype  // True

y1.__proto__;          // Object { location: "sea"
                       //        ,__proto__: Object }
y1.constructor;        // function Object() { [native code] }
  • Quiz: Why y1.constructor is not same as x1.constructor?

JQuery.fn.init

  • jQuery is declarated as
var jQuery = function( selector, context ) {
		// The jQuery object is actually just the init constructor 'enhanced'
		return new jQuery.fn.init( selector, context, rootjQuery );
	},
  • jQuery.fn is just a object as
jQuery.fn = {
	constructor: jQuery,
	init: function( selector, context, rootjQuery ) {
		    var match, elem, ret, doc;
            ... ...
          },
    ... ... // many API declaration.
}
  • Function chain

Since jQuery is just a function, we are able to do with a selector like jQuery('div.navigator').addClass('nav').

Actually in order to use jQuery API like addClass, there must exists following something which of cource can be found at around line 322 of jQuery.1.7.1.css4.

jQuery.fn.init.prototype = jQuery.fn;