1

Is function a 'Function' object in JavaScript? if so, when I create a constructor function like:

//this is a constructor function

function foo(){
    this.name="xx";
}

Does foo has a property named proto pointing to the Function's prototype? How can I see this property?

ps: If proto is created when an instance is created via the new keyword, why does not function foo have it? According to above, foo is created via new Function.

Jason Aller
  • 3,541
  • 28
  • 38
  • 38
monokeros
  • 21
  • 2
  • possible duplicate of [javascript : function and object...?](http://stackoverflow.com/questions/5958417/javascript-function-and-object) – sloth Feb 05 '15 at 08:31
  • I think there are two different question~~ – monokeros Feb 05 '15 at 08:45
  • consider that `String.slice` is undefined, but `String.prototype.slice` is the same exact same function as `"".slice()` and is also the same function as `new String("hello").constructor.prototype.slice`. it is a little funny at first, but the "new " operator essentially puts anything the constructor's prototype defines into virtual properties on the resulting instance. – dandavis Feb 05 '15 at 09:01
  • someone should mention that from a performance standpoint, it's not a great idea to modify the proto after you have existing instances, so these shortcuts like `__proto__` and `.constructor.prototype` are of limited utility in efficiently-written applications. – dandavis Feb 05 '15 at 09:14
  • @dandavis: *"someone should mention that from a performance standpoint, it's not a great idea to modify the proto after you have existing instances"* What do you mean by "modify the proto"? *Modifying* it (adding properties, etc.) or *replacing* it? (Separately, note that assigning a new value to `obj.constructor.prototype` will have no effect on `obj` at all; but it will change what happens the next time that constructor function is used...) – T.J. Crowder Feb 05 '15 at 09:29
  • @T.J.Crowder: i'm referring to the (first) scary red box here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/proto, but i had V8 in mind... – dandavis Feb 05 '15 at 10:45
  • @dandavis: Okay, that would be *replacing* an object's prototype, and would relate only to `.__proto__` (replacing `.constructor.prototype` has no effect on the object). It's also flatly wrong when it says "**every** browser" (their emph). :-) While it impacts Firefox's engine, there's no effect on V8 or JScript: [test](http://jsperf.com/impact-of-replacing-prototype). (*Modifying* the prototype doesn't have any negative perf impact either -- [test](http://jsperf.com/impact-of-modifying-prototype) --but that's different.) MDN is community-edited, and so sometimes wrong, 'till it's fixed. :-) – T.J. Crowder Feb 05 '15 at 12:03
  • @T.J.Crowder: good info. my concern was more the actual de-optimizing cost of object unboxing from redefining the object, but on a small number of instances of small objects, that's going to be negligible. Additionally, that cost might be smaller with setting a proto than touching each object would be (that's the idea), especially since prototype typically contains functions, not optimize-able data. once configured, the instance property access times should be about the same as before (except perhaps in FF). i could have been more clear, but you raise a good point. – dandavis Feb 05 '15 at 21:53
  • @dandavis: Not quite following you. If you have time, perhaps you could demonstrate what concerns you? I'm not seeing an issue, the main thing is to avoid `delete`. I'm always keen to know more about JS performance... – T.J. Crowder Feb 06 '15 at 07:43

1 Answers1

1

is function a object in javascript?

Yes.

Does foo has a property named proto pointing to the Function 's prototype?

Not named proto, no. This is a bit of a confusing area:

  • All objects have an underlying prototype object they inherit from. From ES5 onward, you can get a reference to that object via Object.getPrototypeOf (e.g., var p = Object.getPrototypeOf(blah) gives you a reference to blah's prototype). Some engines (including Firefox's SpiderMonkey) also make underlying prototype available via the pseudo-property __proto__, and that will be in the spec as of ES6, but officially only when JavaScript is used in browsers.

  • Separately, all normal functions have a property called prototype, which is not that function's underyling prototype (see above). Instead, it's the object that will get assigned as the underlying prototype of objects created using that function as a constructor via the new keyword.

Since this is a bit confusing, let's draw a picture. Suppose we have this code:

function Foo() {
    this.name = "xx";
}

var f = new Foo();

(Since I used it as a constructor, I've used the name Foo rather than foo to stick to conventions.)

Here's what we now have in memory:

+------------+
|  Function  |
| (function) |
+------------+       +-----------+
| __proto__  |----+->| (object)  | This is the object assigned to functions
| prototype  |----/  +-----------+ as their underyling prototype
+------------+    |  | call      |
                  |  | apply     |
                  |  | bind      |
                  |  | ...       |
                  |  +-----------+
+------------+    |
|     Foo    |    |
| (function) |    |
+------------+    |
| __proto__  |----+
|            |          +----------+
| prototype  |----+---->| (object) | This is the object assigned to
+------------+    |     +----------+ objects created via `new Foo`
                  |     | (blank)  |
                  |     +----------+
+-----------+     |
|     f     |     |
| (object)  |     |
+-----------+     |
| __proto__ |-----+
| name: xx  |
+-----------+

(I've left off the references to Object.property above to keep things simpler.)

How can I see this property.

See above, either __proto__ (on only some engines for now, will be standard in ES6) or via Object.getPrototypeOf (ES5).

Example:

// Shows you the object referenced by Function.prototype,
// which is `foo`'s underyling prototype
// ONLY WORKS ON SOME ENGINES for now (including Firefox's SpiderMonkey)
console.log(foo.__proto__);

// Shows you the object referenced by foo.prototype
console.log(foo.prototype);
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • Thanks for your answer. In your answer, you mention that the underlying prototype of objects is created via new foo. But the function foo is created by using new Function(). why does foo not have the underlying prototype? – monokeros Feb 05 '15 at 08:37
  • @monokeros: It does, its underlying prototype is the object that `Function.prototype` points to. I've added a diagram to the answer to help clarify, and expanded on `__proto__` vs. `prototype`. – T.J. Crowder Feb 05 '15 at 08:47
  • 2
    "*…`__proto__` … will be standard as of ES6*" deserves some qualification. `__proto__` is included in the ES 6 Draft **for browsers only**, probably only because it has been implemented in some browsers. Mozilla invented it, deprecated it, now [*tolerates it under sufferance*](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/proto). [*Object.getPrototypeOf*](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.getprototypeof) is the recommended method that persists in ES 6. Your answer suggests that it is ES5 only and not in ES 6. – RobG Feb 05 '15 at 08:55
  • @RobG: I don't think my previous wording suggested `getPrototypeOf` was going away, but I've reworded anyway. Hopefully no ambiguity now. – T.J. Crowder Feb 05 '15 at 09:04
  • @RobG: Re browsers only: Holy \*\*\*\*. I hadn't seen that change. – T.J. Crowder Feb 05 '15 at 09:05
  • yeah, but V8 is probably a browser core implementation... (nodejs should be fine, and what else is there really?) – dandavis Feb 05 '15 at 09:06
  • @dandavis: V8 is *used* in some browsers, but it's not just a browser engine. In theory, they could disable `__proto__` outside the browser environment... (But it's there in Node.) – T.J. Crowder Feb 05 '15 at 09:07
  • 1
    @T.J.Crowder Thanks for your answer. It's clear to understand it ~ – monokeros Feb 06 '15 at 02:32