20

Just finished reading "JavaScript: The Good Parts" - Great book. But I am confused about a very important topic on page 33-34 - Augmenting types. It describes the creation of a new method added to Function.prototype, so when invoked with a new method, all Functions will have that method available. Fair enough. But the subsequent examples show this method being used on Numbers and Strings. Which, I am thinking, are Objects - not Functions. What am I missing here?

Function.prototype.method = function (name, func) {
    this.prototype[name] = func;
    return this;
};

Usage example:

Number.method('integer', function() {
    return Math[this < 0 ? 'ceiling' : 'floor'](this);
});

document.writeln((-10 / 3).integer()); //-3
svenyonson
  • 1,815
  • 1
  • 21
  • 30
  • 7
    Functions are objects. – Matt Ball Jan 24 '14 at 00:10
  • 2
    @MattBall I don't think that's what the OP is asking. Rather, I think he/she is asking how `Number` derives from `Function`. – Kevin Ji Jan 24 '14 at 00:13
  • 2
    Number *is* a function. It doesn't "derive" from Function. It is an instance. – Pointy Jan 24 '14 at 00:21
  • @Pointy, Object.getPrototypeOf(Number) == Function.prototype // true – JukkaP Dec 27 '20 at 18:54
  • @JukkaP right, which means it is a Function instance. – Pointy Dec 27 '20 at 19:43
  • @Pointy But that iNumber nstance "derives" from Function.prototype via prototypal inheritance. – JukkaP Dec 28 '20 at 12:31
  • Well it depends on what you want the word "derived" to mean. Number **is** a function, and every function inherits methods from the Function prototype for that reason. I usually think of "derive" as applying to subclasses and the subclassing mechanism, but it's just a word. – Pointy Dec 28 '20 at 12:59

4 Answers4

13

Function object vs Function instance object

First of all, in javascript, a function is also an object. From this, I mean not the object created by new () construct, but the function itself. To avoid confusion, I would refer such objects as Function object, and for object created using new () construct of a function as Function instance object.

_ proto _ and prototype properties

Any function object in javascript has two properties: _ proto _ and prototype. Moreover, any Function instance object (created using new constructor) has a property _ proto _ . The _ proto _ is what defines the inheritance. Some good resource on this could be found at

http://zeekat.nl/articles/constructors-considered-mildly-confusing.html

How is inheritance defined?

An object objA inherits another object objC if objA and objC are connected through any number of _ proto _ . So if objA has _ proto _ equal to objB, and objB has _ proto _ equal to objC, then objA inherits objB and objC, while objB inherits objC.

What is meant by inheritance?

It means any inheriting object can use any property of inherited object.

What is Function.prototype

It is the object whom _ proto _ of every function object refers. This means every Function object has access to properties of Function.prototype, since every Function object inherits Function.prototype object. This also means that if method property is added to Function.prototype object, it would be available to all the possible Function objects in javascript. This includes Strings, Number, etc.

this.prototype[name] = func;

this refers to Function object when the 'method' is invoked from Function objects like Number, String, etc. Which means that we now have a new property in Function object with name "name", and its a function 'func'.

What good is prototype property of Function object

A function object's prototype is referred to by the Function instance object's _ proto _ created using that function's new construct.

If the following was executed:

Number.method('integer', function () {...});

then Number.prototype has that integer method defined in it. This means each Number function instance object, e.g. new Number (2.4), would "inherit" this new property 'integer' from Number.prototype, since that Number function instance object would have its _ proto _ set to Number.prototype.

Ouroboros
  • 1,432
  • 1
  • 19
  • 41
11

You add a method to the Number prototype, so every Number instance has access to it. In other words, because there's a property called "integer" on the Number prototype, any attempt to access that property from any Number instance will succeed. That's kind-of the whole point of putting properties on a constructor prototype.

When a JavaScript primitive number appears on the left side of a . operator, the language automatically boxes it in a Number instance so that the method call makes sense.

edit — let's look at how that "method" function works. In the call

Number.method( "integer", function() { ... } )

what's going on? Well, inside the "method" function, the "name" parameter is "integer". The function parameter is then assigned as a property of this.prototype. What is this in that invocation of the "method" function? It's the Number constructor function. Thus, the "method" function — which is on the Function prototype, and therefore is available to all function instances, like the Number constructor function for example — adds the given function as a property of the prototype of the constructor function involved.

Why is the "method" property visible as a property of the Number constructor? Because the Number constructor is itself a function. The "method" function was created as a property of the Function prototype, so that means it is visible to every function instance — including the Number constructor.

Pointy
  • 405,095
  • 59
  • 585
  • 614
  • Yes, but how is it added to the Number prototype, when 'method' was added to Function.prototype? I could understand if 'method' was added to Object.prototype. – svenyonson Jan 24 '14 at 00:16
  • 1
    @svenyonson `Number` is a function. Try this in your browser console: `typeof Number` – Matt Ball Jan 24 '14 at 00:18
  • @svenyonson as Matt Ball says, the Number constructor is itself a function instance. – Pointy Jan 24 '14 at 00:20
  • @Pointy - I think I understand now. (-10/3) expression had to call the Number constructor. – svenyonson Jan 24 '14 at 00:29
  • @svenyonson yes, exactly!! JavaScript is simple and complicated at the same time :) – Pointy Jan 24 '14 at 00:30
  • @Pointy, while all of the above is true, it also works if 'method' is added to Object instead of Function. (any unintended consequences I am not seeing?). This has to work because Functions are also Objects. I would suggest that from a readability/comprehension perspective, it makes more sense to add it to Object instead of Function. – svenyonson Jan 24 '14 at 16:21
  • @svenyonson yes, you're right, that should work. However, would it make sense to call `.method` on a Date instance? It would probably result in an exception, because a Date instance (probably) doesn't have a "prototype" property. – Pointy Jan 24 '14 at 16:27
  • @Pointy - Date.method('month', function() {return this.getMonth();}); var d = new Date(); d.month(); Works great! – svenyonson Jan 24 '14 at 16:34
  • @svenyonson yes, but the Date constructor is *not* a Date **instance**. If you put "method" on the Object prototype, then it will also be available to Date instances. Try calling `d.method("foo", function() { });` – Pointy Jan 24 '14 at 16:44
  • In the MDN documentation they say that [Function.prototype cannot be modified](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/prototype). Why can we add it the `method` method in this case ? – Martinos Jan 27 '16 at 17:35
  • @Martinos what that means is that the "prototype" property itself on the Function constructor cannot be changed to point to another object. However, the object referred to by the "prototype" property *can* be changed. – Pointy Jan 27 '16 at 20:12
0

Number or Object or other build-in class is also an constructor, then constructor is a function in JavaScript. There are tow important description in ECMAScript specification:

Every built-in function and every built-in constructor has the Function prototype object, which is the initial value of the expression Function.prototype (15.3.4), as the value of its [[Prototype]] internal property.

Unless otherwise specified every built-in prototype object has the Object prototype object, which is the initial value of the expression Object.prototype (15.2.4), as the value of its [[Prototype]] internal property, except the Object prototype object itself.

so in console, we can execute the code:

Number.prototype.__proto__.isPrototypeOf(Function)

the result is true.

so that Number can access the Function.prototype's methods is reasonable.

At the same time, if we extend the Object.prototype as Object.prototype.say = 'hello';, we can also access the property say as Function.say.

Because Function.prototype.isPrototype(Object) is true.

Community
  • 1
  • 1
John Hou
  • 219
  • 2
  • 11
0

is this demonesrate you can see difference between clearly and obviously enter image description here

[**

enter image description here **]2

mostafa kazemi
  • 514
  • 6
  • 7