I understand how to instantiate objects and call them, but I just cannot find a reason to use them in my script. I could do
var obj = {
hi: function() {
return "Hello";
}
};
but why can't I just do it the same way like:
function hi() {
return "Hello";
}
I've never understood the reasons why I should use prototyping either. Most of the things I do in JavaScript I can do well without objects. But I want to use objects. What are objects for and what are the reasons why I should use them?
Objects are useful for example for making a single unit out of values that belong together. Example:
function Person(firstName, lastName, gender, age) {
this.firstName = firstName;
this.lastName = lastName;
this.gender = gender;
this.age = age;
}
Person.prototype = {
getFullName: function() { return this.firstName + ' ' + this.lastName; },
isMale: function() { return this.gender == 'Male'; },
isFemale: function() { return this.gender == 'Female'; }
};
var amanda = new Person('Amanda', 'Smith', "Female", 42);
var john = new Person('John', 'Doe', 'Male', 72);
alert(amanda.getFullName());
alert(john.isMale());
Compared to the less structured:
function getFullName(firstName, lastName) {
return firstName + ' ' + lastName;
}
function isMale(gender) {
return gender == 'Male';
}
function isFemale(gender) {
return gender == 'Female';
}
var amandaFirstName = 'Amanda';
var amandaLastName = 'Smith';
var amandaGender = 'Female';
var amandaAge = 42;
var johnFirstName = 'John';
var johnLastName = 'Doe';
var johnGender = 'Male';
var johnAge = 72;
alert(getFullName(amandaFirstName, amandaLastName));
alert(isMale(johnGender));
Objects are useful because
They are stateful.
They can store relations between strings and data.
It can be easier to decompose a problem by breaking it up into objects that collect related operations and state.
If you don't need non-global state, have no need of lookup tables, and your problem is small or more easily decomposed functionally then don't use objects.
Without what you are referring to as objects, you are going to have loose functions all over the place. This very often will result in code that is very difficult to maintain. At a bare minimum objects give you the ability to lump functions together in order to simulate namespaces-- and that's at a bare minimum.
In your simple example, it makes indeed no sense to write a semi "class" / object to hold that method. But when your code grows, you're getting more and more functions and methods, you don't really want to have them all in one big (global) namespace. That is just so impossible to maintenain, no one will understand that code including you at some later point.
That is the first good reason to wrap methods together in an object/"class". Another good reason is re-usabilty. If you're writting objects which are able to inherit their methods, you can re-create another object and abstract it from there on. Most simple concept, but you want to use it if you're describing "things" in your application as module/object.
It tries to simulate the OOP paradigm that's all. There are various ways of doing this. But ask yourself, doe 'hi' belong in 'obj' or can it be a standalone function? Its all about how closely related is the function to the object. Does the function needs to access the objects private variables and such?
This is less of a "objects in Javascript" and more of an objects in general" question.
I'd say the most relevant Javascript The only thing Javascript specific about objects is their neat use when namespacing. For example, most Javascript libraries pack all their stuff in a single object to avoid namespace collision:
dojo.create( ... )
dojo.connect( ... )
As for the other questions of why OOP, there are 2 basic things I think OOP excels at (generic, dumb, examples follow):
Dynamic dispatching - get rid of "ifs" and put responsabilitty where it belongs
When you look at a code that has tons of "switchs":
function doStuff(animal){
if animal is a tiger:
print_tiger_roar();
else if animal is a cow
print_cow_moo();
if animal is a tiger:
print_tiger_wants_meat();
else if animal is a cow
print cow_wants_grass();
It might be a good idea to bundle each different kind of behaviour in a different kind of object and use dynamic dispatching instead:
function doStuff(animal):
animal.print_speak();
animal.print_food_type();
Now, if you come up with another kind of animal in the future, you don't need to go looking around your code to add it - all you need to do is create a new class with the appropriate print_speack and print_food_type methods and the rest of the code won't notice a thing.
Inheritance + reusing methods
In a normal OO language each object stores (and spends memory) for its instance variables, while all methods + static variables are stored in a single place by the class. Javascript doesn't have classes, but it has prototypes and they serve the same basic function in the end.
Some generic thoughts concerning "Why" part:
Objects exist to communicate. It is a common vocabulary for everyone involved in a project. People are used to operate with things (objects) and their operations (messages or methods), rather than just with disconnected actions (functions).
Related
Read about constructors in functions:
function Animal(name) {
this.name = name;
this.canWalk = true;
}
var animal = new Animal("Hedgehog");
and also about prototypes:
Animal.prototype.draw = function () {
}
But until the end I did not understand exactly how they reduce the code and, in principle, improve the life of programmers. Why? Because it is better understood on real examples from sites and not on examples of animal or "hedgehogs" of all sorts.
An example from my personal experience: I started the cycles well when I needed to prescribe a function for 30 images, but instead of 30 functions I passed one function into a cycle and reduced it the way the code, so I understood the whole essence of the cycle, and not just memorized its anatomy. That would be for learning resources to make examples of real projects beginners would not ask 100 questions of the same type.
Therefore, I have such questions:
Can you write here how the code would look at first without a prototype and then with a prototype on some small example from the site? Or an example that could be implemented on which site.
Can you write here how the code would look at first without a constructor and then with a prototype on some small example from the site? Or an example that could be implemented on which site.
But do not post in the responses or comments a link from the GitHuB with a large code. Just give a small example here. And it is desirable not an example from the game, but from the site
Using an object constructor is a way to initialize an instance with a specific functionality. In most cases it is used to initialize properties with values (like in your code), but can be used for other things as well.
Let use more realistic example - I can initialize a few users object simply by object literals:
const user1 = {
id: 'usr123',
name: 'Max',
questions: 4
}
const user2 = {
id: 'usr124',
name: 'Danny',
questions: 2
}
But there are few problems with this approach.
First, it can be tedious when used a lot.
Second, it's harder to distinguish it from other objects.
Both of these issues can be solved with construction function:
function User(id, name, questions) {
this.id = id;
this.name = name;
this.questions = questions ? questions : 0;
}
const user1 = new User('usr123', 'Max', 4);
const user2 = new User('usr125', 'Ben'); // default questions value would be 0
const isUser = user1 instanceof User; // true
Prototype is a special object which can be used on Objects which has a constructor function (Well, all objects are descendant of Object, but let's leave this aside for a moment). The basic idea is - if I have 100 user objects - I might have some use for have a special properties or logic which relevant for all of them, and not specific for a single instance. For example, let's assume that in case of error, I would like to log all the data of the users.
I can create a special function which get and object and do this:
function userToString(user) {
return user.id + ':' + user.name + '[' + user.questions + ']'; // usr123:Max[4]
}
This would work, but harder to maintain, since it is not really part of "User".
I large projects I would probably put this function in a file with other utilities function, and call it every time i would like to use it.
Another option is to include it as part of the prototype:
User.prototype.toString() {
return this.id + ':' + this.name + '[' + this.questions + ']';
}
user1.toString(); // usr123:Max[4]
I would strongly suggest to using ES6 standard (at least). It's exist for several years, it looks much more intuitive and do some of the complex work for you.
In ES6 this code would look like this:
class User {
constructor(id, name, questions) {
this.id = id;
this.name = name;
this.questions = questions ? questions : 0;
}
toString() {
return this.id + ':' + this.name + '[' + this.questions + ']';
}
}
Look nicer isn't it? but it basically the same. This ES6 syntax is simply sugar coating for the older syntax you've included in your question.
how can i do prototypal inheritance in javasciript. usually i do by this
and
derivedFn.prototype = object.create(clsParent.prototype)
but today i got we can also do this the result is same so what is the differce
derivedFn.prototype = clsParent.prototype
For example
function clsParent() {
this.myName = "faizan"
this.getMyName = function() {}
}
clsParent.prototype.aProp = "property in prototype"
function clsChild() {
this.Fname = "abr"
}
clsChild.prototype = clsParent.prototype; //what is the difference
//Object.create(clsParent.prototype);
// what is the difference if i do inheritance by this
var myObj = new clsChild();
console.log(myObj.myName);
console.log(myObj.aProp);
code is given please clarify me the difference of these two ways inheritance
When you say
clsChild.prototype = clsParent.prototype;
You are making both the clsChild and clsParent's prototypes the same. So, if you make changes to clsChild.prototype, the changes will be visible in any objects created with new clsParent() as well.
Try,
clsChild.prototype.a = 1000;
console.log(new clsParent().a);
// 1000
But when you do Object.create(clsParent.prototype), it will create a brand new object which extends from clsParent.prototype. So, making changes to clsChild.prototype will not affect clsParent.prototype.
Suggestion:
It is usually a bad idea to store a property in the prototype, since it will be shared by all the instances. You should do this only if your usecase demands it.
clsParent.prototype.aProp = "property in prototype"; // Don't do this
In addition to what thefourtheye said. I think it's mostly a matter of clarity. It's easier to think about objects when each class has an object to represent it. Additionally it's probably the most common way of implementing inheritance, which also makes it easier to understand.
Also there are no technical reasons not to store primitives values in a prototype. But it becomes confusing when you define integer properties in one part of the file, and array properties in another.
So JavaScript is a functional language, classes are defined from functions and the function scope corresponds to the class constructor. I get it all now, after a rather long time studying how to OOP in JavaScript.
What I want to do is not necessarily possible, so I first want to know if this is a good idea or not. So let's say I have an array and a class like the following:
var Entry = function(name, numbers, address) {
this.name = name;
if(typeof numbers == "string") {
this.numbers = [];
this.numbers.push(numbers);
}
else this.numbers = numbers;
this.address = address;
};
var AddressBook = [];
And I add contacts with the following function:
function addContact(name, numbers, address) {
AddressBook.push(new Entry(name, numbers, address));
}
Can't I make it so new Entry() would put itself into AddressBook? If I can't do this on create, it would be interesting to do it with a method in the Entry prototype as well. I couldn't figure out a way to do anything similar.
You could try passing the AddressBook array reference to the function like such:
var Entry = function(name, numbers, address, addressBook) {
this.name = name;
if(!(numbers instanceof Array)) {
this.numbers = [numbers];
}
else this.numbers = numbers;
this.address = address;
addressBook.push(this);
};
var addressBook = [];
function addContact(name, numbers, address) {
new Entry(name, numbers, address, addressBook)
}
Reconsider the design approach. The "Entry" object's primary role is Information Holder. You should encapsulate the AddToAddressBook functionality in some sort of a controller or eventHandler.
Details
You've got more than 1 responsibility and it's generally not a good idea to tightly couple the 2 concerns. (e.g. Design principles involved Single Responsibility Principle and Separation of Concerns.)
Information holder – an object designed to know certain information and provide that information to other objects.
Structurer – an object that maintains relationships between objects and information about those relationships.
I'd suggest reading up on SOLID principles and try to keep each object's responsibilities narrowly focused. Your code will be less complex and easier to maintain and extend going forward.
Check out - http://aspiringcraftsman.com/series/solid-javascript/
There's a example of products and cart which is pretty close to your scenario above.
I have been looking into the possibility of reflection in JavaScript. I already have a simple reflector which can list the members of an object/function, like so:
window["Foo"] = {
"Bar": {
"Test": function () {
this.x = 32;
this._hello = "Hello World";
this._item = 123.345;
this.hello = function() {
alert("hello");
};
this.goodbye = function() {
alert("goodbye");
}
}
}
}
$(document).ready(function () {
var x = new Foo.Bar.Test();
Reflect(new Foo.Bar.Test());
});
function Reflect(obj) {
for (var item in obj) {
$("body").append(item + "(" + typeof obj[item] + ") = " + obj[item] + "<br />");
}
}
Results:
x(number) = 32
_hello(string) = Hello World
_item(number) = 123.345
hello(function) = function () { alert("hello"); }
goodbye(function) = function () { alert("goodbye"); }
The next part of my challenge is to build something which can reflect back (if possible) an objects name, and the path to the object.
using this example:...
var x = new Foo.Bar.Test();
How can I reflect back "Test", from x? For example:
ReflectName(x); //returns "Test";
Also how can I reflect back the path to x? For example:
ReflectPath(x) //returns Foo.Bar.Test
Is is possible to do these two things using JavaScript? I have researched this, and so far have not managed to come up with any viable solutions.
I do not want a solution that requires hard coding the name and path of the object/function, as this would defeat the point of using reflection.
There are no classes in JavaScript (although due to code style which for reasons unknown to me imitates Java you could think there are some). Foo.Bar.Test does not mean class Test registered in namespace Foo.Bar, but function which is assigned as attribute Test of some object which is assigned as attribute Bar of some object known as Foo.
You can't do reflection like "give me all variables to which number 7 is assigned", consequently you can't list all the objects which hold Test in one of their attributes.
This is actually good and opens new possibilities, but might be confusing in the beginning.
BTW Since there are no classes in JavaScript, I believe term reflection is not very fortunate. And new Foo() does not mean "create new instance of Foo", but "create a new object and execute function Foo in context of that object, and finally return it. Yeah, the new keyword is very confusing, if you want to do anything more advanced in JavaScript, never trust your Java/C# experience. JavaScript fakes Java (I suppose to not scare newcomers and allow them to do easy things quickly), but it's very different.
This is not possible in JavaScript. (To get a deeper understanding of JavaScript's type system, I recommend reading this.)
The best approximation you can do is querying over a static JSON structure.
Answer to your first question
function ReflectName(obj) { return obj.__proto__.constructor.name }
Second question is a bit more difficult and would require more setup with the definitions.
It is answered a bit better here: Javascript objects: get parent
I've read pages and pages about JavaScript prototypal inheritance, but I haven't found anything that addresses using constructors that involve validation. I've managed to get this constructor to work but I know it's not ideal, i.e. it's not taking advantage of prototypal inheritance:
function Card(value) {
if (!isNumber(value)) {
value = Math.floor(Math.random() * 14) + 2;
}
this.value = value;
}
var card1 = new Card();
var card2 = new Card();
var card3 = new Card();
This results in three Card objects with random values. However, the way I understand it is that each time I create a new Card object this way, it is copying the constructor code. I should instead use prototypal inheritance, but this doesn't work:
function Card(value) {
this.value = value;
}
Object.defineProperty( Card, "value", {
set: function (value) {
if (!isNumber(value)) {
value = Math.floor(Math.random() * 14) + 2;
}
this.value = value;
}
});
This doesn't work either:
Card.prototype.setValue = function (value) {
if (!isNumber(value)) {
value = Math.floor(Math.random() * 14) + 2;
}
this.value = value;
};
For one thing, I can no longer call new Card(). Instead, I have to call var card1 = new Card(); card1.setValue(); This seems very inefficient and ugly to me. But the real problem is it sets the value property of each Card object to the same value. Help!
Edit
Per Bergi's suggestion, I've modified the code as follows:
function Card(value) {
this.setValue(value);
}
Card.prototype.setValue = function (value) {
if (!isNumber(value)) {
value = Math.floor(Math.random() * 14) + 2;
}
this.value = value;
};
var card1 = new Card();
var card2 = new Card();
var card3 = new Card();
This results in three Card objects with random values, which is great, and I can call the setValue method later on. It doesn't seem to transfer when I try to extend the class though:
function SpecialCard(suit, value) {
Card.call(this, value);
this.suit = suit;
}
var specialCard1 = new SpecialCard("Club");
var specialCard2 = new SpecialCard("Diamond");
var specialCard3 = new SpecialCard("Spade");
I get the error this.setValue is not a function now.
Edit 2
This seems to work:
function SpecialCard(suit, value) {
Card.call(this, value);
this.suit = suit;
}
SpecialCard.prototype = Object.create(Card.prototype);
SpecialCard.prototype.constructor = SpecialCard;
Is this a good way to do it?
Final Edit!
Thanks to Bergi and Norguard, I finally landed on this implementation:
function Card(value) {
this.setValue = function (val) {
if (!isNumber(val)) {
val = Math.floor(Math.random() * 14) + 2;
}
this.value = val;
};
this.setValue(value);
}
function SpecialCard(suit, value) {
Card.call(this, value);
this.suit = suit;
}
Bergi helped me identify why I wasn't able to inherit the prototype chain, and Norguard explained why it's better not to muck with the prototype chain at all. I like this approach because the code is cleaner and easier to understand.
the way I understand it is that each time I create a new Card object this way, it is copying the constructor code
No, it is executing it. No problems, and your constructor works perfect - this is how it should look like.
Problems will only arise when you create values. Each invocation of a function creates its own set of values, e.g. private variables (you don't have any). They usually get garbage collected, unless you create another special value, a privileged method, which is an exposed function that holds a reference to the scope it lives in. And yes, every object has its own "copy" of such functions, which is why you should push everything that does not access private variables to the prototype.
Object.defineProperty( Card, "value", ...
Wait, no. Here you define a property on the constructor, the function Card. This is not what you want. You could call this code on instances, yes, but note that when evaluating this.value = value; it would recursively call itself.
Card.prototype.setValue = function(){ ... }
This looks good. You could need this method on Card objects when you are going to use the validation code later on, for example when changing the value of a Card instance (I don't think so, but I don't know?).
but then I can no longer call new Card()
Oh, surely you can. The method is inherited by all Card instances, and that includes the one on which the constructor is applied (this). You can easily call it from there, so declare your constructor like this:
function Card(val) {
this.setValue(val);
}
Card.prototype...
It doesn't seem to transfer when I try to extend the class though.
Yes, it does not. Calling the constructor function does not set up the prototype chain. With the new keyword the object with its inheritance is instantiated, then the constructor is applied. With your code, SpecialCards inherit from the SpecialCard.prototype object (which itself inherits from the default Object prototype). Now, we could either just set it to the same object as normal cards, or let it inherit from that one.
SpecialCard.prototype = Card.prototype;
So now every instance inherits from the same object. That means, SpecialCards will have no special methods (from the prototype) that normal Cards don't have... Also, the instanceof operator won't work correctly any more.
So, there is a better solution. Let the SpecialCards prototype object inherit from Card.prototype! This can be done by using Object.create (not supported by all browsers, you might need a workaround), which is designed to do exactly this job:
SpecialCard.prototype = Object.create(Card.prototype, {
constructor: {value:SpecialCard}
});
SpecialCard.prototype.specialMethod = ... // now possible
In terms of the constructor, each card IS getting its own, unique copy of any methods defined inside of the constructor:
this.doStuffToMyPrivateVars = function () { };
or
var doStuffAsAPrivateFunction = function () {};
The reason they get their own unique copies is because only unique copies of functions, instantiated at the same time as the object itself, are going to have access to the enclosed values.
By putting them in the prototype chain, you:
Limit them to one copy (unless manually-overridden per-instance, after creation)
Remove the method's ability to access ANY private variables
Make it really easy to frustrate friends and family by changing prototype methods/properties on EVERY instance, mid-program.
The reality of the matter is that unless you're planning on making a game that runs on old Blackberries or an ancient iPod Touch, you don't have to worry too much about the extra overhead of the enclosed functions.
Also, in day-to-day JS programming, the extra security from properly-encapsulated objects, plus the extra benefit of the module/revealing-module patterns and sandboxing with closures VASTLY OUTWEIGHS the cost of having redundant copies of methods attached to functions.
Also, if you're really, truly that concerned, you might do to look at Entity/System patterns, where entities are pretty much just data-objects (with their own unique get/set methods, if privacy is needed)... ...and each of those entities of a particular kind is registered to a system which is custom made for that entity/component-type.
IE: You'd have a Card-Entity to define each card in a deck.
Each card has a CardValueComponent, a CardWorldPositionComponent, a CardRenderableComponent, a CardClickableComponent, et cetera.
CardWorldPositionComponent = { x : 238, y : 600 };
Each of those components is then registered to a system:
CardWorldPositionSystem.register(this.c_worldPos);
Each system holds ALL of the methods which would normally be run on the values stored in the component.
The systems (and not the components) will chat back and forth, as needed to send data back and forth, between components shared by the same entity (ie: the Ace of Spade's position/value/image might be queried from different systems so that everybody's kept up to date).
Then instead of updating each object -- traditionally it would be something like:
Game.Update = function (timestamp) { forEach(cards, function (card) { card.update(timestamp); }); };
Game.Draw = function (timestamp, renderer) { forEach(cards, function (card) { card.draw(renderer); }); };
Now it's more like:
CardValuesUpdate();
CardImagesUpdate();
CardPositionsUpdate();
RenderCardsToScreen();
Where inside of the traditional Update, each item takes care of its own Input-handling/Movement/Model-Updating/Spritesheet-Animation/AI/et cetera, you're updating each subsystem one after another, and each subsystem is going through each entity which has a registered component in that subsystem, one after another.
So there's a smaller memory-footprint on the number of unique functions.
But it's a very different universe in terms of thinking about how to do it.