Javascript prototype undefined instead of inherited? - javascript

function test() {
this.a = {
b: 4
};
}
test.prototype.a = {
c: 5
};
var example = new test();
Why is example.a.c == undefined?
Shouldn't it inherit the prototype and return 5?
If this isn't possible, is there some way to add code to return the prototype?:
function test() {
this.a = {
b: 4,
c: *this.return.prototype*
};
}

example.a either references one object or the other, you can't directly make it retrieve properties from different objects.
What I would do is making example.a an object which inherits from the other one:
function test() {
this.a = Object.create(test.a_proto);
this.a.b = 4;
}
test.a_proto = {
c: 5
};
var example = new test();
console.log(example.a.b); // 4 (own)
console.log(example.a.c); // 5 (inherited)

Define a getter for a.c that accesses the prototype.
function test() {
this.a = {
b: 4,
get c() {
return test.prototype.a.c;
}
};
}
test.prototype.a = {
c: 5
};
var example = new test();
console.log(example.a.b);
console.log(example.a.c);
// update prototype
test.prototype.a.c = 10;
console.log(example.a.c);

When you visit 'a' , it firstly find in example. If not find ,it will try to find 'a' in example construct's prototype.So it try to visit test.ptototype.c.So your code can't find examlpe.c.I think you can change your code like this.
function test() {
this.a = {
b: 4
};
}
test.prototype.c = 5;
var example = new test();
console.log(example.c);//print 5

Related

Multiple inheritance console output

I am using below code. I'm getting wrong output console with my code. Right now i am getting "this is aB" but i required constructor related output on my output console. Like "this is aA" for first, "this is aB" for second, "this is aC" for third console.
function A () {
this.name = "A";
}
A.prototype.a = function () {
console.log("this is a"+this.name);
}
function B () {
this.name = "B";
}
B.prototype.b = function () {
console.log("this is b"+this.name);
}
function C() {
this.name = "C";
A.call(this);
B.call(this);
}
C.prototype = Object.assign({}, A.prototype, B.prototype);
C.prototype.constructor = C;
C.prototype.c = function () {
console.log("this is c"+this.name);
}
var x = new C();
x.a(); //this is aB
x.b(); //this is bB
x.c(); //this is cB
this in all three constructors refers to the same object: The one created by the new operator. That one object can only have one name property. So whichever constructor you call last will "win" and the name will be assigned by that. Thus, you're seeing B all the time because even with new C, first C writes C, then A writes A (overwriting C), and finally B writes B (overwriting A).
If you want the code related to each level in the hierarchy to have its own name property, you cannot literally do that, but you can get close by having each one use its own property (e.g., nameA, nameB, and nameC). You can do this in a way that doesn't require you to remember which level you're writing the code at by using brackets notation and a variable shared by all the code for each level.
I'm not recommending that. Whatever the actual problem you're trying to solve is, there's probably a better solution.
But here's how you'd do it:
var A = (function() {
var name = "nameA"; // <== We declare a variable and put this level's property name in it
function A() {
this[name] = "A"; // <== Note we're using brackets notation here
}
A.prototype.a = function() {
console.log("this is a: " + this[name]); // <== Brackets again here
};
return A;
})();
var B = (function() {
var name = "nameB"; // <== Same again for B
function B () {
A.call(this);
this[name] = "B";
}
B.prototype = Object.create(A.prototype);
B.prototype.constructor = B;
B.prototype.b = function() {
console.log("this is b: " + this[name]);
};
return B;
})();
var C = (function() {
var name = "nameC";
function C() {
B.call(this);
this[name] = "C";
}
C.prototype = Object.create(B.prototype);
C.prototype.constructor = C;
C.prototype.c = function() {
console.log("this is c: " + this[name]);
};
return C;
})();
var x = new C();
x.a(); //this is aA
x.b(); //this is bB
x.c(); //this is cC
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="//tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
The one object all three constructors work with will end up with three properties: nameA, nameB, and nameC.
Again, I'm not recommending that, just pointing out that it's possible, and can suit some problems, although it's unclear whether it suits yours.
That was 2016. Here in 2020, you'd probably solve this with private fields. You can use them with a transpiler now and support is being actively added to JavaScript engines:
// NOTE: Only works in environments that support private fields (such as
// modern Chromium-based browsers)
class A {
#name; // <== Private field, only accessible to A's code
constructor() {
this.#name = "A";
}
a() {
console.log("this is a: " + this.#name);
}
}
class B extends A {
#name; // <=== Private field, only accessible to B's code
constructor() {
super();
this.#name = "B";
}
b() {
console.log("this is b: " + this.#name);
}
}
class C extends B {
#name; // <=== Private field, only accessible to C's code
constructor() {
super();
this.#name = "C";
}
c() {
console.log("this is c: " + this.#name);
}
}
const x = new C();
x.a(); // tthis is a: A
x.b(); // tthis is b: B
x.c(); // tthis is c: C
The one object created by new C will have a different private #name field for each class.

Default enum value in javascript class constructor

I have a simple class, and I'm trying to figure out how to set a default value in the constructor:
var Foo = function(bar = Foo.someEnum.VAL1) {
this.bar = bar;
someEnum = {VAL1 : 1, VAL2: 2};
}
and to use it like:
var myFoo = new Foo(Foo.someEnum.VAL1);
but this is apparently wrong. What's the correct way to set a default enum value, or do I need to set the default to null, and check for the null in the constructor and set accordingly?
To clarify, bar is an enum for the Foo class. There are other properties in the class that are not shown. Also, updated class code.
You can try this if you want to make bar an optional parameter:
function Foo(bar) {
this.bar = bar || Foo.enum.VAL1; //If bar is null, set to enum value.
}
//Define static enum on Foo.
Foo.enum = { VAL1: 1, VAL2: 2, VAL3: 3 };
console.log(new Foo().bar); //1
console.log(new Foo(Foo.enum.VAL3).bar); //3
Do you just want bar to be defined inside the function?
var Foo = function() {
var bar = {VAL1 : 1, VAL2: 2};
}
or for a blank starting object:
var Foo = function() {
var bar = {};
}
Or are you wanting it to be set from a parameter that's passed into the function?
var Foo = function(barIn) {
var bar = barIn;
}
Another option - create the object (enum) from values passed in:
var Foo = function(val1, val2) {
var bar = {VAL1 : val1, VAL2: val2};
}
The possibilities go on, but it's not entirely clear what you're trying to achieve.
I'm not entirely sure what you are trying to do but maybe it is this...
var Foo = function (bar = 1) {
this.bar = bar;
}
Foo.VAL1 = 1;
Foo.VAL2 = 2;
Now you can do:
foo1 = new Foo();
alert(foo1.bar); //alerts 1;
foo2 = new Foo(Foo.VAL2);
alert(foo1.bar); //alerts 2;

Javascript property get and set similar to c# .net

i want to functionality something similar to get property of C# .net. for example
var method : function() {
return "something which always change";
},
var objectName = {
property : method()
};
so whenever i call objectName.property this should return the actual new values. not the value set at the time of declaration. is it possible.
In .net property hold the function address and that function get called each time. i want the functionality like that.
thanks,
Use Object.defineProperty to override the getter.
var counter = 0;
var method = function() {
return counter++;
};
function ObjectName() {}
Object.defineProperty(ObjectName.prototype, 'property', {
get: method
});
var objectName = new ObjectName();
console.log(objectName.property); // 0
console.log(objectName.property); // 1
JSBin Demo https://jsbin.com/racegeteni/edit?js,console
other way to write this in more like a .net c# style is
var o = {
a: 7,
get b() {
return this.a + 1;
},
set c(x) {
this.a = x / 2
}
};
console.log(o.a); // 7
console.log(o.b); // 8
o.c = 50;
console.log(o.a); // 25
For OOP reasons, you should treat an object as a Class in .Net.
For example:
var Superman = function () {
this.quality = 'charming';
this.height = "6'5\"";
this.fly = function() {
console.log('flying..');
}
this.save = function(name) {
console.log('Save ' + name);
}
return this;
};
var CK = Superman();
console.log(CK.quality);
CK.save('L. Lane');

How to conditionally add properties to a javascript object literal

I am trying to do the following to satisfy the requirements of a code builder (Sencha Cmd to be specific).
This is the essence I what I need to do. The critical factor is that the function body MUST end with a return of an object literal. I cant return a variable due to restrictions in the builder. So, how to add a property 'b' at the point of the pseudo code below if the parameter 'includeB' is true, but NOT add a property AT ALL if it is false. ie b==undefined or b==null is not allowed.
Perhaps it is not possible.
function create(includeB) {
// Can have code here but the final thing MUST be a return of the literal.
// ...
return {
a : 1
// pseudo code:
// if (includeB==true) then create a property called b
// and assign a value of 2 to it.
// Must be done right here within this object literal
}
}
var obj = create(false);
// obj must have property 'a' ONLY
var obj = create(true);
// obj must have properties 'a' and 'b'
Thanks for reading and considering,
Murray
If you can use ES6, use the spread properties.
function create(includeB) {
return {
a : 1,
...(includeB ? { b: 2 } : {}),
};
}
You've pretty much shown a use case for a constructor function instead of using an object literal:
function CustomObject(includeB) {
this.a = 1;
if (includeB) {
this.b = 2;
}
}
//has `a` only
var obj1 = new CustomObject(false);
//has `a` and `b`
var obj2 = new CustomObject(true);
After re-reading your question it appears that you've got limited access in modifying the function. If I'm understanding your question correctly you can only change a limited portion of the script:
function create(includeB) {
// modifications may be done here
// the rest may not change
return {
a : 1
}
}
var obj = create(false);
// obj must have property 'a' ONLY
var obj = create(true);
// obj must have properties 'a' and 'b'
If that's the case, then you could simply skip the later part of the function:
function create(includeB) {
if (includeB) {
return {
a: 1,
b: 2
};
}
return {
a: 1
};
}
You cannot put boolean logic inside a javascript literal definition. So, if your builder requires the the returned object can ONLY be defined as a javascript literal, then you cannot define properties conditionally that way.
If you can create an object inside your function, modify that object using logic and then return that object, then that's pretty easy.
function create(includeB) {
var x = {
a: 1
};
if (includeB) {
x.b = 2;
}
return x;
}
Your other option would be to wrap the create function and do it outside the create function.
function myCreate(includeB) {
var x = create(includeB)
if (includeB) {
x.b = 2;
}
return x;
}
Or, you could even wrap the create function transparently so callers still use create(), but it's behavior has been altered.
var oldCreate = create;
create = function(includeB) {
var x = oldCreate(includeB);
if (includeB) {
x.b = 2;
}
return x;
}
I recently had to do this, and found you could use a self-calling function within an object's definition (if using ES6). This is similar to the accepted answer, but might be useful for others who need to do this without first defining a constructor function.
For example:
let obj = (() => {
let props = { a: 1 };
if ( 1 ) props.b = 2;
return props;
})();
makes the object: { a: 1, b: 2 }
It's handy for more complicated objects, keeping the construction continuous:
let obj = {
a: 1,
b: (() => {
let props = { b1: 1 };
if ( 1 ) props.b2 = 2;
return props;
})(),
c: 3
}
makes the object:
{
a: 1,
b: {
b1: 1,
b2: 2
},
c: 3
}
You could define it later:
var hasA = create(); // has hasA.a
var hasBoth = create();
hasBoth.b = 2; //now has both
Alternatively, using your argument in create:
function create (includeB) {
var obj = {
a : 1
};
if (includeB) {
obj.b = 2;
}
return obj;
}
Below should work. I hope this help.
function create(includeB){
var object = {
a: 1
};
if (includeB)
object.b = 2;
return object;
}
How about this:
function create(includeB) {
return includeB && { a:1, b:2 } || { a:1 };
}
When includeB is true, the create function will return {a:1, b:2}. If includeB is false, it will return whatever is after the or - in this case, the {a:1} object.
create(true) returns { a:1, b:2 }.
create(false) returns { a:1 }
If you would like to use a declaration to satisfy the same requirement once without too much bloat, you can also simply do the following:
var created = function(includeB) {
var returnObj = { a : 1 };
if(includeB) { returnObj.b = 2; }
return returnObj;
}}(); //automatically runs and assigns returnObj to created

Is possible to pass to a function the properties of an object without the arguments defined and use them by the object's keys?

Quick and strange question:
I have an object (in this example is small but in the project is larger):
var myObject = {
hello: 1, // easier I think
'hey.ya': 5 // quite impossible but the first option is valid too
}
then I want to pass somehow to a function and use "hello" for example in a closure like this
function x(){
// my closure
return function(){this.init = function(){alert(hello)}, this.heyYa = function(){alert(/* I do not know how to call the other hey.ya variable */)}}
}
var myClass = x(), instance = new myClass(); instance.init();
thanks!
You need to use the myObject
var myObject = {
hello: 1,
'hey.ya': 5
}
function x(obj){
return function(){
this.init = function(){
alert(obj.hello)
},
this.heyYa = function(){
alert(obj['hey.ya'])
}
}
}
var myClass = x(myObject);
var instance = new myClass();
instance.init(); // alerts '1'
instance.heyYa(); // alerts '5'

Categories

Resources