Copy and modify similar object for instantiation javascript - javascript

I have an object that looks like
var customObject = function() {
this.property = "value";
};
customObject.prototype = new otherObject();
customObject.prototype.property2 = function() {};
etc. - it's much bigger than this.
I can successfully instantiate the object by writing new customObject().
Now I would like to create a rather similar object, although a little different. This involves modifying certain properties and perhaps even adding or removing some. As in the above example, I would like it to be invokable by writing new customObject2().
I thought I could simply do:
var customObject2 = new customObject();
customObject2.prototype = customObject.prototype;
customObject2.property = "modified value";
etc.
However, when I try to instantiate it by doing new customObject2() I receive an error, stating that the customObject2 is not a function.
I hope I could illustrate well enough as to what pattern I desire to create. What approach should I take to create such a pattern?

If customObject is not a host object (i.e. won't give you an illegal invocation error if you try to call it differently to expected) you can apply the constructor to a different this Object;
var customObject2 = function () {
customObject.call(this); // construct as if `customObject`
// now do more stuff
this.anotherProperty = 'foo';
};
customObject2.prototype = Object.create(customObject.prototype);
// inherit prototype but keep original safe
new customObject2();
Backwards compatible Object.create
function objectWithProto(proto) {
var f;
if (Object.create) return Object.create(proto);
f = function () {};
f.prototype = proto;
return new f();
}

I think this should answer your question. Basically, the new keyword is returning an object and not a function.

Why are you not using the same formula you used the first time? For example:
var customObject2 = function(){};
customObject2.prototype = new customObject();
customObject2.property = "modified value";
new customObject2(); // works!
All properties of customObject will be inherited by the instances of customObject2 through the prototype chain.

Related

Trying to understand this code in Javascript

// Sim.App - application class (singleton)
Sim.App = function()
{
this.renderer = null;
this.scene = null;
this.camera = null;
this.objects = [];
}
// Constructor
EarthApp = function()
{
Sim.App.call(this);
}
// Subclass Sim.App
EarthApp.prototype = new Sim.App();
=============================================
In the above, I don't understand why the author used this statement
EarthApp.prototype = new Sim.App();
He could have used
EarthApp = new Sim.App();
Please help me understand the use of 'prototype' within that statement .
Prototypes are a fundamental piece in Javascript's inheritance model. I recommend you read about it, because without understading it you'll not "get" JS fully.
Having that said, assinging an object as a function's prototype makes this object be in a prototype chain of every instance of this function created afterwards.
The way prototype chain works is (more or less) (see example below):
You try to access "foo" variable in an object
If this object have "foo", return it's value.
If this object does not have "foo", look at it's prototype ('Sim.App' instance in your case) - does it have "foo"? If so, return it's value.
If object's prototype does not have a "foo", look at prototype's prototype - and so on, up through the chain.
If you want to read more on that, have a look at this article.
Example - consider:
var Sim = {};
Sim.App = function () {
this.foo = 'sim';
}
EarthApp = function () {
}
EarthApp.prototype = new Sim.App();
var earth = new EarthApp();
// I can access earth.foo even though 'earth' is an instance of 'EarthApp'
// and not 'Sim.App'. That's because instance of 'Sim.App' is in
// earth's prototype chain.
console.log(earth.foo);
The line
EarthApp.prototype = new Sim.App();
...creates a Sim.App object and assigns it to the prototype property of the EarthApp function. That means that when we do this:
var e = new EarthApp();
...the e object will get the object from EarthApp.prototype as its prototype, giving it access to the properties and methods of that object.
FWIW, the inheritance implemented by that code isn't really ideal, because it's calling the Sim.App constructor to create the EarthApp.prototype object, then calling it again to initialize instances. If you want to chain constructors together in that way, here's the more correct way to do it:
// Reusable `derive` function
// Set up `child`'s `prototype` property to be based on `parent`'s `prototype` property
function derive(child, parent)
{
function ctor()
{
}
ctor.prototype = parent.prototype;
child.prototype = new ctor();
child.prototype.constructor = parent;
}
// Sim.App - application class (singleton)
Sim.App = function()
{
this.renderer = null;
this.scene = null;
this.camera = null;
this.objects = [];
};
// Constructor
EarthApp = function()
{
Sim.App.call(this);
};
// Subclass Sim.App
derive(EarthApp, Sim.App);
You might want to check out my Lineage helper script, which does the above and handles all the plumbing required to handle "supercalls" correctly and such.
It's also worth noting that this is just one way to use JavaScript's prototypical inheritance, which is tremendously flexible.

Javascript object creation using literals vs custom constructor functions

I understand that there are multiple ways to create an object in javascript and I have been reading that object literal syntax is generally preferred. (Correct?)
What I haven't been able to figure out is if there is ever a reason to use any of the other ways to create objects, such as a custom constructor function (var p = new Person("Adam"))? Is it true to use a custom constructor function only if I want private variables or to add methods or properties to its prototype? Is there no way to do these in a literal?
You can use the custom constructor function when you want to create instances of objects, similar to Java.
For example:
function MyObj(x){
this.x = x;
}
MyObj.prototype.printX = function(){
alert(this.x);
}
var obj1 = new MyObj("hello");
var obj2 = new MyObj("hello2");
obj1.printX();//prints hello
obj2.printX();//prints hello2
Now I have two instances of this object. If I used String literals I would need to clone the object into a new var in order to get another instance.
The discussion usually is about to prefer
var myObject = {};
over
var myObject = new Object();
If you however create your own constructor functions you are perfectly allowed to instantiate them with the new keyword, nothing controversial there.
The preferred method would be to use JSON: var p = { "name":"Adam" };
If you have a lot of member variables you need to initialize, or will be using a lot of objects (such as an array of them), etc. then it only makes sense to go ahead and create a function (constructor) which will do all of this for you. Unless you want your code to look like this:
var a = { "name":"Adam", "age":23, "city":"Boston" };
var b = { "name":"Jeff", "age":24, "city":"San mateo" };
var c = { "name":"Aaliyah", "age":25, "city":"New York" };
var d = { "name":"Mary", "age":26, "city":"Dallas" };

How do I retain the properties of a Javascript object while changing the object's constructor to an instance function

I have an instance function in javascript and for naming conventions I have other instance function added as property of the first instance function object. It's better illustrated in the following working JavaScript.
var MyModule = (function() { // instance function
return function() {
console.log("ran MyModule");
}
}());
MyModule.RelatedModule = (function() { //second instance function is a property of first instance function object
return function() {
console.log("ran RelatedModule");
}
}())
var inst1 = new MyModule(), // logs "ran MyModule"
inst2 = new MyModule.RelatedModule(); // logs "ran RelatedModule"
This works as intended with no errors. What I'd like to do though is to create the function definition for MyModule after I've created the MyModule object, can anyone help me achieve this? I've illustrated my attempts below.
var MyModule = {}; // create object first, try to set a constructor on it later
MyModule.RelatedModule = (function() { // add properties to the MyModule object
return function() {
console.log("ran RelatedModule");
}
}())
// the following does not work, I'd like to set the `MyModule` constructor instance function and retain the `MyModule.RelatedModule` property
MyModule.constructor = (function() {
return function() {
console.log("ran MyModule");
}
}());
So, how do I retain the properties of an object and change it's constructor?
You're confusing a couple of concepts. In your first example, MyModule doesn't have a constructor, it is a constructor. That is, it's a function object that you intend to use with the new operator to create new objects. Those objects will have a constructor property that points back to MyModule (the function that created them). Changing this constructor property won't have any effect on MyModule; that property is just a pointer back to the function that instantiated the object.
In other words, you can't change MyModule's constructor. That's a meaningless statement.
Now, when you write:
var MyModule = {};
...you create a new object whose constructor property is Object():
console.log(MyModule.constructor) // prints Object()
Again, changing this property doesn't really do much (except obfuscate some useful book-keeping).
At this point MyModule is just a plain-old object. It's not a function at all. That's why you're getting the "not a function" error. Because it's not, but you're trying to use it as though it is. If you want that name to refer to a function (i.e. to a different object) then you're going to lose all references to any properties you previously set, because you're pointing at an entirely new object.
That's just the way it is.
Now, you could save a reference to the object that contains all those previously-set properties and copy them back into MyObject once you've pointed that name at a function. But I'm not sure what the point would be.
Everything lwburk says is correct, however, the below does what you were trying to accomplish, it does this by calling an init() method from MyModule.
var MyModule = function(){
return this.init();
};
MyModule.prototype.init = function(){};
MyModule.RelatedModule = (function() { // add properties to the MyModule object
return function() {
console.log("ran RelatedModule");
};
}());
MyModule.prototype.init = function(){
console.log("ran MyModule");
};
var inst1 = new MyModule(),
inst2 = new MyModule.RelatedModule();
First, there is a known browser bug where the constructor property (of the constructed object) correctly resolves using the prototype, but is not applied in object construction. So you need the following polyfill:
function NEW(clas, ...args)
{
let res = Object.setPrototypeOf({}, clas.prototype);
res.constructor.apply(res, args);
return res;
}
Second, you need to be setting MyModule.prototype.constructor instead of MyModule.constructor. The reason is that MyModule.constructor is the function that constructs new classes, not the function that constructs new objects. (See: Why does a class have a "constructor" field in JavaScript?)
In other words:
var MyModule = {}; // create object first, try to set a constructor on it later
MyModule.RelatedModule = (function() { // add properties to the MyModule object
return function() {
console.log("ran RelatedModule");
}
}())
// set the `MyModule` prototype.constructor instance function and retain the `MyModule.RelatedModule` property
MyModule.prototype = {
constructor() {
console.log("ran MyModule");
}}
var inst1 = NEW(MyModule), // logs "ran MyModule"
inst2 = NEW(MyModule.RelatedModule); // logs "ran RelatedModule"
The short answer is that you can't do that. You can however change the prototype of an object. Check out this answer for insight into how to rethink your approach to work with this constraint: Changing constructor in JavaScript

Using "Object.create" instead of "new"

Javascript 1.9.3 / ECMAScript 5 introduces Object.create, which Douglas Crockford amongst others has been advocating for a long time. How do I replace new in the code below with Object.create?
var UserA = function(nameParam) {
this.id = MY_GLOBAL.nextId();
this.name = nameParam;
}
UserA.prototype.sayHello = function() {
console.log('Hello '+ this.name);
}
var bob = new UserA('bob');
bob.sayHello();
(Assume MY_GLOBAL.nextId exists).
The best I can come up with is:
var userB = {
init: function(nameParam) {
this.id = MY_GLOBAL.nextId();
this.name = nameParam;
},
sayHello: function() {
console.log('Hello '+ this.name);
}
};
var bob = Object.create(userB);
bob.init('Bob');
bob.sayHello();
There doesn't seem to be any advantage, so I think I'm not getting it. I'm probably being too neo-classical. How should I use Object.create to create user 'bob'?
With only one level of inheritance, your example may not let you see the real benefits of Object.create.
This methods allows you to easily implement differential inheritance, where objects can directly inherit from other objects.
On your userB example, I don't think that your init method should be public or even exist, if you call again this method on an existing object instance, the id and name properties will change.
Object.create lets you initialize object properties using its second argument, e.g.:
var userB = {
sayHello: function() {
console.log('Hello '+ this.name);
}
};
var bob = Object.create(userB, {
'id' : {
value: MY_GLOBAL.nextId(),
enumerable:true // writable:false, configurable(deletable):false by default
},
'name': {
value: 'Bob',
enumerable: true
}
});
As you can see, the properties can be initialized on the second argument of Object.create, with an object literal using a syntax similar to the used by the Object.defineProperties and Object.defineProperty methods.
It lets you set the property attributes (enumerable, writable, or configurable), which can be really useful.
There is really no advantage in using Object.create(...) over new object.
Those advocating this method generally state rather ambiguous advantages: "scalability", or "more natural to JavaScript" etc.
However, I have yet to see a concrete example that shows that Object.create has any advantages over using new. On the contrary there are known problems with it. Sam Elsamman describes what happens when there are nested objects and Object.create(...) is used:
var Animal = {
traits: {},
}
var lion = Object.create(Animal);
lion.traits.legs = 4;
var bird = Object.create(Animal);
bird.traits.legs = 2;
alert(lion.traits.legs) // shows 2!!!
This occurs because Object.create(...) advocates a practice where data is used to create new objects; here the Animal datum becomes part of the prototype of lion and bird, and causes problems as it is shared. When using new the prototypal inheritance is explicit:
function Animal() {
this.traits = {};
}
function Lion() { }
Lion.prototype = new Animal();
function Bird() { }
Bird.prototype = new Animal();
var lion = new Lion();
lion.traits.legs = 4;
var bird = new Bird();
bird.traits.legs = 2;
alert(lion.traits.legs) // now shows 4
Regarding, the optional property attributes that are passed into Object.create(...), these can be added using Object.defineProperties(...).
Object.create is not yet standard on several browsers, for example IE8, Opera v11.5, Konq 4.3 do not have it. You can use Douglas Crockford's version of Object.create for those browsers but this doesn't include the second 'initialisation object' parameter used in CMS's answer.
For cross browser code one way to get object initialisation in the meantime is to customise Crockford's Object.create. Here is one method:-
Object.build = function(o) {
var initArgs = Array.prototype.slice.call(arguments,1)
function F() {
if((typeof o.init === 'function') && initArgs.length) {
o.init.apply(this,initArgs)
}
}
F.prototype = o
return new F()
}
This maintains Crockford prototypal inheritance, and also checks for any init method in the object, then runs it with your parameter(s), like say new man('John','Smith'). Your code then becomes:-
MY_GLOBAL = {i: 1, nextId: function(){return this.i++}} // For example
var userB = {
init: function(nameParam) {
this.id = MY_GLOBAL.nextId();
this.name = nameParam;
},
sayHello: function() {
console.log('Hello '+ this.name);
}
};
var bob = Object.build(userB, 'Bob'); // Different from your code
bob.sayHello();
So bob inherits the sayHello method and now has own properties id=1 and name='Bob'. These properties are both writable and enumerable of course. This is also a much simpler way to initialise than for ECMA Object.create especially if you aren't concerned about the writable, enumerable and configurable attributes.
For initialisation without an init method the following Crockford mod could be used:-
Object.gen = function(o) {
var makeArgs = arguments
function F() {
var prop, i=1, arg, val
for(prop in o) {
if(!o.hasOwnProperty(prop)) continue
val = o[prop]
arg = makeArgs[i++]
if(typeof arg === 'undefined') break
this[prop] = arg
}
}
F.prototype = o
return new F()
}
This fills the userB own properties, in the order they are defined, using the Object.gen parameters from left to right after the userB parameter. It uses the for(prop in o) loop so, by ECMA standards, the order of property enumeration cannot be guaranteed the same as the order of property definition. However, several code examples tested on (4) major browsers show they are the same, provided the hasOwnProperty filter is used, and sometimes even if not.
MY_GLOBAL = {i: 1, nextId: function(){return this.i++}}; // For example
var userB = {
name: null,
id: null,
sayHello: function() {
console.log('Hello '+ this.name);
}
}
var bob = Object.gen(userB, 'Bob', MY_GLOBAL.nextId());
Somewhat simpler I would say than Object.build since userB does not need an init method. Also userB is not specifically a constructor but looks like a normal singleton object. So with this method you can construct and initialise from normal plain objects.
TL;DR:
new Computer() will invoke the constructor function Computer(){} for one time, while Object.create(Computer.prototype) won't.
All the advantages are based on this point.
Sidenote about performance: Constructor invoking like new Computer() is heavily optimized by the engine, so it may be even faster than Object.create.
You could make the init method return this, and then chain the calls together, like this:
var userB = {
init: function(nameParam) {
this.id = MY_GLOBAL.nextId();
this.name = nameParam;
return this;
},
sayHello: function() {
console.log('Hello '+ this.name);
}
};
var bob = Object.create(userB).init('Bob');
Another possible usage of Object.create is to clone immutable objects in a cheap and effective way.
var anObj = {
a: "test",
b: "jest"
};
var bObj = Object.create(anObj);
bObj.b = "gone"; // replace an existing (by masking prototype)
bObj.c = "brand"; // add a new to demonstrate it is actually a new obj
// now bObj is {a: test, b: gone, c: brand}
Notes: The above snippet creates a clone of an source object (aka not a reference, as in cObj = aObj). It benefits over the copy-properties method (see 1), in that it does not copy object member properties. Rather it creates another -destination- object with it's prototype set on the source object. Moreover when properties are modified on the dest object, they are created "on the fly", masking the prototype's (src's) properties.This constitutes a fast an effective way of cloning immutable objects.
The caveat here is that this applies to source objects that should not be modified after creation (immutable). If the source object is modified after creation, all the clone's unmasked properties will be modified, too.
Fiddle here(http://jsfiddle.net/y5b5q/1/) (needs Object.create capable browser).
I think the main point in question - is to understand difference between new and Object.create approaches. Accordingly to this answer and to this video new keyword does next things:
Creates new object.
Links new object to constructor function (prototype).
Makes this variable point to the new object.
Executes constructor function using the new object and implicit perform return this;
Assigns constructor function name to new object's property constructor.
Object.create performs only 1st and 2nd steps!!!
In code example provided in question it isn't big deal, but in next example it is:
var onlineUsers = [];
function SiteMember(name) {
this.name = name;
onlineUsers.push(name);
}
SiteMember.prototype.getName = function() {
return this.name;
}
function Guest(name) {
SiteMember.call(this, name);
}
Guest.prototype = new SiteMember();
var g = new Guest('James');
console.log(onlineUsers);
As side effect result will be:
[ undefined, 'James' ]
because of Guest.prototype = new SiteMember();
But we don't need to execute parent constructor method, we need only make method getName to be available in Guest.
Hence we have to use Object.create.
If replace Guest.prototype = new SiteMember();
to Guest.prototype = Object.create(SiteMember.prototype); result be:
[ 'James' ]
Sometimes you cannot create an object with NEW but are still able to invoke the CREATE method.
For example: if you want to define a Custom Element it must derive from HTMLElement.
proto = new HTMLElement //fail :(
proto = Object.create( HTMLElement.prototype ) //OK :)
document.registerElement( "custom-element", { prototype: proto } )
The advantage is that Object.create is typically slower than new on most browsers
In this jsperf example, in a Chromium, browser new is 30 times as fast as Object.create(obj) although both are pretty fast. This is all pretty strange because new does more things (like invoking a constructor) where Object.create should be just creating a new Object with the passed in object as a prototype (secret link in Crockford-speak)
Perhaps the browsers have not caught up in making Object.create more efficient (perhaps they are basing it on new under the covers ... even in native code)
Summary:
Object.create() is a Javascript function which takes 2 arguments and returns a new object.
The first argument is an object which will be the prototype of the newly created object
The second argument is an object which will be the properties of the newly created object
Example:
const proto = {
talk : () => console.log('hi')
}
const props = {
age: {
writable: true,
configurable: true,
value: 26
}
}
let Person = Object.create(proto, props)
console.log(Person.age);
Person.talk();
Practical applications:
The main advantage of creating an object in this manner is that the prototype can be explicitly defined. When using an object literal, or the new keyword you have no control over this (however, you can overwrite them of course).
If we want to have a prototype The new keyword invokes a constructor function. With Object.create() there is no need for invoking or even declaring a constructor function.
It can Basically be a helpful tool when you want create objects in a very dynamic manner. We can make an object factory function which creates objects with different prototypes depending on the arguments received.
You have to make a custom Object.create() function. One that addresses Crockfords concerns and also calls your init function.
This will work:
var userBPrototype = {
init: function(nameParam) {
this.name = nameParam;
},
sayHello: function() {
console.log('Hello '+ this.name);
}
};
function UserB(name) {
function F() {};
F.prototype = userBPrototype;
var f = new F;
f.init(name);
return f;
}
var bob = UserB('bob');
bob.sayHello();
Here UserB is like Object.create, but adjusted for our needs.
If you want, you can also call:
var bob = new UserB('bob');
While Douglas Crockford used to be a zealous advocate of Object.create() and he is basically the reason why this construct actually is in javascript, he no longer has this opinion.
He stopped using Object.create, because he stopped using this keyword altogether as it causes too much trouble. For example, if you are not careful it can easily point to the global object, which can have really bad consequences. And he claims that without using this Object.create does not make sense anymore.
You can check this video from 2014 where he talks at Nordic.js:
https://www.youtube.com/watch?v=PSGEjv3Tqo0
new and Object.create serve different purposes. new is intended to create a new instance of an object type. Object.create is intended to simply create a new object and set its prototype. Why is this useful? To implement inheritance without accessing the __proto__ property. An object instance's prototype referred to as [[Prototype]] is an internal property of the virtual machine and is not intended to be directly accessed. The only reason it is actually possible to directly access [[Prototype]] as the __proto__ property is because it has always been a de-facto standard of every major virtual machine's implementation of ECMAScript, and at this point removing it would break a lot of existing code.
In response to the answer above by 7ochem, objects should absolutely never have their prototype set to the result of a new statement, not only because there's no point calling the same prototype constructor multiple times but also because two instances of the same class can end up with different behavior if one's prototype is modified after being created. Both examples are simply bad code as a result of misunderstanding and breaking the intended behavior of the prototype inheritance chain.
Instead of accessing __proto__, an instance's prototype should be written to when an it is created with Object.create or afterward with Object.setPrototypeOf, and read with Object.getPrototypeOf or Object.isPrototypeOf.
Also, as the Mozilla documentation of Object.setPrototypeOf points out, it is a bad idea to modify the prototype of an object after it is created for performance reasons, in addition to the fact that modifying an object's prototype after it is created can cause undefined behavior if a given piece of code that accesses it can be executed before OR after the prototype is modified, unless that code is very careful to check the current prototype or not access any property that differs between the two.
Given
const X = function (v) { this.v = v };
X.prototype.whatAmI = 'X';
X.prototype.getWhatIAm = () => this.whatAmI;
X.prototype.getV = () => this.v;
the following VM pseudo-code is equivalent to the statement const x0 = new X(1);:
const x0 = {};
x0.[[Prototype]] = X.prototype;
X.prototype.constructor.call(x0, 1);
Note although the constructor can return any value, the new statement always ignores its return value and returns a reference to the newly created object.
And the following pseudo-code is equivalent to the statement const x1 = Object.create(X.prototype);:
const x0 = {};
x0.[[Prototype]] = X.prototype;
As you can see, the only difference between the two is that Object.create does not execute the constructor, which can actually return any value but simply returns the new object reference this if not otherwise specified.
Now, if we wanted to create a subclass Y with the following definition:
const Y = function(u) { this.u = u; }
Y.prototype.whatAmI = 'Y';
Y.prototype.getU = () => this.u;
Then we can make it inherit from X like this by writing to __proto__:
Y.prototype.__proto__ = X.prototype;
While the same thing could be accomplished without ever writing to __proto__ with:
Y.prototype = Object.create(X.prototype);
Y.prototype.constructor = Y;
In the latter case, it is necessary to set the constructor property of the prototype so that the correct constructor is called by the new Y statement, otherwise new Y will call the function X. If the programmer does want new Y to call X, it would be more properly done in Y's constructor with X.call(this, u)
new Operator
This is used to create object from a constructor function
The new keywords also executes the constructor function
function Car() {
console.log(this) // this points to myCar
this.name = "Honda";
}
var myCar = new Car()
console.log(myCar) // Car {name: "Honda", constructor: Object}
console.log(myCar.name) // Honda
console.log(myCar instanceof Car) // true
console.log(myCar.constructor) // function Car() {}
console.log(myCar.constructor === Car) // true
console.log(typeof myCar) // object
Object.create
You can also use Object.create to create a new object
But, it does not execute the constructor function
Object.create is used to create an object from another object
const Car = {
name: "Honda"
}
var myCar = Object.create(Car)
console.log(myCar) // Object {}
console.log(myCar.name) // Honda
console.log(myCar instanceof Car) // ERROR
console.log(myCar.constructor) // Anonymous function object
console.log(myCar.constructor === Car) // false
console.log(typeof myCar) // object
I prefer a closure approach.
I still use new.
I don't use Object.create.
I don't use this.
I still use new as I like the declarative nature of it.
Consider this for simple inheritance.
window.Quad = (function() {
function Quad() {
const wheels = 4;
const drivingWheels = 2;
let motorSize = 0;
function setMotorSize(_) {
motorSize = _;
}
function getMotorSize() {
return motorSize;
}
function getWheelCount() {
return wheels;
}
function getDrivingWheelCount() {
return drivingWheels;
}
return Object.freeze({
getWheelCount,
getDrivingWheelCount,
getMotorSize,
setMotorSize
});
}
return Object.freeze(Quad);
})();
window.Car4wd = (function() {
function Car4wd() {
const quad = new Quad();
const spareWheels = 1;
const extraDrivingWheels = 2;
function getSpareWheelCount() {
return spareWheels;
}
function getDrivingWheelCount() {
return quad.getDrivingWheelCount() + extraDrivingWheels;
}
return Object.freeze(Object.assign({}, quad, {
getSpareWheelCount,
getDrivingWheelCount
}));
}
return Object.freeze(Car4wd);
})();
let myQuad = new Quad();
let myCar = new Car4wd();
console.log(myQuad.getWheelCount()); // 4
console.log(myQuad.getDrivingWheelCount()); // 2
console.log(myCar.getWheelCount()); // 4
console.log(myCar.getDrivingWheelCount()); // 4 - The overridden method is called
console.log(myCar.getSpareWheelCount()); // 1
Feedback encouraged.

Generating a class from an object (JavaScript)

I'm trying to generate a class from an object in JavaScript. For example:
var Test = {
constructor: function() { document.writeln('test 1'); },
method: function() { document.writeln('test 2'); }
};
var TestImpl = function() { };
TestImpl.prototype.constructor = Test.constructor;
TestImpl.prototype.method = Test.method;
var x = new TestImpl();
x.method();
But this doesn't work: it'll only write 'test 2' (for whatever reason, constructor isn't being defined properly). Why?
I think you're doing it wrong.
Remember, JavaScript doesn't actually have classes at all. It has prototypes instead. So what you're really trying to do is create a prototype object that works like a collection of functions that you've built on another object. I can't imagine any useful purpose for this -- could you elaborate as to what you're trying to do?
Although I think you could make it work by using something like:
var TestImpl = function() {
Test.constructor.apply(this);
};
TestImpl.prototype.method = Test.method;
Your TestImpl function is the constructor. Usually you would do something like this:
var Test1 = function () {
document.writeln('in constructor');
};
Test1.prototype = {
x: 3,
method1: function() { document.writeln('x='+this.x); }
}
var y1 = new Test1();
y1.method1();
y1.x = 37;
y1.method1();
var y2 = new Test1();
y2.method1();
y2.x = 64;
y2.method1();
I think you have things a little backwards. Usually you will assign a prototype to a constructor, rather than assigning a constructor to a prototype.
The reason for assigning a method to the constructor's prototype, rather than to the "this" object inside the constructor, is that the former method creates only 1 shared function, whereas the latter method creates separate instances of a function. This is important (to keep memory allocation to a reasonable amount) if you create lots of objects each with lots of methods.
var Test = function () {
document.writeln('test 1');
this.method = function() { document.writeln('test 2'); }
};
var x = new Test();
x.method();
Javascript doesn't have a "Class" concept, It's all about prototype and the way you use them [ and you can simulate any kind of inheritance with this little neat feature. ]
In javascript "Function" plays the role of [ Class, Method and Constructor ].
so inorder to create "Class" behaviour in Javascript all you need to do is to use the power of "Function".
var A = function(){
alert('A.Constructor');
}
A.prototype = {
method : function(){
alert('A.Method');
}
}
var b = new A(); // alert('A.Constructor');
b.method(); // alert('A.Method');
now the neat thing about JS is that you can easily create "Inheritance" behaviour by using the same method. All you need to do is to connect the second class "Prototype Chain" to the first one, How?
B = function(){
this.prototype = new A(); // Connect "B"'s protoype to A's
}
B.prototype.newMethod = function() { alert('testing'); }
var b = new B();
b.method(); // Doesn't find it in B's prototype,
// goes up the chain to A's prototype
b.newMethod(); // Cool already in B's prototype
// Now when you change A, B's class would automatically change too
A.prototype.method = function(){ alert('bleh'); }
b.method(); // alert('bleh')
If you need any more references I suggest to take a look at Douglas Crockford's Site
Happy JS ing.

Categories

Resources