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];
}
}
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.
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());
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.
I receive a bunch of objects via JSON which ultimately need to have some instance member functions.
Is there a way to do this without copying the data?
For example:
var DataObject = function() {};
DataObject.prototype.add = function() { return this.a + this.b; };
var obj = JSON.parse('{"a":1, "b":2}');
// Do something to obj to make it inherit from DataObject
console.assert( obj.add() === 3 );
I've tried setting obj.prototype = DataObject.prototype but that doesn't seem to work. What am I missing?
Well, in ECMAScript6 (in IE11, and every other non ie browser today), that would be __proto__
obj.__proto__ = Object.create(DataObject.prototype);
[fiddle]
Generally, make sure you only do this at the object creation case, otherwise it can be very risky to do.
Also note, setting the protoype explicitly is not always faster than copying two properties, as you can see here so you have to be sure there is actual gain here.
So I am trying to learn javascript by learning how Mootools works internally. I am looking at these lines specifically:
var Type = this.Type = function(name, object){
if (name){
var lower = name.toLowerCase();
var typeCheck = function(item){
return (typeOf(item) == lower);
};
Type['is' + name] = typeCheck;
if (object != null){
object.prototype.$family = (function(){
return lower;
}).hide();
}
}
if (object == null) return null;
object.extend(this);
object.$constructor = Type;
object.prototype.$constructor = object;
return object;
};
//some more code
new Type('Type',Type);
What is happening here?
What is the object being assigned to in the constructor statement down at the bottom, the global window object?
Why is it being called as a constructor with the new statement when the Type function seems to only update the passed in object rather than creating a new one?
Specifically what is 'this' in the line object.extend(this); ? is it the global window object, if so is it adding all the key, value pairs of that object to the Type object?
Sheesh, questions lately seem to focus a lot more on mootools internals.
I will answer to the best of my knowledge as I am not a core dev.
Type in MooTools is pretty similar to Class (in fact, the Class constructor itself is a Type) but it focuses more on data / values and the Types of values. It also is meant to extend the native Types defined by ECMA spec and make them more flexible.
I guess there is no point in talking about data types in general (String, Number, Array, Object, etc). Why is there are need to extend them? Well, for starters, Duct Typing is a little quirky in js. typeof {}; // object, typeof []; // object, typeof new Date(); // object etc - not the most helpful, even if since all types inherit from object and is logical for them to be grouped together, it does not help you write code.
So, in the context of js objects, they are created from constructor objects...
What Type does is not replace the constructor functions but changes an existing constructor by adding new methods or properties to it.
eg. new Type('Array', Array);
This will turn the native Array constructor into a type object of sorts. You don't need to save the result or anything - it's a one off operation that mods the original and leaves it open for manipulation.
typeOf(Array); // type
So, what is different? Well, for starters, typeOf([]) is now able to actually tell us what it really is - array. And what really happens here is this: object.extend(Type);, the magical bit. It will copy to the target object all the properties defined on the Type object - you can see them here:
https://github.com/mootools/mootools-core/blob/master/Source/Core/Core.js#L211-232
So, immediately, your newly created Type gets the all important implement and extend methods.
More advanced, let's create a new type that is based on the native Array constructor:
var foo = new Type('foo', Array),
a = new foo();
// it's a real boy!
a.push('hi');
// ['hi'], foo, object
console.log(a, typeOf(a), typeof a);
But, what if we wanted a custom Type? One that is magical and special? No problem, because argument 2 can actually be a (anonymous) function.
var Awesome = new Type('awesome', function(name, surname) {
// console.log('I R teh construct0r!');
this.name = name;
this.surname = surname;
});
// extend it a little.
Awesome.implement({
getName: function() {
return this.name;
},
getSurname: function() {
return this.surname;
}
});
var Dimitar = new Awesome('dimitar', 'christoff');
console.log(typeOf(Dimitar)); // awesome
console.log(Dimitar.getName()); // dimitar
In another example, look at DOMEvent. It takes the above and makes it into a faster leaner Object type. https://github.com/mootools/mootools-core/blob/master/Source/Types/DOMEvent.js#L21
So why is that not a class? Because, Classes are more expensive and events happen all the time.
I hope this helps you somewhat. for a more detailed explanation, ask on the mailing list and hope for the best, perhaps a core dev will have time as it's not your standard 'how do I get the accordion working' type of question...