when I have function I want to use as a constructor, say:
function clog(x){
var text = x;
return console.log(text );
}
And I have made some instances of it
var bla = new clog();
Now I want to add new functionality it, so I would use
clog.prototype.alert = alert(text);
what would be the difference if I simply do:
clog.alert = alert(text);
Would that not be inherited by the objects that clog is their prototype?
Instances created by a constructor function (
clogin your case) inherit a reference to theclog.prototypeobject. So if you add a property toclog.prototype, it will show up on instances. If you add a property toclogitself, it will not show up on instances.There are some issues with your quoted code, so let’s look at an abstract example:
From your comment below:
Because it’s
Foo.prototype, notFoo, that is the prototype for objects created vianew Foo().No,
FooandFoo.prototypeare completely distinct objects.Foois a function object, which like all function objects can have properties. One ofFoo‘s properties isprototype, which is a non-function object that’s initially blank other than aconstructorproperty that points back toFoo. It’sFoo.prototype, notFoo, that instances created vianew Fooget as their prototype.Foo‘s only role is to create objects that useFoo.prototypeas their prototype. (Actually, inFoo‘s case, it just initializes those objects; they’re created by thenewoperator. With a traditional function likeFoo,newcreates the object. If this code were using ES2015+classsyntax,newwouldn’t create the object, it would leave that toFoo[ifFoowere a base class constructor] orFoo‘s ultimate base class [ifFoowere a subclass constructor].)(To avoid confusion, I’ve changed
Foo.new = ...toFoo.newProp = ...above, sincenewis a keyword. While you can use it like you did as of ES5, it’s best not to.)Because
Foo.newProphas virtually nothing to do withf. You can find it, onf.constructor.newProp, sincef.constructorisFoo.Some ASCII-art:
Given this code:
we have these objects with these properties (some omitted for clarity):
+−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+ | | V +−−−−−−−−−−−−−−−−−−+ | +−−−−−−−−−−−−−−−−+ +−−>| [String] | | | Foo [Function] | | +−−−−−−−−−−−−−−−−−−+ | +−−−−−−−−−−−−−−−−+ | | "I'm bar on Foo" | | | bar |−−−−+ +−−−−−−−−−−−−−−−−−−+ | | prototype |−−−−+ | +−−−−−−−−−−−−−−−−+ | | +−−−−−−−−−−+ | | | V | +−−−−−−−−−−−−−+ | | [Object] | | +−−−−−−−−−−−−−+ | | constructor |−−+ +−−−−−−−−−−−−−−−−−−−−−−−−−−−−+ | bar |−−−−−>| [String] | +−−−−−−−−−−−−−+ +−−−−−−−−−−−−−−−−−−−−−−−−−−−−+ | "I'm bar on Foo.prototype" | +−−−−−−−−−−−−−−−−−−−−−−−−−−−−+Now if we do
we have (new stuff in bold):
+−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+ | | V +−−−−−−−−−−−−−−−−−−+ | +−−−−−−−−−−−−−−−−+ +−−>| [String] | | | Foo [Function] | | +−−−−−−−−−−−−−−−−−−+ | +−−−−−−−−−−−−−−−−+ | | "I'm bar on Foo" | | | bar |−−−−+ +−−−−−−−−−−−−−−−−−−+ | | prototype |−−−−+ | +−−−−−−−−−−−−−−−−+ | | +−−−−−−−−−−−−−+ | | | V | +−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−+ | | f [Object] | +−−−−−>| [Object] | | +−−−−−−−−−−−−−−−+ | +−−−−−−−−−−−−−+ | | [[Prototype]] |−−−−−−−−−−+ | constructor |−−+ +−−−−−−−−−−−−−−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−−−+ | bar |−−−−>| [String] | +−−−−−−−−−−−−−+ +−−−−−−−−−−−−−−−−−−−−−−−−−−−−+ | "I'm bar on Foo.prototype" | +−−−−−−−−−−−−−−−−−−−−−−−−−−−−+([[Prototype]] is an object’s internal field referring to its prototype. This is accessible via
Object.getPrototypeOf[or__proto__on JavaScript engines on web browsers, but don’t use__proto__, it’s just for backward compatibility with old SpiderMonkey-specific code.)Now suppose we do this:
All that changes is the
fobject (new stuff in bold):+−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+ | | V +−−−−−−−−−−−−−−−−−−+ | +−−−−−−−−−−−−−−−−+ +−−>| [String] | | | Foo [Function] | | +−−−−−−−−−−−−−−−−−−+ | +−−−−−−−−−−−−−−−−+ | | "I'm bar on Foo" | | | bar |−−−−+ +−−−−−−−−−−−−−−−−−−+ | | prototype |−−−−+ | +−−−−−−−−−−−−−−−−+ | | +−−−−−−−−−−−−−+ | | | V | +−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−+ | | f [Object] | +−−−−−>| [Object] | | +−−−−−−−−−−−−−−−+ | +−−−−−−−−−−−−−+ | | [[Prototype]] |−−−−−−−−−−+ | constructor |−−+ +−−−−−−−−−−−−−−−−−−−−−−−−−−−−+ | charlie |−−−−−−−−−−+ | bar |−−−−−>| [String] | +−−−−−−−−−−−−−−−+ | +−−−−−−−−−−−−−+ +−−−−−−−−−−−−−−−−−−−−−−−−−−−−+ | | "I'm bar on Foo.prototype" | | +−−−−−−−−−−−−−−−−−−−−−−−−−−−−+ | | +−−−−−−−−−−−−−−−−−−−−+ +−−−−−>| [String] | +−−−−−−−−−−−−−−−−−−−−+ | "I'm charlie on f" | +−−−−−−−−−−−−−−−−−−−−+fnow has its own property, calledcharlie. This means that these two statements:Get processed slightly differently.
Let’s look at
f.charliefirst. Here’s what the engine does withf.charlie:fhave its own property called"charlie"?Simple enough. Now let’s look at how the engine handles
f.bar:fhave its own property called"bar"?fhave a prototype?f‘s prototype have a property called"bar"?So there’s a big difference between
f.charlieandf.bar:fhas its own property calledcharlie, but an inherited property calledbar. And iff‘s prototype object hadn’t had a property calledbar, its prototype object (in this case,Object.prototype) would be checked, and so on up the chain until we run out of prototypes.You can test whether a property is an “own” property, btw, using the
hasOwnPropertyfunction that all objects have:Answering your question from the comments:
Within the call to
Personthat’s part of thenew Person(...)expression,thisrefers to the newly-generated object that will be returned by thenewexpression. So when you dothis.prop = "value";, you’re putting a property directly on that object, nothing to do with the prototype.Putting that another way, these two examples result in exactly the same
pobject:Here are the issues with the quoted code I mentioned:
Issue 1: Returning something from a constructor function:
99.9999% of the time, you don’t want to return anything out of a constructor function. The way the
newoperation works is:prototypeproperty.thisrefers to the new object.newexpression is the object created in step 1.newoperation is that object instead.So in your case, since
console.logdoesn’t return anything, you just remove thereturnkeyword from your code. But if you used thatreturn xyz();construct with a function that returned an object, you’d mess up your constructor function.Issue 2: Calling functions rather than referring to them
In this code:
you’re calling the
alertfunction and assigning the result of it to a property calledalertonclog.prototype. Sincealertdoesn’t return anything, it’s exactly equivalent to:…which probably isn’t what you meant. Perhaps:
There we create a function and assign a reference to it to the
alertproperty on the prototype. When the function is called, it will call the standardalert.Issue 3: Constructor functions should be initially capped
This is just style, but it’s overwhelmingly standard: Constructor functions (functions meant to be used with
new) should start with an upper case letter, soClograther thanclog. Again, though, this is just style.