I am curious as to what's going on here. As you can see, I have defined a constructor function called range to build new range objects. I've extended the range constructor through it's prototype, adding a simple includes method. I've created my new object and used the variable of p. When I attempt to use this method with my range objects, all is well and it works as expected. The problem is when I try to look at at p.prototype it tells me that it's type is undefined and p.prototype has no methods... Huh??
What's going on here?? How is p an object and p.prototype is not?
function range(from, to) {
this.from = from;
this.to = to;
}
range.prototype = {
includes: function(x) { return this.from <= x && x <= this.to; },
}
var p = new range(1, 4);
console.log(typeof p) //outputs object
console.log(typeof p.prototype) //outputs undefined
console.log(Object.getOwnPropertyNames(range.prototype)); //outputs includes
console.log(Object.getOwnPropertyNames(p.prototype)); //throws error, p.prototype is not an object
The problem is when I try to look at at p.prototype it tells me that it's type is undefined
That's correct. The objects created by your range constructor do not have a prototype property, but they do have an underlying prototype (which is drawn from the prototype property of the range function).
Let's look at what happens when you do new range():
The JavaScript engine creates a new, blank object.
The JavaScript engine assigns that object's underlying prototype (not prototype) to be the object referenced by range.prototype. (In the spec, this property — which is not directly accessible in code but see below — is called [[Proto]].)
The JavaScript engine calls range with this referring to the new object.
Assuming range doesn't return a different object (which it can do; this is a bit obscure), the result of new range is the new object created in step 1.
Later, when you use this.includes, this is what happens:
The engine looks at the actual object to see if it has an includes property.
Since it doesn't, the engine looks at [[Proto]] to see if it has one.
Since it does, it uses that one (if not, it would have looked at [[Proto]]'s [[Proto]] and so on).
The key things here are:
Objects have underlying prototypes, which are not accessible via any named property on the object itself. (In fact, it used to be we couldn't get to them at all. Now, in ES5, we have Object.getPrototypeOf.)
Objects created via new SomeFunctionName get their prototype from SomeFunctionName.prototype property, which is a perfectly normal property of the SomeFunctionName object (functions are first-class objects in JavaScript).
Side note: You're replacing the prototype of range with your code. In general, although it works, I would avoid that. Instead, augment the existing object referred to by range.prototype. (Add properties to it, rather than replacing it.) But that's not central to your question.
I think you wanted was:
range.prototype.includes = function(x) {
return this.from <= x && x <= this.to;
}
You redefined the prototype object, so the reference to the original one has disappeared. Try this way:
range.prototype.includes = function(x) {
return this.from <= x && x <= this.to;
}
Number.prototype.myRound = function (decimalPlaces) {
var multiplier = Math.pow(10, decimalPlaces);
return (Math.round(this * multiplier) / multiplier);
};
Related
If functions are objects, where does the function's body go?
Let me clarify what I am confused about. Functions are objects, okay. I can think of an object as a hash map consisting of string keys and arbitrarily typed values. I can do this:
function Square(size) {
Rectangle.call(this, size, size);
}
Square.prototype = new Rectangle();
I just treated Square like a regular object and messed with its prototype property by assigning a new value to it. However, if functions are just objects (or hash maps for that matter), where is the function's body (in this example Rectangle.call(this, size, size);) being stored?
I figured it must be stored as the value of some property, something like the following maybe:
console.log(Square.executableBody); // "Rectangle.call(this, size, size);"
Obviously, this is not the case. Interestingly, while reading "The Principles of Object-Oriented JavaScript" by Nicholas C. Zakas, I stumbled upon this:
[...] functions are actually objects in JavaScript. The defining characteristic of a function - what distinguishes it from any other object - is the presence of an internal property named [[Call]]. Internal properties are not accessible via code [...] The [[Call]] property is unique to functions and indicates that the object can be executed.
This might be the property I was looking for above. It does not go into detail, though. Is the function's body actually stored within the [[Call]] property? If so, how does execution work? Unfortunately I was unable to find out more about [[Call]], Google mostly came up with information on a function's call method...
Some clarification would be much appreciated! :)
It becomes the value of another internal property, called [[Code]]:
13.2 Creating Function Objects
Given an optional parameter list specified by FormalParameterList, a body specified by FunctionBody, a Lexical Environment specified by Scope, and a Boolean flag Strict, a Function object is constructed as follows:
[...]
Set the [[Code]] internal property of F to FunctionBody.
If so, how does execution work?
Calling a function basically calls the internal [[Call]] method, which is described in http://es5.github.io/#x13.2.1. I guess the important step is:
Let result be the result of evaluating the FunctionBody that is the value of F's [[Code]] internal property.
Basically, for all practical purposes you can consider the function in its entirety to be the object. You can study the JS spec or JS engine source code to learn about how the function body is actually stored in an internal property on the object, but this won't really help you understand how it works as a JS programmer. You can see the body as a string by evaluating fn.toString. You cannot otherwise access the body other than to execute it or bind to it or call other methods on Function.prototype. However, because it's an object, it can also have properties attached to it like any other object.
Why would I want to attach a property to a function? Here is an example of a memoization function (deliberately simplified):
function memoize(fn) {
var cache = {};
function memoized(x) {
return x in cache ? cache[x] : cache[x] = fn(x);
};
memoized.clear = function() { cache = {}; };
return memoized;
}
So we are placing a function clear as a property on the returned function. We can use this as:
memofied = memoize(really_long_calculation);
result = memofied(1); // calls really_long_calculation
result = memofied(1); // uses cached value
memofied.clear(); // clear cache
result = memofied(1); // calls really_long_calculation again
The function is enough of an object that Object.defineProperty can be called on it, allowing us to write the memoization function above as follows, if we really wanted to:
function memoize(fn) {
var cache = {};
return Object.defineProperty(function (x) {
return x in cache ? cache[x] : cache[x] = fn(x);
}, 'clear', {value: function() { cache = {}; } });
}
(since Object.defineProperty returns the object.) This has the advantage that clear takes on the default non-enumerable and non-writeable properties, which seems useful.
I could even use a function as the first (prototype) argument to Object.create:
someobj = Object.create(function() { }, { prop: { value: 1 } });
but there's no way to call the function serving as prototype. However, its properties will be available in the prototype chain of the created object.
Constructor1=function(){};
Constructor1.prototype.function1=function this_function()
{
// Suppose this function was called by the lines after this code block
// this_function - this function
// this - the object that this function was called from, i.e. object1
// ??? - the prototype that this function is in, i.e. Constructor1.prototype
}
Constructor2=function(){};
Constructor2.prototype=Object.create(Constructor1.prototype);
Constructor2.prototype.constructor=Constructor2;
object1=new Constructor2();
object1.function1();
How do I retrieve the last reference (indicated by ???) without knowing the name of the constructor?
For instance, say I had an object which inherits from a chain of prototypes. Can I know which prototype is used when I call a method on it?
Both seem theoretically possible, but I can't find any way that works without more than constant number of assignment statements (if I have many such functions).
The prototype of each function has a reference back to the function via the constructor property [MDN]. So you can get the constructor function via
var Constr = this.constructor;
Getting the prototype is a bit trickier. In browsers supporting ECMAScript 5, you can use Object.getPrototypeOf [MDN]:
var proto = Object.getPrototypeOf(this);
In older browser it might be possible to get it via the non-standard __proto__ [MDN] property:
var proto = this.__proto__;
Can I know which prototype is used when I call a method on it?
Yes, if the browser supports ES5. Then you have to repeatedly call Object.getPrototypeOf() until you find the object with that property. For example:
function get_prototype_containing(object, property) {
do {
if(object.hasOwnProperty(property)) {
break;
}
object = Object.getPrototypeOf(object);
}
while(object.constructor !== window.Object);
// `object` is the prototype that contains `property`
return object;
}
// somewhere else
var proto = get_prototype_containing(this, 'function1');
I am unable to understand this loop behavior of the javascript.
Can someone tell me why was it designed in this way?
Is there any real use case of this behavior?
why this loop? {
Newly created instance inherits properties from the prototype property of the constructor function object.
prototype property of the constructor function is an object that keeps constructor property.
constructor property is equal to the constructor function object.
Again constructor function object keeps prototype property.
}
instance1---inhertis(keeps)-->Prototype property of func()-->keep constructor property-->function object func-->keep prototype property.
var func = function(){};
var construct = func.prototype.constructor;
console.log(construct === func); //true
var instance1 = new func();
Updated: Even if in between i assigned something else, instanceof always returns true.
var func1 = function(){};
func1.prototype.constructor = 1;
var instance1 = new func1();
console.log(instance1 instanceof func1); //true
var func2 = function(){};
func2.prototype.constructor = 0;
var instance2 = new func2();
console.log(instance2 instanceof func2); //true
Sorry to ask 2 question in 1 but both may be related.
Of course it retains the instance. Why wouldn't it? If you're making a duck, it's a duck - its DNA says that it's a duck, no matter if you paint it black or teach it to be a goose.
Also, in your case, setting the constructor has no effect. When you do new func (or new func(), which are identical), you go and grab an internal property of the function (the [[Construct]] property), and not func.prototype.constructor.
obj.constructor is defined on every single object, since it's defined on every "constructor": That is, Object Number Function Date Boolean String and so on. Each have a constructor property in their prototype:
Object.prototype.constructor === Object;
String.prototype.constructor === String;
//etc
Each one has its prototype.constructor pointing to itself.
Since functions can also behave like constructors, their .prototype.constructor property points to themselves as well. AFAIK, that's unused in the language itself.
The terse, technical answer? http://es5.github.com/#x11.8.6
//foo instanceof bar
Return the result of calling the [[HasInstance]] internal method of bar with argument foo.
(slightly paraphrased)
Basically, you're asking mother-duck: "Excuse me ma'am, is this your child?" The child has little say in the matter.
Edit: As mentioned in the comments, changing the prototype does indeed affect the instanceof results. Like above, there's the intuitive answer and the technical answer.
Intuitive answer is simple: The prototype defines the object. Therefore, changing the prototype changes the DNA - you make the duck a goose, not by teaching it to be a goose, but by going to its DNA and changing it to a goose DNA.
The technicality is seeing what [[HasInstance]] does. (the other [[HasIntsance]] calls this one) The spec is really dry and terse, so here's the algorithm written in pseudo-javascript:
//assume Func is the function we're talking about
function HasInstance ( value ) {
if ( IsntAnObject(value) ) {
return false;
}
var proto = Func.prototype;
if ( Type(proto) !== "Object" ) {
return false;
}
while ( value !== null ) {
value = value.prototype;
if ( value === proto ) {
return true;
}
}
return false;
}
As can be seen, by changing the prototype, we're changing the behavior - value will be different values.
Very nice question!
Since prototypes are Object instances (as everything in JavaScript is), they have to share Object's prototype. Which happens to have the constructor property.
Instances share all properties of their constructor prototypes, including the constructor property.
The constructor property of a function's prototype is specified to reflect the function itself. For example:
Object.prototype.constructor === Object
Function.prototype.constructor === Function
/* the same with every other function */
When you overwrite a constructor function's prototype, like this:
Func.prototype = 1
The prototype itself and all instances of Func have a different constructor property, in the case above – Number.
As for the instanceof, it has nothing to do with the constructor property per se. It has to do with the prototype.
function Func() {}
Func.prototype = { a: 1 } // assign a prototype
var fn = new Func() // create an instance
fn instanceof Func // true (reflects connexion to the original prototype)
Func.prototype = { b: 2 } // assign a completely different prototype
fn instanceof Func // false (the connexion is broken)
Below little code might clear up your confusion. As you can see the new instance actually does not have its own property called "constructor". So when you are asking for instance.constructor, you are actually getting instance.prototype.constructor value due to prototype chaining. To be consistent you want to see instance.constructor set to same value as the function that created it. This is why JS interpreter sets prototype.constructor to the value of the function itself.
function Rabbit() { }
var rabbit = new Rabbit()
alert( rabbit.hasOwnProperty('constructor') ) // false
alert( Rabbit.prototype.hasOwnProperty('constructor') ) // true
This works same for non-function objects. They don't have their own .constructor property and so the call ultimately ends up in Object.prototype.constructor and hence you get same answer for all non-function objects.
A question to ask at this point is why JS designer made this choice for function objects instead of explicitly setting constructor property of instance to function itself. I don't know the answer but I can guess that it adds more "dynamism" in the language. The instance.constructor can be used to create a new instance in generic way even if you don't have the original function that created the instance.
function makeUnicorn(animal) {
var unicorn = new animal.constructor();
unicorn.HornOnNose = true;
return unicorn;
}
var unicornRabbit = makeUnicorn(rabbit);
Notice that above runs without error for any object, even ones that are not an instance of function. You can conceivably use this JavaScript feature to customize behavior of above "generic" function which you otherwise couldn't if constructor was an own property of the instance.
Horse.prototype.constructor = function() {
var newHorse = new Horse();
newHorse.Color = "White";
return newHorse;
}
I am just learning Javascript and I was wondering, is using the prototype declaration, like this:
function TSomeObj()
{
this.name="my object";
}
TSomeObj.prototype.showname = function() {
alert(this.name);
}
Basically the same as doing it like this:
function TSomeObj()
{
this.name="my object";
this.showname = function() {
alert(this.name);
}
}
When I dump the object's properties I get the same result:
TSomeObj (inline version) =
{
'name': 'my object',
'test': function
}
TSomeObj (prototype declaration) =
{
'name': 'my object',
'test': function
}
What exactly is the benefit of using prototype declarations? Except less cluttering and more orderly sourcecode perhaps.
Update: I should perhaps have made it more clear that it was the final result i was curious about. The end result is ofcourse the same (i.e both register a new function in the object prototype) - but the way they do it is wildly different. Thank you for all replies and info!
Note: This answer is accurate but does not fully reflect the new way to create classes in JavaScript using the ES6 class Thing {} syntax. Everything here does in fact apply to ES6 classes, but might take some translation.
I initially answered the wrong question. Here is the answer to your actually-asked question. I'll leave my other notes in just in case they're helpful to someone.
Adding properties to an object in the constructor function through this.prop is different from doing so outside through Object.prototype.prop.
The most important difference is that when you add a property to the prototype of a function and instantiate a new object from it, that property is accessed in the new object by stepping up the inheritance chain rather than it being directly on the object.
var baseobj = {};
function ObjType1() {
this.prop = 2;
}
function ObjType2() {}
ObjType1.prototype = baseobj;
ObjType2.prototype = baseobj; // these now have the *same* prototype object.
ObjType1.prototype.prop = 1;
// identical to `baseobj.prop = 1` -- we're modifying the prototype
var a = new ObjType1(),
b = new ObjType2();
//a.hasOwnProperty('prop') : true
//b.hasOwnProperty('prop') : false -- it has no local property "prop"
//a: { prop = 2 }, b : { prop = 1 } -- b's "prop" comes from the inheritance chain
baseobj.prop = 3;
//b's value changed because we changed the prototype
//a: { prop = 2 }, b : { prop = 3 }
delete a.prop;
//a is now reflecting the prototype's "prop" instead of its own:
//a: { prop = 3 }, b : { prop = 3 }
A second difference is that adding properties to a prototype occurs once when that code executes, but adding properties to the object inside the constructor occurs each time a new object is created. This means using the prototype performs better and uses less memory, because no new storage is required until you set that same property on the leaf/proximate object.
Another difference is that internally-added functions have access to private variables and functions (those declared in the constructor with var, const, or let), and prototype-based or externally-added functions do not, simply because they have the wrong scope:
function Obj(initialx, initialy) {
var x = initialx,
y = initialy;
this.getX = function() {
return x;
}
var twoX = function() { // mostly identical to `function twoX() { ... }`
return x * 2;
}
this.getTwoX = function() {
return twoX();
}
}
Obj.prototype.getY = function() {
return y; // fails, even if you try `this.y`
}
Obj.prototype.twoY = function() {
return y * 2; // fails
}
Obj.prototype.getTwoY = function() {
return twoY(); // fails
}
var obj = new Obj();
// obj.y : fails, you can't access "y", it is internal
// obj.twoX() : fails, you can't access "twoX", it is internal
// obj.getTwoX() : works, it is "public" but has access to the twoX function
General notes about JavaScript objects, functions, and inheritance
All non-string and non-scalar variables in JavaScript are objects. (And some primitive types undergo boxing when a method is used on them such as true.toString() or 1.2.valueOf()). They all act somewhat like a hash/dictionary in that they have an unlimited(?) number of key/value pairs that can be assigned to them. The current list of primitives in JavaScript is: string, number, bigint, boolean, undefined, symbol, null.
Each object has an inheritance chain of "prototypes" that go all the way up to the base object. When you access a property of an object, if that property doesn't exist on the object itself, then the secret prototype of that object is checked, and if not present then that object's prototype, so on and so forth all the way up. Some browsers expose this prototype through the property __proto__. The more modern way to get the prototype of an object is Object.getPrototypeOf(obj). Regular objects don't have a prototype property because this property is for functions, to store the object that will be the prototype of any new objects created using that function as their constructor.
A JavaScript function is a special case of an object, that in addition to having the key/value pairs of an object also has parameters and a series of statements that are executed in order.
Every time a function object is invoked it is paired with another object that is accessed from within the function by the keyword this. Usually, the this object is the one that the function is a property of. For example, ''.replace() boxes the string literal to a String, then inside the replace function, this refers to that object. another example is when a function is attached to a DOM element (perhaps an onclick function on a button), then this refers to the DOM element. You can manually choose the paired this object dynamically using apply or call.
When a JavaScript function is invoked with the new keyword as in var obj = new Obj(), this causes a special thing to happen. If you don't specifically return anything, then instead of obj now containing the return value of the Obj function, it contains the this object that was paired with the function at invocation time, which will be a new empty object with the first parent in its inheritance chain set to Obj.prototype. The invoked Obj() function, while running, can modify the properties of the new object. Then that object is returned.
You don't have to worry much about the keyword constructor, just suffice it to say that obj.constructor points to the Obj function (so you can find the thing that created it), but you'll probably not need to use this for most things.
Back to your question. To understand the difference between modifying the properties of an object from within the constructor and modifying its prototype, try this:
var baseobj = {prop1: 'x'};
function TSomeObj() {
this.prop2 = 'y';
};
TSomeObj.prototype = baseobj;
var a = new TSomeObj();
//now dump the properties of `a`
a.prop1 = 'z';
baseobj.prop1 = 'w';
baseobj.prop2 = 'q';
//dump properties of `a` again
delete a.prop1;
//dump properties of `a` again
You'll see that setting a.prop1 is actually creating a new property of the proximate object, but it doesn't overwrite the base object's prop1. When you remove prop1 from a then you get the inherited prop1 that we changed. Also, even though we added prop2 after a was created, a still has that property. This is because javascript uses prototype inheritance rather than classic inheritance. When you modify the prototype of TSomeObj you also modify all its previously-instantiated objects because they are actively inheriting from it.
When you instantiate a class in any programing language, the new object takes on the properties of its "constructor" class (which we usually think of as synonymous with the object). And in most programming languages, you can't change the properties or methods of the class or the instantiated object, except by stopping your program and changing the class declaration.
Javascript, though, lets you modify the properties of objects and "classes" at run-time, and all instantiated objects of that type class are also modified unless they have their own properties that override the modification. Objects can beget objects which can beget objects, so this works in a chain all the way up to the base Object class. I put "classes" in quotes because there really isn't such a thing as a class in JavaScript (even in ES6, it's mostly syntactic sugar), except that the new keyword lets you make new objects with the inheritance chain hooked up for you, so we call them classes even though they're just the result of constructor functions being called with the new keyword.
Some other notes: functions have a Function constructor, objects have an Object constructor. The prototype of the Function constructor is (surprise, surprise) Object.
Inheriting from an object without the constructor function running
In some cases, it's useful to be able to create a new "instance of an object" without the constructor function running. You can inherit from a class without running the class's constructor function like so (almost like manually doing child.__proto__ = parent):
function inheritFrom(Class) {
function F() {};
F.prototype = Class.prototype;
return new F();
}
A better way to do this now is Object.setPrototypeOf().
The accepted answer missed the most important distinctions between prototypes and methods bound to a specific object, so I'm going to clarify
Prototype'd functions are only ever declared once. Functions attached using
this.method = function(){}
are redeclared again and again whenever you create an instance of the class. Prototypes are, thus, generally the preferred way to attach functions to a class since they use less memory since every instance of that class uses the same functions. As Erik pointed out, however, functions attached using prototypes vs attached to a specific object have a different scope, so prototypes don't have access to "private" variables defined in a function constructor.
As for what a prototype actually is, since it's an odd concept coming from traditional OO languages:
Whenever you create a new instance of a function:
var obj = new Foo();
the following logic is run (not literally this code, but something similar):
var inheritsFrom = Foo,
objectInstance = {};
objectInstance.__proto__ = inheritsFrom.prototype;
inheritsFrom.apply( objectInstance, arguments );
return objectInstance;
so:
A new object is created, {}, to represent the new instance of the function
The prototype of the function is copied to __proto__ of the new object. Note that this is a copy-by-reference, so Foo.prototype and objectInstance.__proto__ now refer to the same object and changes made in one can be seen in the other immediately.
The function is called with this new object being set as this in the function
and whenever you try to access a function or property, e.g.: obj.bar(), the following logic gets run:
if( obj.hasOwnProperty('bar') ) {
// use obj.bar
} else if( obj.__proto__ ){
var proto = obj.__proto__;
while(proto){
if( proto.hasOwnProperty('bar') ){
// use proto.bar;
}
proto = proto.__proto__;
}
}
in other words, the following are checked:
obj.bar
obj.__proto__.bar
obj.__proto__.__proto__.bar
obj.__proto__.__proto__.__proto__.bar
... etc
until __proto__ eventually equals null because you've reached the end of the prototype chain.
Many browsers actually expose __proto__ now, so you can inspect it in Firebug or the Console in Chrome/Safari. IE doesn't expose it (and may very well have a different name for the same thing internally).
How do you determine the difference between new Object and new fn under these conditions?
var fn = function(){};
fn.prototype = {};
You may not rely on __proto__ or Object.getPrototypeOf existing, as they are not in IE or Opera.
The solution may not statically use fn, such as instanceof fn.
Implementing your own Object.getPrototypeOf is fine.
Not required: It would be nice if your solution works with objects from other frames and doesn't use function serialization.
Here's some example base code to start off with:
var fn = function(){};
fn.prototype = {};
var x = new fn,
y = new Object;
fn = null; // prohibit static reference to fn
// define your detection function here
function isNewObject(obj) {
};
alert(isNewObject(x) !== isNewObject(y) ? "pass" : "fail");
I'm pretty sure you can't do this in ES3 with only standard support, and here's why:
Look at x and y creation.
var fn = function(){};
fn.prototype = {};
var x = new fn,
y = new Object;
When x is instantiated, its internal [[Prototype]] is being set to an object referenced by fn.prototype (just an Object object that you assigned to fn.prototype). Object's constructor - fn - is then being called in a context of that newly created object, but since it doesn't mutate ab object in any way, we can consider that step irrelevant.
When y is instantiated, its internal [[Prototype]] is being set to Object.prototype, which is an Object object too. Its constructor (Object) is then being called in a context of this newly created object as well, but nothing happens there either.
So now you end up with 2 Object objects which only differ in that their internal [[Prototype]]'s reference different objects - x's one references whatever you assigned to fn.prototype and y's references Object.prototype. Their internal [[Class]] properties are identical too (i.e. equal to "Object")
You can't get direct access to [[Prototype]] in ES3. You can infer something about it by using instanceof, but since fn is nulled in your example intanceof-based inference is out of the picture.
Now, you can augment Object constructor in such way that it would somehow mutate instantiated object. You can then inspect an object and detect this augmentation. For example:
Object = function() {
return ({ __: void 0 });
}
and then:
function isNewObject(object) {
return '__' in object;
}
but this will, of course, only work when object is being created with new Object and not via, say, an object literal - { }. It's also rather obtrusive :)
Perhaps there are other ways, but I can't see them right now.
HTH
As far as I know your problem is impossible to solve with ES3: instanceof and isPrototypeOf() can't be used to solve it because the prototype object of fn is inaccessible, and only ES5 allows access to the internal [[Prototype]] property via Object.getPrototypeOf().
Btw, an even harder problem to solve would be if you assign Object.prototype to fn.prototype, eg
var x = (function() {
function Foo() {}
Foo.prototype = Object.prototype;
return new Foo;
})();
As the prototype chain of Foo and Object instances is identical, there shouldn't be any way to distinguish them.