It is my understanding that the "standard" way to define a new ClassB extending ClassA is as following:
function ClassA() {
this.a = {}; // ClassA's instance member.
}
ClassA.prototype.meth1 = function () { .. } // ClassA's method, shared by all instance.
function ClassB() {}
ClassB.prototype = new ClassA() // <== "standard" way to extend
ClassB.prototype.meth2 = function () {...} // ClassB's method
When I try to define a new class ArrayX like following:
function ArrayX() {
}
ArrayX.prototype = new Array()
ArrayX.prototype.removeDup = function removeDup() {
var o = [];
for(var j=0; j<this.length; j++) {
if(notExist(this[j])
o.push(this[j])
}
return o
function notExist(itm) {
for(var j=0; j<o.length; j++) {
if(o[j]===itm)return false
}
return true;
}
var x = new ArrayX();
console.log(x.length) // returns 0. Good
console.log(x) // returns []. Good
x[0] = 0;
console.log(x); // returns []. No good. I expect x should have one element.
(new ArrayX([1,1,2,3,3])).removeDup() // I expect returns [1,2,3]
I know I can define the function-removeDup in following way:
Array.prototype.removeDup = function removeDup() { ...}
However, I just want to define a new class extending some standard javascript class like Array, or, even the DOM classes.
So, how to define a new class extending standard javascript class like Array?
no need to create a very own class:
Array.prototype.myFunction = function(){
//your custom code
}
By referring link#1, link#2 & link#3, I try this, it works as I expected.
function ArrayX() {
// Array.apply(this, arguments)
// calling Array() has same effect as new Array() according to
// [link#3]
// It is no good here.
this.push.apply(this, arguments); // <-- this works OK. Suggested by link#2
debugger; // Now, `this` has array of value [1, 1, 2, 3, 3], which is
// found in arguments when running new ArrayX(1,1,2,3,3);
// Good.
}
ArrayX.prototype = new Array(); // Suggested by link#1
ArrayX.prototype.removeDup = function removeDup() {
var o = [];
for(var j=0; j<this.length; j++) {
if(notExist(this[j]))
o.push(this[j])
}
return o
function notExist(itm) {
for(var j=0; j<o.length; j++)
if(o[j]===itm)return false
}
return true;
}
var x = new ArrayX(1,1,2,3,3); // x is now [1,1,2,3,3]. Good
console.log(x.length) // 5 Good
var y = x.removeDup(); // y is [1,2,3]. Good
console.log(y);
Related
I'm doing some practice with javascript data structures and am essentially trying to extend Array.
class Collection {
constructor(array){
let collection = Object.create(Array.prototype);
collection = (Array.apply(collection, array) || collection);
collection.clear = () => {
while(this.length > 0){
this.pop();
}
return this
};
return(collection);
}; }
The problem is that when I do the following
c = new Collection([1,2,3]);
c.clear();
c is still [1,2,3] when I am expecting [ ]. Why does modifying this not modify c?
Why does modifying this not modify c?
because this references an instance of Collection that you create with new Collection(...), while your constructor returns the value of let collection; which is NOT this in that context.
Besides that, your code is quite interresting. I think this is what you were trying to build:
class Collection extends Array {
constructor(array) {
// call the constructor of the Array class
super(array.length);
// copy the values from `array` onto `this`;
Object.assign(this, array);
}
clear() {
// that's all it takes to empty an Array
this.length = 0;
}
}
var c = new Collection([1, 2, 3]);
console.log(c);
c.clear();
console.log(c);
This is for the way you defining the function.
As you re defining as lamda expression, the value of this is not getting bound properly.
Change into to normal function declaration.
class Collection {
constructor(array){
let collection = Object.create(Array.prototype);
collection = (Array.apply(collection, array) || collection);
debugger;
collection.clear = function() {
while(this.length > 0){
this.pop();
}
return this
};
return(collection);
}; }
var c = new Collection([1,2,3]);
c.clear();
console.log(c);
I want to create a method which automatically implemented when create an instance of an object, exactly like concept of class constructor.
function myString(string) {
// Storing the length of the string.
this.length = 0;
// A private constructor which automatically implemented
var __construct = function() {
this.getLength();
}();
// Calculates the length of a string
this.getLength = function() {
for (var count in string) {
this.length++;
}
};
}
// Implementation
var newStr = new myString("Hello");
document.write(newStr.length);
I have the following error message when implement the previous code:
TypeError: this.getLength is not a function.
UPDATE:
The problem was in this scope.
The following is constructor method after updade:
var __construct = function(that) {
that.getLength();
}(this);
Bergi's answer in this thread is far more relevant: How to define private constructors in javascript?
Though a bit crude you can create a method called init and then call that method at the bottom of your function so when you instantiate a new object that code shall be run.
function myString(string) {
//Initalization function
this.init = function() {
this.calcLength();
}
// Storing the length of the string.
this.length = 0;
this.getLength = function() {
return this.length;
}
// Calculates the length of a string
this.calcLength = function() {
for (var count in string) {
this.length++;
}
};
this.init();
}
// Implementation
var newStr = new myString("Hello");
var element = document.getElementById('example');
element.innerText = newStr.getLength();
Edit: I'm aware there are better ways to achieve this, but this gets the job done.
Edit 2: Fiddle https://jsfiddle.net/ntygbfb6/3/
I have a method in a base class that I want to keep in a subclass, but just add to it. I've found lots of stuff on augmenting classes and objects with properties and methods, but I can't find, or don't understand, how to just augment the method. The worst case scenario is that I would have to paste the entire method of the parent class into the subclass, but that seems like duplicate code... please help
function someObject (){
this.someProperty = 1;
this.incrementProperty = function incrementProperty(){
this.propertyOfSomeObject += 1;
}
}
function newObject (){
someObject.call(this);
this.incrementProperty = function incrementProperty(){
//do everything the super class has for this property already
return this.someProperty;
}
}
var incrementer = new newObject;
alert (incrementer.incrementProperty()); //I want output to be 2
// parent object
function someObject () {
this.someProperty = 1;
}
// add incrementProperty to the prototype so you're not creating a new function
// every time you instantiate the object
someObject.prototype.incrementProperty = function() {
this.someProperty += 1;
return this.someProperty;
}
// child object
function newObject () {
// we could do useful work here
}
// setup new object as a child class of someObject
newObject.prototype = new someObject();
// this allows us to use "parent" to call someObject's functions
newObject.prototype.parent = someObject.prototype;
// make sure the constructor points to the right place (not someObject)
newObject.constructor = newObject;
newObject.prototype.incrementProperty = function() {
// do everything the super class has for this property already
this.parent.incrementProperty.call(this);
return this.someProperty;
}
var incrementer = new newObject();
alert (incrementer.incrementProperty()); // I want output to be 2
See: http://jsfiddle.net/J7RhA/
this should do, you have to use prototype to have a real concept of oo with javascript
function someObject (){
this.someProperty = 1;
this.propertyOfSomeObject = 0;
this.incrementProperty = function incrementProperty(){
this.propertyOfSomeObject += 1;
return this.propertyOfSomeObject;
}
}
function newObject (){
someObject.call(this);
this.incrementProperty = function incrementProperty(){
this.__super__.incrementProperty.apply(this);
return this.propertyOfSomeObject + 1;
}
}
newObject.prototype = new someObject()
newObject.prototype.__super__ = newObject.prototype
var incrementer = new newObject();
alert(incrementer.incrementProperty()); //I want output to be 2
experiment removing incrementProperty from newObject and it will return 1
I usually use the augment library to write classes in JavaScript. This is how I would rewrite your code using augment:
var Foo = Object.augment(function () {
this.constructor = function () {
this.someProperty = 1;
};
this.incrementProperty = function () {
this.someProperty++;
};
});
var Bar = Foo.augment(function (base) {
this.constructor = function () {
base.constructor.call(this);
};
this.incrementProperty = function () {
base.incrementProperty.call(this);
return this.someProperty;
};
});
As you can see since Bar extends Foo it gets Foo.prototype as a parameter (which we call base). This allows you to easily call the base class constructor and incrementProperty functions. It also shows that the constructor itself is just another method defined on the prototype.
var bar = new Bar;
alert(bar.incrementProperty());
The output will be 2 as expected. See the demo for yourself: http://jsfiddle.net/47gmQ/
From this answer:
Overriding functions
Sometimes children need to extend parent functions.
You want the 'child' (=RussionMini) to do something extra. When RussionMini can call the Hamster code to do something and then do something extra you don't need to copy and paste Hamster code to RussionMini.
In the following example we assume that a Hamster can run 3km an hour but a Russion mini can only run half as fast. We can hard code 3/2 in RussionMini but if this value were to change we have multiple places in code where it needs changing. Here is how we use Hamster.prototype to get the parent (Hamster) speed.
// from goog.inherits in closure library
var inherits = function(childCtor, parentCtor) {
function tempCtor() {};
tempCtor.prototype = parentCtor.prototype;
childCtor.prototype = new tempCtor();
childCtor.prototype.constructor = childCtor;
};
var Hamster = function(name){
if(name===undefined){
throw new Error("Name cannot be undefined");
}
this.name=name;
}
Hamster.prototype.getSpeed=function(){
return 3;
}
Hamster.prototype.run=function(){
//Russionmini does not need to implement this function as
//it will do exactly the same as it does for Hamster
//But Russionmini does need to implement getSpeed as it
//won't return the same as Hamster (see later in the code)
return "I am running at " +
this.getSpeed() + "km an hour.";
}
var RussionMini=function(name){
Hamster.apply(this,arguments);
}
//call this before setting RussionMini prototypes
inherits(RussionMini,Hamster);
RussionMini.prototype.getSpeed=function(){
return Hamster.prototype
.getSpeed.call(this)/2;
}
var betty=new RussionMini("Betty");
console.log(betty.run());//=I am running at 1.5km an hour.
I want to write a small game using JavaScript and <canvas> but first I want to nail the "correct" or at least common approach to working with Objects.
One topic I am having trouble understanding in particular is how I could implement overriding of method.
When I create an Object, I may have this:
function MyObject()
{
var base = {};
base.i = 0;
base.update = function()
{
base.i ++;
}
return base;
}
Then when I create another Object that should start with the same members, I use this:
function AnotherObject()
{
var base = new MyObject();
base.j = 0;
return base;
}
I want to add more content to AnotherObject.update() while still running the logic I have in MyObject.update(), but when I do this within AnotherObject():
base.update = function()
{
j ++;
}
Then I of course lose the logic I added in MyObject.update().
How can I write AnotherObject.update() so that it also calls the original update() method defined by MyObject?
First, I'd suggest you read this excellent excellent MDN article. It will enlighten you.
You can achieve subclassing this way:
function MyObject() {
this.i = 0;
}
MyObject.prototype.update = function() {
this.i++;
}
function AnotherObject() {
MyObject.call(this);
this.j = 0;
}
AnotherObject.prototype = new MyObject;
AnotherObject.prototype.constructor = AnotherObject;
AnotherObject.prototype.update = function() {
MyObject.prototype.update.call(this);
this.j++;
}
obj = new AnotherObject();
console.log(obj.i); //0
console.log(obj.j); //0
obj.update();
console.log(obj.i); //1
console.log(obj.j); //1
console.log(obj instanceof MyObject) //true
console.log(obj instanceof AnotherObject) //true
+1 for zzzzBov's comment. You're using base when you should be using prototype. Not within the constructor function, but rather after the constructor function to further refine the class definition.
function MyObject() {
this.value = 5;
}
MyObject.prototype.update = function() {
this.value++;
}
Var newObject = new MyObject();
newObject.update =function() {
value--;
}
As others have suggested you should follow prototype based inheritance. That is the right way to do it.
But as a solution to what you have done so far you can do as shown below
function MyObject() {
var base = {};
base.i = 0;
base.update = function () {
this.i++;
}
base.show = function () {
console.log("i is " + this.i);
}
return base;
}
function AnotherObject() {
var base = new MyObject();
base.j = 0;
var update = base.update; // proxy variable that refers to original `update`
base.update = function () {
update.call(this); // invoke original `update`
this.j++;
}
var show = base.show; // proxy variable that refers to original `show`
base.show = function () {
show.call(this); // invoke original `show`
console.log("j is " + this.j);
}
return base;
}
var t = AnotherObject();
t.update();
t.show();
Is something like this possible:
function FooClass()
{
var barsArray=new Array();
var index=0;
function addBar()
{
barsArray[index]=new BarClass(index);
}
}
function BarClass()
{
var myIndex;
function BarClass(index)
{
myIndex=index;
}
}
I'm inferring that you want to have a Foo object, and that Foo object should contain an array of Bar objects. Each Bar object should know its array index within its parent Foo object.
If that is an accurate description, then try this:
function BarClass(idx) {
this.myIndex = idx;
}
function FooClass(howMany) {
this.barsArray = [];
for (var x = 0; x < howMany; x++) {
this.barsArray[x] = new BarClass(x);
}
}
var foo = new FooClass(5);
// foo.barsArray[0].myIndex === 0
// foo.barsArray[1].myIndex === 1
// foo.barsArray[2].myIndex === 2
// foo.barsArray[3].myIndex === 3
// foo.barsArray[4].myIndex === 4
// foo.constructor === 'FooClass'
// foo.barsArray[0].constructor === 'BarClass'
Good luck!
Not quite (actually it compiles, but probably doesn't do what you intended).
I'm assuming you want to create a FooClass class with an addBar method that appends a BarClass object to it's barsArray member.
The addBar function is just a local variable inside the FooClass function/constructor. To make it accessible from outside the constructor, you need to assign it to this.addBar. Other than remembering to increment index, that's all you would need to change in FooClass.
For the BarClass class, remember that a "class" is really just a constructor function. You don't need to (and can't) a separate constructor. BarClass would just be a single function that takes an index and assigns it to this.myIndex.
function FooClass()
{
// use this.barsArray = [], etc if you want them to be publically available
var barsArray=[]; // It's usually better to use "[]" instead of "new Array()"
var index=0;
this.addBar = function() {
barsArray[index]=new BarClass(index);
index++;
}
}
function BarClass(index)
{
this.myIndex=index;
}
If you change barsArray and index to be properties instead of local variables ("this.barsArray = [];" and "this.index = 0"), you can put addBar in FooClass.prototype and there will only be one instance of the function:
function FooClass()
{
this.barsArray=[];
this.index=0;
}
FooClass.prototype.addBar = function() {
this.barsArray[this.index]=new BarClass(this.index);
this.index++;
};