This question already has answers here:
does javascript support multiple inheritance like C++
(4 answers)
Closed 9 years ago.
I have a situation here. I have two modules(nothing but javascript function) defined like this:
Module1:
define(function(){
function A() {
var that = this;
that.data = 1
// ..
}
return A;
});
Module2:
define(function(){
function B() {
var that = this;
that.data = 1;
// ...
}
return B;
});
How to inhert both modules inside other module?
1) In js everything is just an object.
2) Javascript inheritance uses prototype inheritance and not classic inheritance.
JavaScript doesn't support multiple inheritance.
To have both of them inside the same class try to use mixins that are better anyhow:
function extend(destination, source) {
for (var k in source) {
if (source.hasOwnProperty(k)) {
destination[k] = source[k];
}
}
return destination;
}
var C = Object.create(null);
extend(C.prototype,A);
extend(C.prototype,B);
mixins:
http://javascriptweblog.wordpress.com/2011/05/31/a-fresh-look-at-javascript-mixins/
inheritance in js:
http://howtonode.org/prototypical-inheritance
http://killdream.github.io/blog/2011/10/understanding-javascript-oop/index.html
Here you go a little demonstration of the functionality you want to achieve:
var obj1 = function() {
var privateMember = "anything";
this.item1 = 1;
}
var obj2 = function() {
this.item2 = 2;
}
var objInheritsBoth = function() {
obj1.call(this); // call obj1 in this context
obj2.call(this);
this.item3 = 3;
}
var x = new objInheritsBoth();
console.log(x.item1, x.item2, x.item3); // 1 2 3
Related
This question already has answers here:
Private properties in JavaScript ES6 classes
(41 answers)
Closed 5 years ago.
I want to build a class using javascript like in c, the main problem is private attribute.
var tree = {
private_var: 5,
getPrivate:function(){
return this.private_var;
}
};
console.log(tree.private_var);//5 this line want to return unaccessible
console.log(tree.getPrivate());//5
so I want to detect the access from tree.private_var and return unaccessible, and this.private_var return 5.
My question is: Is there any way to set private attribute in javascript?
EDIT: I saw this way
class Countdown {
constructor(counter, action) {
this._counter = counter;
this._action = action;
}
dec() {
if (this._counter < 1) return;
this._counter--;
if (this._counter === 0) {
this._action();
}
}
}
CountDown a;
a._counter is not accessible?
but
Define tree as a function instead of JavaScript object, define private variable in the function by var keyword, define public getting function by this. keyword and create a new instance by using the function
var Tree = function(){
var private_var = 5;
this.getPrivate = function(){
return private_var;
}
}
var test = new Tree();
test.private_var; //return undefined
test.getPrivate(); //return 5
In ES6, you can do this but it is not supported by IE so I wouldn't recommend
class Tree{
constructor(){
var private_var =5;
this.getPrivate = function(){ return private_var }
}
}
var test = new Tree();
test.private_var; //return undefined
test.getPrivate(); //return 5
This question already has answers here:
Are ES6 classes just syntactic sugar for the prototypal pattern in Javascript?
(7 answers)
Closed 6 years ago.
When I research online, I'm finding different answers.
class Foo {
constructor() {
this.data = [];
}
add(x) {
//
}
}
Is the above code equivalent to Code A or Code B?
Code A:
function Foo() {
this.data = [],
this.add = function(x) {
//
}
}
Code B:
function Foo() {
this.data = []
}
Foo.prototype.add = function(x) {
//
}
Code B in your example, here is an example taken from https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Classes
class Animal {
speak() {
return this;
}
static eat() {
return this;
}
}
let obj = new Animal();
let speak = obj.speak;
speak(); // undefined
let eat = Animal.eat;
eat(); // undefined
is the same as
function Animal() { }
Animal.prototype.speak = function(){
return this;
}
Animal.eat = function() {
return this;
}
let obj = new Animal();
let speak = obj.speak;
speak(); // global object
let eat = Animal.eat;
eat(); // global object
Be aware this is using ES6 notation and is not fully supported at time of writing. See here for what supports ES6 - https://kangax.github.io/compat-table/es6/
This question already has answers here:
How to execute a JavaScript function when I have its name as a string
(36 answers)
Closed 8 years ago.
Based on a question I asked prior to this, how would I qualify this string...
"MyCustomObject.prototype.foo.bar"
to this:
window['MyCustomObject']['prototype']['foo']['bar']
in object form? (it must not qualify to...
"window['MyCustomObject']['prototype']['foo']['bar']"
...as a string!).
As a reference, consider the following...(the code is wrong...it needs fixing (without the eval keyword))
var fn = "MyCustomObject.prototype.foo.bar";
var ptr = fn.split('.');
var ptrPath = 'window'
for(var index = 0; index < ptr.length; index++) {
ptrPath += '[\'' + ptr[index] + '\']';
}
ptrPath = function() {
alert("Hello");
}
should resolve to this;
var inst = new MyObject();
inst.foo.bar(); //alerts...."Hello"
I modified the answer in this question to suit your needs.
var getPropertyByName = function (fullString, context) {
var namespaces = fullString.split(".");
var functionName = namespaces.pop();
for (var i = 0; i < namespaces.length; i++) {
context = context[namespaces[i]];
}
return context[functionName];
};
getPropertyByName('MyCustomObject.foo.bar', window);
http://jsfiddle.net/jbabey/4GVUK/
You could try this way:
var fn = "foo.prototype.bar";
var ptr = fn.split('.');
var func = ptr.reduce(function(a, b){
return a[b] ? a[b] : a;
}, window);
The working demo.
Finally after much effort, I have figured out the solution.
The idea behind the Object.implement function is to allow a developer to:
Define an object/function by name (E.G. "Custom" or "Custom.prototype.foo.bar"), regardless of that objects existence.
Define the object/functions context (E.G window)
Define the object/function implementation
define whether to override the object/function if an implementation already exists.
Consider the Object.implement code sample:
Object.implement = function(fn, context, implementation, override) {
var properties = fn.split('.');
var fnName = properties.pop();
for(var index = 0; index < properties.length; index++) {
if(!context[properties[index]]) {
context[properties[index]] = { };
}
context = context[properties[index]];
}
if(!context[fnName] || override) {
context[fnName] = implementation;
}
};
I can now use this to safely create/implement objects and functions. Consider this a bit like a "shim" feature, where if a function does not exist, an implementation can be provided, however with the added functionality that existing functionality can be over-ridden as well:
Object.implement("HashTable", window, function() { }, true);
Object.implement("HashTable.prototype.bar", window, function() { alert("Hello World") }, true);
var ht = new HashTable();
ht.bar();
It works in FireFox...I have yet to test in other browsers!
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 it possible in javascript to have a variable that is not able to access out side the class's functions, but is able to be accessed by classes that inherit it? I.E:
class1 has protected var x = 4;
class2 inherits class1;
class2.prototype.getVar = function(){return /* parent, uber, super, whatever */ this.x;};
var cl2 = new class2();
console.log(cl2.x) // undefined
console.log(cl2.getVar()) // 4
No. Prototypal inheritance is limited to properties of objects.
Variables within the constructor are only available to other code in that variable scope.
You could probably come up with something like...
function cls1() {
var a = 'foo';
this.some_func = function() {
alert(a);
};
}
function cls2() {
cls1.apply(this, arguments);
var cls1_func = this.some_func;
var b = 'bar'
this.some_func = function() {
cls1_func.apply(this, arguments);
alert(b);
};
}
var x = new cls2;
x.some_func(); // alert "foo" alert "bar"
Or to make it more specific to your pseudo code...
function class1() {
var x = 4;
this.getVar = function() {
return x;
};
}
function class2() {
class1.apply(this, arguments);
var cls1_get_var = this.getVar;
this.getVar = function() {
return cls1_get_var.apply(this, arguments);
};
}
class2.prototype = Object.create( class1.prototype );
var cl2 = new class2;
console.log(cl2.x) // undefined
console.log(cl2.getVar()) // 4
I think you need to use a closure to achieve what your trying to do. Something like this:
Class1 = function() {
var x = 4;
return {
getVar: function() {
return x;
}
}
} ();// executes the function immediately and returns an
//an object with one method - getVar. Through closure this method
//still has access to the variable x
Class2 = function() { };// define a constructor function
Class2.prototype = Class1;//have it inherit from Class1
Cl2 = new Class2();//instantiate a new instance of Class2
console.log(Cl2.x);//this is undefined
console.log(Cl2.getVar());//this outputs 4
This is one of the neat things about javascript in that you can achieve the same things in javascript as you would in a class based language without all the extra key words. Douglas Crockford (always good to consult about javascript) explains prototypal inheritance here
Edit:
Just had a second look at your question.If you want newly created methods in your class to access the variable in the base class then you would have to call the getVar method within your own method.Like such:
Class2 = function() {
this.getVar2 = function() {
return this.getVar();
}
};
console.log(Cl2.getVar2()) //outputs 4