from the page https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Details_of_the_Object_Model:
When JavaScript sees the new operator,
it creates a new generic object and
passes this new object as the value of
the this keyword to the WorkerBee
constructor function. The constructor
function explicitly sets the value of
the projects property, and implicitly
sets the value of the internal
proto property to the value of WorkerBee.prototype. (That property
name has two underscore characters at
the front and two at the end.) The
proto property determines the prototype chain used to return
property values. Once these properties
are set, JavaScript returns the new
object and the assignment statement
sets the variable mark to that object.
So basically if we have this function:
function Bee(first_name, second_name){
this.FirstName=name;
this.SecondName=name;
}
I want to know what is the difference between doing something like var bee1 = new Bee("qwe", "asd"); vs:
var bee1={};
bee1.__proto__=Bee.prototype;
var r=Bee.call(bee1, "qwe", "asd");
if(r!==undefined){
bee1=r;
}
For one thing, var bee1 = new Bee("qwe", "asd"); is cross-browser compatible. Some browsers won't let you mess around with an object's __proto__ field -- IE being one of those.
For another, it's less code, and makes more sense at first glance.
Also, in the second example, as of the first line, you've created bee1 but haven't initialized it. As of the second line, the system will consider it a Bee, but it's still not built like one. If something goes awry in the constructor, or anywhere else between creation and construction, you can end up with a half-baked Bee. This as opposed to new Bee(...), which either gives you back a properly constructed Bee or throws an exception.
Related
There are 2 ways to create object
Direct
var x={};
Using the new keyword i.e using constructor function.
var x=new Object();
//or
var x=new Date(); //using constructor function.
Is there any way to determine how that object is created?
Fundamentally, in JavaScript, we don't care how an object was created. We normally just assume that if the object walks like a duck and talks like a duck, it's a duck. (This is called "duck typing.") And that turns out to be just as well, because we can't know how an object was created.
There are really two questions here:
How can you tell whether an object was created with an object initializer ({}) or new Object, and
How can you tell whether an object was created with one of those or some other constructor function (like Date).
The answer to Question 1 is: You can't. There is no difference, at all, in the resulting object, so you can't tell how it was created.
The answer to Question 2 is more complicated:
You can't know, for certain, that an object was created with a given constructor. JavaScript is too powerful, giving you too much control over the object, for it to be possible to be sure.
All you can know is what the object's prototype chain tells you, from which you can infer how it was constructed, but the inference could be incorrect.
Let's take your
var x = new Date();
example. To do that inference, you can use at least three tools:
instanceof: E.g., if (x instanceof Date). instanceof is an operator accepting an object and a function. It checks the object's prototype chain to see if the object the function's prototype property refers to is anywhere in the chain. If so, instanceof's result is true; if not, it's false. So if the object is created with new Date (or new Foo if Foo derives from Date), x instanceof Date will be true.
But again, JavaScript is really powerful, and you can fool it. For instance:
var x = Object.create(Date.prototype);
console.log(x instanceof Date); // true
We didn't use new Date to create that object, but we can't tell that we didn't. (And in this particular case, x won't work correctly as a Date, because Date objects have a special internal slot that normal objects don't have. Many of the Date.prototype functions will fail on the above. But that's Date-specific.)
The constructor property. By default, the prototype property on a function has a property, constructor, that points back to the function. E.g., Date.prototype.constructor === Date is true in the normal case. Since objects created with a constructor get that object as their prototype, you can use constructor to see what constructor (if any) is associated with that object: if (x.constructor === Date) will be true for something created with new Date (in the normal case).
But again, we can fool that check:
var x = Object.create({constructor: Date});
console.log(x.constructor === Date); // true
getPrototypeOf and related: You can check the prototype chain of an object directly (rather than just through instanceof). But this has the same vulnerability that instanceof has: We can fool it by creating the object with Object.create (or before Object.create was in the language, using custom constructor function).
instanceof has the advantage that it checks the entire hierarchy, and doesn't rely on constructor; in hierarchies created with ES5 and earlier (e.g., before ES2015's class), people frequently failed to set constructorcorrectly.
So again, fundamentally, we don't care how an object was created; and that's just as well, because we can't know, for sure, how it was created.
You can't differentiate creation of plain object since for javascript this is exactly the same thing.
var o1 = {};
var o2 = new Object();
I've just started to learn Javascript.
As per my understanding so far, you can declare class/static variables in two ways. The 1st way:
Blog.prototype.signature = "By Blogger-Name";
And the 2nd way:
Blog.signature = "By Blogger-Name";
By using the first method, the variable signature is available to all instances of Blog.
However, a variable that remains the same value for all instances of a class should really not be an instance variable. As I see it, class/static variables should be declared using the second method only.
Hence, my question is, is there a scenario where one would be required/forced to declare variables the first way? Or is my understanding of all of this lacking in any way? Please let me know.
EDIT: In what instances is the first method preferred and, similarly, in what instances is the second method preferred?
EDIT 2: So I've learnt that the first method actually adds instance properties with a default value. This can also be achieved by setting a default value in the constructor itself. So when would adding a property this way (i.e. using prototype) be preferred?
Hence, my question is, is there a scenario where one would be required/forced to declare variables the first way?
The only thing that comes to mind would be if you needed to allow for code using an object created via new Blog to access the property without knowing the constructor function's name. E.g.:
function useABlogInstance(blog) {
// Here, assume I don't know that `blog` was created via `new Blog`
console.log(blog.signature);
}
Although a canny user could do
console.log(blog.constructor.signature);
to access Blog.signature (assuming you maintain the constructor backlink), that wouldn't be very clean. :-)
It's important to note that a property on Blog.prototype isn't a "class" or "static" property, it's an instance property (on the Blog.prototype object). While it's true that reading that property from an object created via new Blog will find it on the prototype (if the instance doesn't have its own signature property), the results of writing to the property are very, very different. Consider:
function A() {}
A.prototype.prop = "prototype prop";
var a1 = new A();
var a2 = new A();
snippet.log(a1.prop); // "prototype prop"
snippet.log(a2.prop); // "prototype prop"
a1.prop = "updated";
snippet.log(a1.prop); // "updated" -- because `a1` has its own `prop` property
// now and no longer uses the prototype's
snippet.log(a2.prop); // "prototype prop"
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
Contrast that with:
function B() {}
B.prop = "B prop";
var b1 = new B();
var b2 = new B();
snippet.log(b1.constructor.prop); // "B prop"
snippet.log(b2.constructor.prop); // "B prop"
snippet.log(B.prop); // "B prop"
b1.constructor.prop = "updated";
snippet.log(b1.constructor.prop); // "updated"
snippet.log(b2.constructor.prop); // "updated"
snippet.log(B.prop); // "updated"
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
For "class"-wide information, I would always use Blog.signature, not Blog.prototype.signature. I'd use Blog.prototype.signature for instance-specific default properties where the values are primitives or functions (but not non-function objects or arrays, I'd set those up in the constructor function).
Side note: You're not declaring a variable in either of your code snippets. You're adding a property to an object. In the first snippet, you're adding the property to the object that will get assigned as the prototype of objects created via new Blog. In the second case, you're adding a property to the Blog object (functions are objects). Neither is a variable, in both cases it's a property.
There are no class variables in Javascript. Actually, there are no classes altogether in Javascript. Thinking in terms of classes and static variables (are you a Java dev?) won't let you know what's going on. Even if the concept of "a class" is independent of the programming language to some degree, it is important to understand that it's not a fundamental programming construct - and in fact there are languages without classes, like Javascript.
Javascript is a very simple language: it has functions and dictionaries, and has the syntax to combine both and support programming the object-oriented way. Take this example:
var johnSnow = { first: "John", last: "Snow" };
function fullName(character) {
return character.first + " " + character.last;
}
console.log(fullName(johnSnow));
And now the OO version:
var Character = function(first, last) {
this.first = first;
this.last = last;
}
Character.prototype.fullName = function() {
return this.first + " " + this.last;
}
console.log(new Character("John", "Snow").fullName());
Finally we can answer your question: when should you set a property on a constructor and when you should use an instance?
Set the property on the instance when they should not be shared with other instances (obviously). You recognize these properties because often are used in instance methods and read with this.$name
Set the property on the constructor... never! Properties set on constructors are simply global variables. So just use global variables, possibly namespacing them (but obviously you'll need a global at some point!)
I guess it all depends on how you want to access the signature variable.
If you want an easy access to it from a Blog instance, use the prototype versions. Then you can do:
var blog = new Blog;
console.log(blog.signature);
Otherwise, you'll have to use Blog.signature or blog.constructor.signature.
I wouldn't worry about making signature an instance variable when you put it in the prototype because that's not what you're doing.
Blog.prototype doesn't get copied around -- it's not something every instance would have its own private copy of. It's a shared object that blog objects (=objects created with new Blog) will have set as their __proto__ (=Object.getPrototypeOf(blog)). __proto__ will be used to search for properties (that includes functions) that are not direct attributes of the instance.
A __proto__ can be overriden by setting an actual instance variable:
var Blog = function () {};
Blog.prototype.signature = "Original sig";
var blog = new Blog();
blog.signature === "Original sig"
//^looked up in Blog.prototype === Object.getPrototypeOf(blog) === blog.__proto__
blog.signature = "New sig"
//^set as an instance property
blog.signature === "New sig"
Blog.prototype.signature !== "New sig" //actual instance properties override prototype properties, but they don't over-write them
var blog2 = new Blog()
blog2.signature === "Original sig"
A classical object-oriented programming language such as C++/Java does a very similar thing, actually. Objects in C++/Java have properties and methods, and methods behave as if they were function pointer properties of instances, but they're not. Methods don't add any size to instances. They're all looked up in a shared place--your class's prototype if you will. The difference is, that in C++/Java the link doesn't exist at runtime (it's maintained by the compiler) and is only for methods. In JavaScript, each object has a real link to a class-shared lookup place (the object's constructor's prototype attribute), the link is accessible via either the objet's __proto__ attribute or more standardly via what you get with Object.getPrototypeOf(someobject), and it's not only for methods (like in C++/Java) but for properties as well.
The only difference between foo1 = {} and foo2 = new Bar is the fact that foo1.__proto__ == Object.prototype, whereas foo2.__proto__ == Bar.prototype. In JavaScript there are no classes and no instances, only plan objects.
Now, if you set Bar.prototype.property = "value", then looking up foo2.property first checks, whether foo2 has its own property called property. If it does not, it continues with foo2.__proto__ until it finds an object that does have an own property called property or until it gets to an object, whose __proto__ is null (usually Object.prototype).
It should now be obvious that by declaring Bar.prototype.property, you are setting up the default value, which looking up foo2.property resolves to, when it doesn't have its own property property. Setting up foo2.property in the constructor defines foo2's own property. You could call it an instance variable, but really, it's just a hash map key.
In this Udacity video on game development, the instructor mentions that Javascript allows us to create an object by giving a handle to its definition. Then, it says that to allow this "an overloaded object definition will update a hash table with a pointer to its class definition".
I quite know what a hash table, a pointer, an overloaded method, and the factory pattern are, but I cannot make sense of this mysterious statement, or of the rest of the explanation.
"Hash table" is just a fancier way of saying "ordinary Javascript object". What the instructor means by "handle to its definition" is just another way of saying "the function that acts as a constructor for the class".
Ultimately, what he means by the statement you mentioned:
each overloaded entity definition will update a hash table with a pointer to its class definition
is the following:
All "subclasses" of Entity will register their constructor function in a single shared hashmap/object using the key which is the type value.
This allows you to get the constructor function (in other words, the function to call new on, which will return an instance of that entity) for any type by accessing gGameEngine.factory[type].
This is nice, because whenever a programmer adds a new type of entity, so long as they remember to add a new entry to that gGameEngine.factory object with the correct key, then that object will contain everything you need to construct any type of supported object.
So the code that iterates over the JSON structure generated by the level editor can create an instance of any type the same way, using something like:
var typeConstructor = gGameEngine.factory(tileSpec.type),
instance;
if (typeConstructor) {
instance = new(typeConstructor)(tileSpec /* or whatever params */);
}
This is similar to the code visible at around the 1 minute mark of the video you linked to.
Make sense now?
I think all he's saying is that you can map references to functions / objects / variables inside another object. He's using one type of property accessor syntax, but I think he's overcomplicating things by using language like 'handle' and 'hash table'.
var someClass = function () {
// stuff
}
var containingObject = {};
containingObject["someClass"] = someClass;
// same thing as
containingObject.someClass = someClass;
Then you can instantiate the class by calling the containingObject property.
var classInstance = new containingObject["someClass"]()
// or
var classInstance = new containingObject.someClass()
I have been digging deeper and deeper into JavaScript in an effort to set up a sound, maintainable inheritance model for a project I'm working on. I have come across some fantastic resources, one of which points out an interesting issue arising from pointing the prototype of a "class" to a new instance of another "class". It uses this article to illustrate the point.
Specifically, the article points out that creating instances of "Cat" via the following code (pulled from the second article linked above) will result in each instance of "Cat" pointing to the same single instance of "Mammal"
function Mammal(name){
this.name=name;
this.offspring=[];
}
Mammal.prototype.haveABaby=function(){
var newBaby=new Mammal("Baby "+this.name);
this.offspring.push(newBaby);
return newBaby;
}
Mammal.prototype.toString=function(){
return '[Mammal "'+this.name+'"]';
}
Cat.prototype = new Mammal();
Cat.prototype.constructor=Cat;
As the article that points this out (the first one linked above) shows, using this code results in the following:
var myPet = new Cat('Felix');
myPet.haveABaby();
var myPet2 = new Cat('Garfield');
myPet2.haveABaby();
console.log(myPet2.offspring); // returns ["","",...]
So, myPet2 has two elements in its offspring array. This isn't ideal as it has has only had one baby.
That all makes sense to me; however, what's confusing is, if you change this.offspring=[] to this.offspring=0 and then change this.offspring.push(newBaby) to this.offspring++, each new instance of "Cat" appears to have its offspring attribute set at 0.
var myPet = new Cat('Felix');
myPet.haveABaby();
var myPet2 = new Cat('Garfield');
myPet2.haveABaby();
console.log(myPet2.offspring); // returns 1
So, myPet2 has 1 offspring. This is what should happen.
Why does this appear to reset this.offspring each time, whereas the array/.push() approach does not? My initial thought is that it has something do with with an array being treated as an object and thus any 'offspring' property of the Mammal type will always refer to the same thing, whereas an integer is a primitive value that is created anew each time. Yes?
Either way, aren't these two outcomes at odds with one another as far as whether or not a new instance of Mammal is created for each new Cat?
Each instance of Cat creates a new instance of an Object object that has prototype Mammal. Note that while it's true that there is only one instance of Mammal, the this in both Cats are separate instances of Cat, not Mammal. What is happening is not caused by the fact that both Cat share a Mammal prototype, but because arrays are references, not values.
Thus, while there are two Cats and both Cats this are really separate instances, they both share the same array offspring.
This illustrates what's happening without the confusion of objects, constructors and prototypes:
var a=[];
var b=a;
a.push('hello');
alert(b[0]); // alerts 'hello'.
Contrast this to things that are values in javascript (strings and numbers):
var a=0;
var b=a;
a++;
alert(b); // alerts 0
Reference types (arrays & objects) merely point to the underlying object. Thus when a variable with reference type is assigned to another variable they both share the same object (only the address is copied, not the object itself).
In contrast, value types (numbers & strings) get copied when assigned to another variable.
Additional answer
One subtle side effect of this is that you can break the shared offspring reference between the Cats by reassigning one of them to another array:
myPet.offspring = [new Mammal('Kitty'), new Mammal('Spot')];
alert(myPet2.offspring.length); // alerts 0
// Because the code above causes the
// `offspring` property of myPet to
// point to a different array.
Already answered this today, you can find it here:
https://stackoverflow.com/a/26337868/1641941
Those mdn articles don't look like Mozilla developer network articles I suggest using this one as it doesn't create an instance of Parent to set prototype part of inheritance and doesn't modify objects you don't own to achieve a simple task as inheritance:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create?redirectlocale=en-US&redirectslug=JavaScript%2FReference%2FGlobal_Objects%2FObject%2Fcreate
Could someone explain this to me in a sensible way:
function One() {}
One.prototype.obj = { key: 'value' };
One.prototype.str = 'string';
var inst1 = new One(),
inst2 = new One();
// now let’s change some things in our second instance
inst2.obj.key = 'buh!';
inst2.str = 'buh!';
// ok, so what happens to our other instance?
console.log( inst1.str ); // Yields 'string' (unaffected, expected)
console.log( inst1.obj.key ); // Yields 'buh!' (!!)
console.log( One.prototype.obj.key ); // is also 'buh!'
It seems that if a prototype contains an object, the instance you create using the new keyword has that object, but if you change it, you also change the prototype object, thus affecting all instances, like a sibling-inheritance-pattern...
Is this the way it’s suppose to work?
Actually, Javascript doesn't copy anything from the prototype. Everything you define on the prototype exists only once (on the prototype itself) and gets reused because the same prototype instance is passed to all objects.
When you access a property on an object, the object checks to see if it is defined on itself. If it is, it will return the value associated with that property. If it's not, it will delegate the call to its prototype, who will from now on be responsible for what happens. That's why "inheritance" (code reuse) in Javascript is better called delegation.
Things are a bit different for write access. If you set a property on the object, it will "shadow" the value locally. That's the reason why the str property is unaffected, it has actually been defined on the inst2 object. But if you delete inst2.str and do another console.log( inst2.str ) you will notice that it will return the old value.
PS:
If you want a way to prevent that from happening have a look at this tutorial: http://kevlindev.com/tutorials/javascript/inheritance/index.htm
I recommend reading the entire thing, but if you just want the meat see the KevLinDev.extend function in the "Creating a subclass" section.
In short, yes. Javascript does not implicitly copy objects for you, so when you create the object literal at obj, all instances of the One class simply refer to it via reference. Instead, you need to dynamically create the obj object in the constructor:
function One(){
this.obj = {key:'value'};
}
See also: javascript multidimensional object