I was tackling this question in leet code:
Implement the MapSum class:
MapSum() Initializes the MapSum object. void insert(String key, int
val) Inserts the key-val pair into the map. If the key already
existed, the original key-value pair will be overridden to the new
one. int sum(string prefix) Returns the sum of all the pairs' value
whose key starts with the prefix.
In javascript, the template for solving the question is:
/**
* Initialize your data structure here.
*/
var MapSum = function() {
};
/**
* #param {string} key
* #param {number} val
* #return {void}
*/
MapSum.prototype.insert = function(key, val) {
};
/**
* #param {string} prefix
* #return {number}
*/
MapSum.prototype.sum = function(prefix) {
};
/**
* Your MapSum object will be instantiated and called as such:
* var obj = new MapSum()
* obj.insert(key,val)
* var param_2 = obj.sum(prefix)
*/
I was struck by the class template. I'm used to seeing javascript classes more similar to this:
class MapSum {
constructor() {
}
insert(key, value) {
}
sum(prefix) {
}
}
Is the template leetcode provided, considered a class? What kind of class is it? What is it called when you initialize an object via function expression (var MapSum = function() { //....}) ? What are the biggest differences/implications from writing a class that way vs the way I suggested?
The class keyword is actually just syntaxic sugar over prototypal inheritance
This code demonstrates that the two syntaxes are equivalent:
class MapSum {
constructor() {
}
insert(key, value) {
}
sum(prefix) {
}
}
console.log(typeof MapSum); // function (actually the constructor)
console.log(MapSum.prototype.insert); // function
console.log(MapSum.prototype.sum); // function
A class is actually just a constructor function, which has a special object named prototype attached to it. Every instance of the class has an internal link to the prototype of the constructor.
I'm reading the JSVerbalExpression source code, and i'm trying to understand why the authors are injecting methods in the prototype of the construction function, instead of just assigning them:
function VerbalExpression() {
var verbalExpression = new RegExp();
// Add all the class methods
VerbalExpression.injectClassMethods(verbalExpression);
// Return the new object.
return verbalExpression;
}
/**
* #param {RegExp} verbalExpression An instance of RegExp on which to add VerbalExpressions methods
* #return {RegExp} A new instance of RegExp with injected methods
*/
VerbalExpression.injectClassMethods = function injectClassMethods(verbalExpression) {
var method;
// Loop over all the prototype methods
for (method in VerbalExpression.prototype) {
// Make sure this is a local method.
if (VerbalExpression.prototype.hasOwnProperty(method)) {
// Add the method
verbalExpression[method] = VerbalExpression.prototype[method];
}
}
return verbalExpression;
};
Is it related with performance?
Thanks.
I'm trying to typecheck a library that returns an Object of constructor functions. With the following code Closure errors with:
./my-app.js:11: ERROR - Cannot call non-function type Foo.Wheel
const wheel = new Foo.Wheel();
^
Here's the code structure:
my-app-code.js - The code I'm using
const Foo = /** #type{!Foo.Module} */ require('foo');
const wheel = new Foo.Wheel();
wheel.rotate();
externs-foo.js - Closure externs for the Foo library
/** #const */
const Foo = {};
/** #record */
Foo.Module = function() {};
/** #type {!Foo.Wheel} */
Foo.Module.prototype.Wheel;
/** #constructor */
Foo.Wheel = function() {};
/**
* #returns {void}
*/
Foo.Wheel.prototype.rotate = function() {};
foo/index.js - corresponds to Foo.Module type.
module.exports = {
Wheel: require("./wheel"),
};
foo/wheel.js - corresponds to Foo.Wheel.
function Wheel() {}
Wheel.prototype.rotate = function() {};
module.exports = Wheel;
I tried one variation on externs-foo.js with the following results.
Make Foo.module.prototype.Wheel a function
/** #return {!Foo.Wheel} */
Foo.Module.prototype.Wheel = function() {};
Errors with:
my-app.js:11: ERROR - Expected a constructor but found type function(this:Foo.Module):Foo.Wheel.
const wheel = new Foo.Wheel();
my-app.js:13: ERROR - Property rotate never defined on module$myapp_Foo of type Foo.Module
wheel.rotate();
I'm aware of two solutions to this issue:
Declaring Foo.Module.prototype.Wheel = Foo.Wheel; in the externs file.
Use #type {function(new:Foo.Wheel)}, which says that the function is in fact a constructor that instantiates a Foo.Wheel object.
I prefer solution #1 because it declares a reference to the constructor function, so the compiler will allow me to access properties of the constructor (e.g. static methods). IIRC this can't be done in solution #2.
The annotations #type {!Foo.Wheel} and #return {!Foo.Wheel} won't work because they refer to an instance of Foo.Wheel and what you actually want is the constructor itself.
I'm creating two objects (Inherits), both inherit from Base.
The second object's property assignment overrides the value in the first object.
Any thoughts? How to make a proper inheritance so that Base class will contain common members for its inheritance descendants, but the descendants could assign values of their own without interfering each other.
var testParams1 = { title: "john" };
var testParams2 = { title: "mike" };
Function.prototype.inheritsFrom = function (baseClass)
{
this.prototype = new baseClass;
this.prototype.constructor = this;
this.prototype.base = baseClass.prototype;
return this;
};
function Base() {
this.viewModel = {};
this.viewModel.title = (function ()
{
var savedVal = "";
return function (newVal)
{
if (typeof (newVal) === "undefined")
{
return savedVal;
}
savedVal = newVal;
};
})();
}
function Inherits(params) {
this.viewModel.title(params.title);
}
Inherits.inheritsFrom(Base);
///// preparing code:
var testObj1 = new Inherits(testParams1);
var testObj2 = new Inherits(testParams2);
///// testing code:
equals(testObj1.viewModel.title(), testParams1.title, "first instance ok"); // returns "john"
equals(testObj2.viewModel.title(), testParams2.title, "second instance ok"); // also returns "john"
Problem(s)
The Base class constructor is called once and only once.
this.prototype = new baseClass;
Privileged methods will refer to the same this object across instances because those methods are created within the constructor (which was called only once).
Problem(s) based on a matter of opinion
You should try to avoid modifying native prototypes (ie. Function.prototype) if you plan on working alongside JavaScript that you do not own.
Solution
Call the constructor and parent constructor(s) for each new instance that is created.
Inherit the parent prototype chain (not a instance of a the parent class).
Maintain a 1:1 ratio of number of instances created to the number of calls the constructor(s) in the prototype chain.
Final solution to Max's problem
Please pay special attention to the inherits function and the ParentClass.call(this, title); line.
Constructors to look for are ParentClass and ChildClass
/**
* Allows a child constructor to safely inherit the parent constructors prototype chain.
* #type {Function}
* #param {!Function} childConstructor
* #param {!Function} parentConstructor
*/
function inherits(childConstructor, parentConstructor){
var TempConstructor = function(){};
TempConstructor.prototype = parentConstructor.prototype; // Inherit parent prototype chain
childConstructor.prototype = new TempConstructor(); // Create buffer object to prevent assignments directly to parent prototype reference.
childConstructor.prototype.constructor = childConstructor; // Reset the constructor property back the the child constructor
};
//////////////////////////////////////
/** #constructor */
function ParentClass(title) {
this.setTitle(title);
var randId_ = Math.random();
/** #return {number} */
this.getPrivlegedRandId = function()
{return randId_;};
};
/** #return {string} */
ParentClass.prototype.getTitle = function()
{return this.title_;};
/** #param {string} value */
ParentClass.prototype.setTitle = function(value)
{this.title_ = value;};
//////////////////////////////////////
/**
* #constructor
* #param {string} title
* #param {string} name
*/
ChildClass = function (name, title) {
ParentClass.call(this, title); // Call the parent class constructor with the required arguments
this.setName(name);
}
inherits(ChildClass, ParentClass); // Inherit the parent class prototype chain.
/** #return {string} */
ChildClass.prototype.getName = function()
{return this.name_;};
/** #param {string} value */
ChildClass.prototype.setName = function(value)
{this.name_ = value;};
Down the rabbit hole
For those who are curious why that works vs simply memorizing it the inherits function.
How properties are resolved using the prototype chain
When a property is not found at the instance level, JavaScript will try to resolve the missing property by searching through the instance constructors prototype chain. If the property is not found in the first prototype object, it will search the parent prototype object and so on all the way up to Object.prototype. If it can't find it within Object.prototype then an error will be thrown.
Calling the parent constructor from child constructor : Attempt #1
// Bad
var ChildConstructor = function(arg1, arg2, arg3){
var that = new ParentConstructor(this, arg1, arg2, arg3);
that.getArg1 = function(){return arg1};
return that;
}
Any varible that is created using new ChildConstructor will return an instance of ParentConstructor.
The ChildConstructor.prototype will be not be used.
Calling the parent constructor from child constructor : Attempt #2
// Good
var ChildConstructor = function(arg1, arg2, arg3){
ParentConstructor.call(this, arg1, arg2, arg3);
}
Now constructor and the parent constructor is called appropriately. However, only methods defined within the constructor(s) will exist. Properties on the parent prototypes will not be used because they have not yet been linked to the child constructors prototype.
Inheriting the parent prototype : Attempt #1
// Bad
ChildConstructor.prototype = new ParentConstructor();
The parent constructor will either be called only once or one too many times depending on whether or not ParentConstructor.call(this) is used.
Inheriting the parent prototype attempt #2
// Bad
ChildConstructor.prototype = ParentConstructor.prototype;
Though this technically works, any assignments to ChildConstructor.prototype will also be assigned to ParentConstructor.prototype because Objects are passed by reference and not by copy.
Inheriting the parent prototype attempt #3
// Almost there
var TempConstructor = function(){};
TempConstructor.prototype = ParentConstructor.prototype;
ChildConstructor.prototype = new TempConstructor();
This allows you to assign properties to ChildConstructor.prototype because it is an instance of a temporary anonymous function.
Properties that are not found on the instance of TempConstructor will then check it's prototype chain for the property, so you have successfully inherited the parent prototype. The only problem is that ChildConstructor.prototype.constructor is now pointing to TempConstructor.
Inheriting the parent prototype attempt #4
// Good
var TempConstructor = function(){};
TempConstructor.prototype = ParentConstructor.prototype;
ChildConstructor.prototype = new TempConstructor();
ChildConstructor.prototype.constructor = ChildConstructor;
All Together
var ParentConstructor = function(){
};
var ChildConstructor = function(){
ParentConstructor.call(this)
};
var TempConstructor = function(){};
TempConstructor.prototype = ParentConstructor.prototype;
ChildConstructor.prototype = new TempConstructor();
ChildConstructor.prototype.constructor = ChildConstructor;
You've successfully inherited from the parent class! Let's see if we can do better.
The inherits function
function inherits(childConstructor, parentConstructor){
var TempConstructor = function(){};
TempConstructor.prototype = parentConstructor.prototype; // Inherit parent prototype chain
childConstructor.prototype = new TempConstructor(); // Create buffer object to prevent assignments directly to parent prototype reference.
childConstructor.prototype.constructor = childConstructor; // Reset the constructor property back the the child constructor (currently set to TempConstructor )
};
var ParentConstructor = function(){
};
var ChildConstructor = function(){
ParentConstructor.call(this)
};
inherits(ChildConstructor, ParentConstructor);
There is a lot of information about composition vs inheritance online, but I haven't found decent examples with JavaScript. Using the below code to demonstrate inheritance:
function Stock( /* object with stock names and prices */ ) {
for (var company_name in arguments[0]) {
// copy the passed object into the new object created by the constructor
this[company_name] = arguments[0][company_name];
}
}
// example methods in prototype, their implementation is probably redundant for
// this question, but list() returns an array with toString() invoked; total()
// adds up the stock prices and returns them. Using ES5 feature to make
// inherited properties non-enumerable
Stock.prototype = {
list: function () {
var company_list = [];
for (var company_name in this)
company_list.push(company_name);
return company_list.toString();
},
total: function () {
var price_total = 0;
for (var company_name in this)
price_total += this[company_name];
return '$' + price_total;
}
};
Object.defineProperties(Stock.prototype, {
list: { enumerable: false },
total: { enumerable:false }
});
var portfolio = new Stock({ MSFT: 25.96, YHOO: 16.13, AMZN: 173.10 });
portfolio.list(); // MSFT,YHOO,AMZN
portfolio.total(); // $215.19
(To make the code smaller, you can leave out the method implementations, like: Stock.total = function(){ /* code */ } I just put them in there to be fancy). If composition is favored for a lot of situations in OOP, how come most people using JavaScript seem to only use prototypes and inheritance? I did not find a lot of information about composition in JavaScript online, only in other languages.
Can someone give me an example using the above code to demonstrate composition and aggregation?
The language is irrelevant when dealing with composition vs inheritance. If you understand what class is and what an instance of a class is, then you have all you need.
Composition is simply when a class is composed of other classes; or to say it another way, an instance of an object has references to instances of other objects.
Inheritance is when a class inherits methods and properties from another class.
Let's say you have two functionality, A and B. You want to define a third functionality, C, that has some or all of both A and B. You could either make C extend from B and A, in which case C has everything B and A has because C isA B and A, or you can make each instance of C have an instance of A and an instance of B, and invoke items on those functionalities. In the latter case, each instance C in effect wraps an instance of B and an instance of A.
Of course, depending on the language, you might not be able to have a class extend from 2 classes (e.g. Java doesn't support multiple inheritance), but that's a language specific detail that has nothing to do with the concept.
Now, for the language specific details...
I used the word class, but javascript has no notion of Class as such. It has objects, and thats it (other than the simple types). Javascript uses prototypal inheritance, which means it has a way of efficiently defining objects and the methods on those objects (this is the topic for another question; you can search SO as there are already answers.)
So going with our example above, you have A, B, and C.
For inheritance, you would have
// define an object (which can be viewed as a "class")
function A(){}
// define some functionality
A.prototype.someMethod = function(){}
If you wanted C to extend A, you would do
C.prototype = new A();
C.prototype.constructor = A;
Now every instance of C would have the method someMethod, because every instance of C "isA" A.
Javascript doesn't have multiple inheritance* (more on this later), so you can't have C extend both A and B. You can use composition, however, to give it the functionality. Indeed, this is one of the reasons composition is preferred by some over inheritance; there are no limits on combining functionality (but this isn't the only reason).
function C(){
this.a = new A();
this.b = new B();
}
// someMethod on C invokes the someMethod on B.
C.someMethod = function(){
this.a.someMethod()
}
So there are your simple examples for both inheritance and composition. However, this is not the end of the story. I said before that Javascript does not support multiple inheritance, and in a sense it doesn't, because you can't base the prototype of an object off the prototypes of multiple objects; i.e. you can't do
C.prototype = new B();
C.prototype.constructor = B;
C.prototype.constructor = A;
because as soon as you do the third, line, you just undid the the second line. This has implications for the instanceof operator.
However, this doesn't really matter, because just because you can't redefine the constructor of an object twice, you can still add any methods you want to the prototype of an object. So just because you can't do the above example, you can still add anything you want to C.prototype, including all the methods on the prototypes of both A and B.
Many frameworks support this and make it easy. I do a lot of Sproutcore work; with that framework you can do
A = {
method1: function(){}
}
B = {
method2: function(){}
}
C = SC.Object.extend(A, B, {
method3: function(){}
}
Here I defined functionality in object literals A and B, and then added the functionality of both to C, so every instance of C has methods 1, 2, and 3. In this particular case, the extend method (provided by the framework) does all the heavy lifting of setting up the prototypes of the objects.
EDIT -- In your comments, you bring out a good question, namely "If you use composition, how do you reconcile the scope of the main object against the scope of the objects of which the main object is composed".
There are a bunch of ways. The first is simply to pass arguments. So
C.someMethod = function(){
this.a.someMethod(arg1, arg2...);
}
Here you are not messing with scopes, you are simply passing arguments around. This is a simple and very viable approach. (the arguments can come from this or be passed in, whatever...)
Another way to do it would be to use the call (or apply) methods of javascript, which basically allows you to set the scope of a function.
C.someMethod = function(){
this.a.someMethod.call(this, arg1, arg2...);
}
to be a bit more clear, the following is equivalent
C.someMethod = function(){
var someMethodOnA = this.a.someMethod;
someMethodOnA.call(this, arg1, arg2...);
}
In javascript, functions are object, so you can assign them to variables.
the call invocation here is setting the scope of someMethodOnA to this, which is the instance of C.
...
Can someone give me an example using the above code to demonstrate
composition and aggregation?
At first glance the provided example does not seem to be the best
choice in order to demonstrate composition in JavaScript. The prototype
property of the Stock constructor function still remains the ideal
place for both methods total and list for both do access any stock
object's own properties.
What can be done is decoupling the implementations of these methods
from the constructors prototype and providing them back exactly there -
yet in an additional form of code reuse - Mixins ...
example:
var Iterable_listAllKeys = (function () {
var
Mixin,
object_keys = Object.keys,
listAllKeys = function () {
return object_keys(this).join(", ");
}
;
Mixin = function () {
this.list = listAllKeys;
};
return Mixin;
}());
var Iterable_computeTotal = (function (global) {
var
Mixin,
currencyFlag,
object_keys = global.Object.keys,
parse_float = global.parseFloat,
aggregateNumberValue = function (collector, key) {
collector.value = (
collector.value
+ parse_float(collector.target[key], 10)
);
return collector;
},
computeTotal = function () {
return [
currencyFlag,
object_keys(this)
.reduce(aggregateNumberValue, {value: 0, target: this})
.value
.toFixed(2)
].join(" ");
}
;
Mixin = function (config) {
currencyFlag = (config && config.currencyFlag) || "";
this.total = computeTotal;
};
return Mixin;
}(this));
var Stock = (function () {
var
Stock,
object_keys = Object.keys,
createKeyValueForTarget = function (collector, key) {
collector.target[key] = collector.config[key];
return collector;
},
createStock = function (config) { // Factory
return (new Stock(config));
},
isStock = function (type) {
return (type instanceof Stock);
}
;
Stock = function (config) { // Constructor
var stock = this;
object_keys(config).reduce(createKeyValueForTarget, {
config: config,
target: stock
});
return stock;
};
/**
* composition:
* - apply both mixins to the constructor's prototype
* - by delegating them explicitly via [call].
*/
Iterable_listAllKeys.call(Stock.prototype);
Iterable_computeTotal.call(Stock.prototype, {currencyFlag: "$"});
/**
* [[Stock]] factory module
*/
return {
isStock : isStock,
create : createStock
};
}());
var stock = Stock.create({MSFT: 25.96, YHOO: 16.13, AMZN: 173.10});
/**
* both methods are available due to JavaScript's
* - prototypal delegation automatism that covers inheritance.
*/
console.log(stock.list());
console.log(stock.total());
console.log(stock);
console.dir(stock);
There is a lot of information about composition vs inheritance
online, but I haven't found decent examples with JavaScript.
...
I did not find a lot of information about composition in JavaScript
online, only in other languages.
...
Maybe the search query was not specific enough but even in 2012
searching for "JavaScript Mixin composition" should have led into
a not that bad direction.
...
If composition is favored for a lot of situations in OOP, how
come most people using JavaScript seem to only use prototypes
and inheritance?
Because most of them use, what they got tought and/or what they
are familar with. Maybe there should be more knowledge spread
about JavaScript as delegation based language too and what can
be achieved with it.
appendix:
This are related threads, recently updated and hopefully helping ...
stackoverflow.com :: How to use mixins properly in Javascript
stackoverflow.com :: Traits in javascript
stackoverflow.com :: Javascript Distinguish between Composition vs. Inheritance
I think I can show you how to rewrite your code in "object composition" fashion by using plain JavaScript (ES5). I use factory functions instead of constructor functions for creating an object instance, so no new keyword needed. That way, I can favour object augmentation (composition) over classical/pseudo-classical/prototypal inheritance, so no Object.create function is called.
The resulting object is a nice flat-composed object:
/*
* Factory function for creating "abstract stock" object.
*/
var AbstractStock = function (options) {
/**
* Private properties :)
* #see http://javascript.crockford.com/private.html
*/
var companyList = [],
priceTotal = 0;
for (var companyName in options) {
if (options.hasOwnProperty(companyName)) {
companyList.push(companyName);
priceTotal = priceTotal + options[companyName];
}
}
return {
/**
* Privileged methods; methods that use private properties by using closure. ;)
* #see http://javascript.crockford.com/private.html
*/
getCompanyList: function () {
return companyList;
},
getPriceTotal: function () {
return priceTotal;
},
/*
* Abstract methods
*/
list: function () {
throw new Error('list() method not implemented.');
},
total: function () {
throw new Error('total() method not implemented.');
}
};
};
/*
* Factory function for creating "stock" object.
* Here, since the stock object is composed from abstract stock
* object, you can make use of properties/methods exposed by the
* abstract stock object.
*/
var Stock = compose(AbstractStock, function (options) {
return {
/*
* More concrete methods
*/
list: function () {
console.log(this.getCompanyList().toString());
},
total: function () {
console.log('$' + this.getPriceTotal());
}
};
});
// Create an instance of stock object. No `new`! (!)
var portofolio = Stock({MSFT: 25.96, YHOO: 16.13, AMZN: 173.10});
portofolio.list(); // MSFT,YHOO,AMZN
portofolio.total(); // $215.19
/*
* No deep level of prototypal (or whatsoever) inheritance hierarchy;
* just a flat object inherited directly from the `Object` prototype.
* "What could be more object-oriented than that?" –Douglas Crockford
*/
console.log(portofolio);
/*
* Here is the magic potion:
* Create a composed factory function for creating a composed object.
* Factory that creates more abstract object should come first.
*/
function compose(factory0, factoryN) {
var factories = arguments;
/*
* Note that the `options` passed earlier to the composed factory
* will be passed to each factory when creating object.
*/
return function (options) {
// Collect objects after creating them from each factory.
var objects = [].map.call(factories, function(factory) {
return factory(options);
});
// ...and then, compose the objects.
return Object.assign.apply(this, objects);
};
};
Fiddle here.