I was wondering if the following code would be considered a "has-a" relationship instead of an "is-a" relationship. I was wondering if this is to be considered "tightly - coupled ". I'm trying to keep certain variables private. Using Symbols I can somewhat keep them hidden. I write getFirstName() to make it shorter, this also allows me to know what Mixin it came from. I just wanted some feed back, I'm still a newbie. I can't really find anything on google on object composition with Javascript. I have tried to do mixins by assigning them to the prototype. My understanding is that object composition is an object made with other objects.
let InfoMixin = (function(){
let firstName = Symbol();
function infoMix(first){
this[firstName] = first;
}
infoMix.prototype.getFirstName = function(){
return this[firstName];
};
return infoMix;
})();
function Student(first){
this.infoMix = new InfoMixin(first);
}
Student.prototype.getFirstName = function(){
return this.infoMix.getFirstName();
}
let student1 = new Student('Nick');
alert(student1.getFirstName());
Related
I have been fiddling around with object building via composition in Javascript (specifically NodeJS) and I have come up with a way of building up my objects but I need to know if this is an insane way of doing things.
The simple version is this:
I have two objects, both have two properties, one holding a number and the other holding a string.
File: Cat.js
function Cat() {
this.name = 'Fuzzy Whiskerkins';
this.owner = 'James';
}
module.exports = Cat;
File: Car.js
function Car() {
this.color = 'blue';
this.owner = 'James';
}
module.exports = Car;
I would like to now add a basic getter/setter function for all properties in both of these objects. I would also like to be able to check that the value passed into these setters matches the type. Instead of writing four prototype functions for each of these properties I have done the following:
File: StringProperty.js
module.exports = function(newObject, propertyName) {
newObject.prototype[propertyName] = function( newString ) {
if ( typeof newString !== 'undefined' ) {
if ( typeof newString !== 'string' ) {
return;
}
this.properties.[propertyName] = newString;
return this;
}
return this.properties.[propertyName];
}
}
File: Cat.js
var StringProperty = require('./StringProperty.js');
function Cat() {
this.properties.name = 'Fuzzy Whiskerkins';
this.properties.owner = 'James';
}
StringProperty( Cat, 'name' );
StringProperty( Cat, 'owner' );
module.exports = Cat;
File: Car.js
var StringProperty = require('./StringProperty.js');
function Car() {
this.properties.color = 'blue';
this.properties.owner = 'James';
}
StringProperty( Car, 'color' );
NumberProperty( Car, 'owner' );
module.exports = Car;
Now both objects have all the basic functionality they need and I was able to do it with a minimal amount of code and whenever I need to add another string property the amount of code I will have to add will be minimal.
Am I crazy? Is this an insane thing to/is there a better way to be doing this?
EDIT:
What I am trying to accomplish with this is the application I am working on has 100+ objects and each with 10+ properties and the idea of having to write almost the exact same code for every single one of those properties does not set well with me. I would prefer to be able to have a bit of code that adds the property and creates the getter/setter functions (with adding options for divergence in property restrictions such as different length restrictions on string properties). I have looked at multiple examples of object construction via composition in JS but nothing I tried fit into the NodeJS module structure.
Your solution will not work. You're shadowing the accessor method as soon as you set a value. Also, why are you testing for typeof !== "number" on in a method that expects a string?
Resolving those issues, your type checking just silently exits. You'll hate that once you try to set a value and can't figure out why it's not setting. I'd use TypeScript if you want a stronger type system.
I think you'd be better off trying to write idiomatic JS code. Use the features the language provides in their simplest and most direct manner. Don't try to be too clever with these constructs. Before JS had all its new features, people tried stuff like this, and it never seemed to go that well.
Is there any difference in how these functions operate? The first one is more typically of what I think about when thinking of a constructor.
Example 1: using this to name and set properties. Then using new to create a new Book object.
function Book(name, numPages) {
this.name = name;
this.numPages = numPages;
}
var myBook = new Book('A Good Book', '500 pages');
Example 2: returning a object by using new and just calling the function itself.
function Movie(name, numMinutes) {
return { name:name, numMinutes:numMinutes };
}
var best = new Movie('Forrest Gump', '150');
var other = Movie('Gladiator', '180');
I guess what I'm trying to figure out is if these are different in the way they create an object? If so is one better than the other? Are there different situations where one would work better over the other?
The first one is a constructor, and can therefore be extended by a prototype, and you can test via instanceof wether the result is an Instance of this type.
Downside: if you forget the new-keyword your code will blow up (unless you write a workaround for that into each constuctor)
And you can't really use apply() with a constructor to pass an array of arguments, when you instantiate a new Object; on the other hand, don't do that, even if you can/could.
The second one is a factory, not a constructor. Independant wether you use the new-keyword or not.
with this implementation it creates Objects that look the same but don't share a type or prototype (although the underlying JS-engine recognizes them as similar and so they share the same hidden Class as long as they have the same properties, added in the same order, ... different topic)
long story short, neither performance nor memory-footprint suffer from this approach (anymore)
But you can't check wether they are of the same type, and you don't have a shared prototype that may affect all instances (maybe a pro or a con.)
My goto-approach If I need inheritance, is kind of a mix of both:
(if I just need a data-object I usually use a factory and plain objects).
function Book(conf) {
var book = Object.create(Book.prototype);
//a book like this usually has multiple configs/properties
if(typeof conf === "object"){
for(var k in conf) book[k] = conf[k];
}else if(conf){
//assuming that I get at least the name passed
book.name = String(conf);
}
return book;
}
//I have a prototype that can be extended
//with default-values for example; no idea for a good method
//to add to the prototype in this example ;)
Book.prototype.numPages = 0;
//but I can also use it like a plain function; no error if you
var myBook1 = Book("Peter Pan");
var myBook2 = Book({
name: "American Gods",
author: "Neil Gaiman"
});
If I add the following line to the top of the function I can also use that as a method to cast anything into an Instance of Book without cloning already existing instances
function Book(conf) {
//with this simple line I can also use this as a function to cast anything into a "Book"
if(conf instanceof Book) return conf;
var book = Object.create(Book.prototype);
//...
return book;
}
var data = [
"Peter Pan",
{name: "American Gods"},
//...
];
var books = data.map(Book);
In my opinion, I have the benefits of both worlds with this approach.
Basically, when you use new, the JS engine makes a brand new object for you and injects that as the value of this. It also automatically gives you any methods attach to the prototype of the constructor. Using a constructor also allows you to check if an object is an instanceof something more easily.
function MovieA(title) {
this.title = title;
}
MovieA.prototype.getTitle = function() {
return this.title;
};
function MovieB(title) {
return {
title: title
};
}
MovieB.prototype.getTitle = function() {
return this.title;
};
var a = new MovieA('A');
console.log(a instanceof MovieA); // true
console.log(a.getTitle()); // 'A'
var b = MovieB('B');
console.log(b instanceof MovieB); // false
console.log(b.getTitle()); // Uncaught TypeError: b.getTitle is not a function
Everything that new offers you can be attained through other methods but requires more manual labor.
The second method, factories, tend to work better for unit testing, custom object creation and functional programming. It works better for unit testing because if you have a factory producing all of your objects, you can just replace that factory with a mock-up to test different cases.
var Factory = {
makeThing: function() {
return { name: 'thing' };
}
};
// Want to test the case for if makeThing fails inside of some other code
var MockFactory = {
makeThing: function() {
return null;
};
};
As for when you use either, it all depends. Some people don't use new at all. Others exclusively use new. It all depends on if you need any of the things listed above, how much control you need over the creation of objects, when you want to use this or not, etc. In the end, it's all a matter of preference.
The difference is the constructor used to create the object returned.
new Book('A Good Book', '500 pages');
creates a Book object instance, with the instance inheriting properties from Book.prototype, including a constructor property value of Book. The Book.prototype object itself inherits from Object.prototype.
var other = Movie('Gladiator', '180');
uses Movie as a factory function (new not required) and returns an Object object instance, with the instance inheriting properties directly fromObject.prototype, including a constructor property value of Object.
More briefly stated, Object literal syntax creates an Object object.
In a JavaScript code, we currently create a lot of objects using Method1 (see code). Would it be better to use Method2? (using .prototype) What would the benefits be? (Espescially interested in execution speed and memory usage.)
var exampleObjectFunction1 = function(){ alert(this.exampleProperty1);};
var exampleObjectFunction2 = function(){ this.myFunction1(); };
var exeampleProperties = {
exampleProperty1: 'example',
exampleProperty2: 'example',
};
//Method1: Current instanciation method
function exampleObject1(properties) {
this.exampleProperty1 = properties.property1;
this.examplePropertyX = properties.propertyX;
this.exampleObjectFunction1 = exampleObjectFunction1;
this.exampleObjectFunction2 = exampleObjectFunction2;
};
var exampleObject1 = new exampleObject(properties);
//Method2: Using prototype (better?)
function exampleObject2(properties) {
this.exampleProperty1 = properties.property1;
this.examplePropertyX = properties.propertyX;
};
exampleObject2.prototype.exampleObjectFunction1 = exampleObjectFunction1;
exampleObject2.prototype.exampleObjectFunction2 = exampleObjectFunction2;
var exampleObject2 = new exampleObject2(properties);
Edit: I see a lot of "constructor vs prototype" comparisons. But the "constructor" codes there usually redefine the functions inside the constructor while I pre-define them in re-usable variable. I think that this is a different scheme, though I am not quite sure if it's closer to "prototype" or to "constructor".
Let's say you create 1000 objects of exampleObject1 and 1000 objects of exampleObject2.
If you want to override exampleFunction1 for all exampleObject1 objects, you have to iterate through all your objects and change it.
If you want to do it for all exampleObject2 objects, you just change it's prototype in one place.
So, from the point of code extensibility is using of prototype better choice.
There's a handful of questions extremely similar to this, I know, but I can't seem to get anything to work.
For sake of brevity, I'll summarize this. I have this constructor function with strings assigned as values of the keys (assignment).
var Quote = function() {
this.quote1 = 'You can discover more about a person in an hour of play than in a year of conversation.';
this.quote2 = 'Nothing is at last sacred but the integrity of your own mind.';
this.quote3 = 'We have to fight them daily, like fleas, those many small worries about the morrow, for they sap our energies.';
this.quote4 = 'Ethics are so annoying. I avoid them on principle.';
this.quote5 = "Never trust anything that can think for itself if you can't see where it keeps its brain.";
};
module.exports = Quote;
Using AJAX I am printing the value of the keys inside the constructor to a static page. However... I am only successful in printing "quote1", "quote2", etc... (Just the name of the keys).
This is what my function for accessing the constructor looks like. My question is: How can I access the string values assigned to the keys inside the constructor? Is that possible?
Thank you in advance.
module.exports = function(object) {
var propArray = Object.keys(object);
var randomProp = propArray[Math.floor(Math.random() * propArray.length)];
return {quote: randomProp};
};
Inside your function, you should be able to access the quote by key using this:
object[randomProp]
In JavaScript, object properties can be accessed using square bracket notation. See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Working_with_Objects.
As you might have expected, there are several things wrong with your code :)
I've rewritten it with pretty thorough comments.
<script>
// create your 'Quote' class, which can be instantiated as many times as necessary
var Quote = function() {
this.quote1 = 'You can discover more about a person in an hour of play than in a year of conversation.';
this.quote2 = 'Nothing is at last sacred but the integrity of your own mind.';
this.quote3 = 'We have to fight them daily, like fleas, those many small worries about the morrow, for they sap our energies.';
this.quote4 = 'Ethics are so annoying. I avoid them on principle.';
this.quote5 = "Never trust anything that can think for itself if you can't see where it keeps its brain.";
};
// now let's set up the 'exports' method on the function's prototype
// this will allow any new instance of the Quote function to call or override this method
// without affecting the master 'Quote' class
Quote.prototype.exports = function() {
// you don't need to explicitly pass an object to this function
// just have it reference itself using the 'this' keyword
var propArray = Object.keys(this);
var randomProp = propArray[Math.floor(Math.random() * propArray.length)];
// objects in JavaScript can be handled like associative arrays
// simply access the key of 'this' with the value provided by 'randomProp'
return {quote: this[randomProp]};
};
// create a new instance of 'Quote'
// this guy can be used and manipulated independent of the master 'Quote' class
var module = new Quote();
// let's store the value returned by 'exports' in randomQuote
// note the () at the end of module.exports -- this tells JavaScript to treat the object as a function
var randomQuote = module.exports();
// write your quote to the document -- or do whatever else you want to with it at this point
document.write(randomQuote.quote);
</script>
Instead of return { quote: randomProp } you should use return object[randomProp].
You can access object properties via dot notation or square bracket notation.
Here's an example from jsbin
https://jsbin.com/yopeli/edit?js,console
I wonder, how to make such a thing in JavaScript or is such a stuff even possible in it?
For example, I have:
// ps: this code is abstract and just an idea, not real one
var A = function( inputInstance ) {
if ( inputInstance !== undefined )
this = inputInstance;
else
this = new B();
};
I'm interested in this possible or impossible stuff in JavaScript, because similar thing is possible in various functional programming languages, e.g. F#:
http://msdn.microsoft.com/en-us/library/dd233237.aspx
// This object expression specifies a System.Object but overrides the
// ToString method.
let obj1 = { new System.Object() with member x.ToString() = "F#" }
printfn "%A" obj1
It can be very useful, if such thing could be possible in JavaScript, but I suggest it isn't possible, because I don't want to set several properties from one instance just for a object copy:
this.id = inputObject.id;
this.guid = inputObject.guid;
this.data = inputObject.data;
...
I don't want to declare each member of inputObject, I want to set/copy all existed properties from one instance to another just by one elegant line like in functional languages like F#, so is it possible in JavaScript?
No, it is not possible. You can, however, use a loop.
for (var key in inputInstance) {
// Remove this if you want to copy inherited properties too
if (inputInstance.hasOwnProperty(key)) {
this[key] = inputInstance[key];
}
}