function A() {
this.a = 'this is a';
var b = 'this is b';
}
function B() {
var self = this;
this.c = 'this is c';
var d = 'this is d';
// a: undefined, b: undefined, c: this is c, d: this is d
$("#txt1").text('a: ' + A.a + ', b: ' + b + ', c: ' + this.c + ', d: ' + d);
C();
function C() {
// this.c is not defined here
// a: undefined, b: undefined, c: this is c, d: this is d
$("#txt2").text('a: ' + A.a + ', b: ' + b + ', c: ' + self.c + ', d: ' + d);
}
}
B.prototype = new A();
var b = new B();
Is it possible for class B and inner function C to get variable a and b?
Fiddle file is here: http://jsfiddle.net/vTUqc/5/
You can get a in B, using this.a, since the prototype of B is an instance of A. You can also get a in C, using self.a:
function A() {
this.a = 'this is a'; // This is accessible to any instance of A
var b = 'this is b'; // This is not accessible outside the scope of the function
}
function B() {
var self = this;
alert(this.a); // Alerts 'this is a'
C(); // Also alerts 'this is a'
function C() {
alert(self.a);
}
}
B.prototype = new A();
new B();
You can't get b directly on the other hand. If you want to access it, you could use a function that returns its value:
function A() {
this.a = 'this is a';
var b = 'this is b';
this.returnb = function(){
return b;
}
}
Now b is accessible to instances of A via (new A()).returnb()
Related
I have the below code -
function x(a, b) {
this.b = b || 'test';
this.c = false;
}
x.prototype.z = function() {
if(this.c) {
console.log('hello')
}
}
let n = function(a, b, v, d) {
x.call(this,a, b);
this.a = a;
this.v = v;
this.d = d;
}
n.prototype = Object.create(x.prototype);
let n1 = new n();
Which three properties are set for n1? --> i find only b, c are getting set. but it is asking for 3 options
c
z
v
d
b
This is what n1 looks like
{
a: undefined,
b: "test",
c: false,
d: undefined,
v: undefined,
z: function() {
if (this.c) {
console.log('hello')
}
}
}
z also has a value because with Object.create(x.prototype) we copy over the x.prototype.z function. reference
I know I can create a toString() function on an object, so that every time it's printed or treated like a string it will first stringify the object with that function.
Is it possible to do that directly so I can use String object functions on the object?
var SomeObject = function(a, b){
this.a = a;
this.b = b
}
SomeObject.prototype.toString = function(){
return [ this.a, this.b ].join(' ')
}
var objInstance = new SomeObject('this', 'that');
console.log(objInstance + '') // This that
console.log(("" + objInstance).split('')) // [ 't', 'h', 'i', 's', ' ', 't', 'h', 'a', 't' ]
console.log(objInstance.split()) // Error
Is it possible to do so that the object "behaves" like a string when a String function is called on it?
In other words, I'd like objInstance.split() to have the same result as ("" + objInstance).split(''), and also objInstance.length or objInstance.match(/something/), etc.
You can let your objects inherit from String so that all string methods become available:
class SomeObject extends String {
constructor(a, b) {
super(a + " " + b);
this.a = a;
this.b = b;
}
}
var obj = new SomeObject('this', 'that');
console.log(obj.split(""));
No need to use complicated Proxy solutions :-)
All the String.prototype methods (except for .toString, .valueOf and [Symbol.iterator]) are "intentionally generic; [they do] not require that its this value be a String object. Therefore, [they] can be transferred to other kinds of objects for use as a method." You can call them on any value, they will coerce it to a string (using .toString() or .valueOf as usual).
You don't even need to use ES6 class extends to inherit from the builtin (which also makes your string value immutable), it works in ES5 as well:
function SomeObject(a, b) {
this.a = a;
this.b = b;
}
SomeObject.prototype = Object.create(String.prototype);
SomeObject.prototype.constructor = SomeObject;
SomeObject.prototype.toString = function() {
return this.a + " " + this.b;
};
var obj = new SomeObject('this', 'that');
console.log(obj.split(""));
One option would be to return a Proxy that checks whether the property exists on String.prototype, and if it does, calls that property with the string that represents the object:
// Declare the proxy handler up front here
// to avoid unnecessary creation of duplicate handler objects
const handler = {
get(obj, prop) {
if (obj[prop] !== undefined) {
return obj[prop];
}
const stringMethod = String.prototype[prop];
if (stringMethod) {
return stringMethod.bind(obj.a + ' ' + obj.b);
}
},
};
const SomeClass = function(a, b) {
this.a = a;
this.b = b
return new Proxy(this, handler);
}
const instance = new SomeClass('this', 'that');
// String methods:
console.log(instance.trim());
console.log(instance.includes('this'));
console.log(instance.includes('somethingelse'));
console.log(instance.split(''));
// Can still assign and retrieve values directly on the object as normal:
instance.foo = 'foo';
console.log(instance.foo);
One option to extend the SomeObject too, something like this.
var SomeObject = function(a, b){
this.a = a;
this.b = b
}
SomeObject.prototype.toString = function(){
return [ this.a, this.b ].join(' ')
};
SomeObject.prototype.split = function() {
return String.prototype.split.apply(this.toString(), arguments);
};
var objInstance = new SomeObject('this', 'that');
console.log(objInstance + '') // this that
//console.log(("" + objInstance).split('')) // [ 't', 'h', 'i', 's', ' ', 't', 'h', 'a', 't' ]
console.log(objInstance.split(''));
In a comment you've asked:
I was thinking about doing this programmatically by doing it for all functions - but is there a way to list all functions of an object?
Yes, you'd use getOwnPropertyNames on String.prototype and filter out the ones that aren't functions:
var SomeObject = function(a, b){
this.a = a;
this.b = b
}
SomeObject.prototype.toString = function(){
return [ this.a, this.b ].join(' ')
};
Object.getOwnPropertyNames(String.prototype).forEach(function(name) {
var fn = String.prototype[name];
if (name !== "toString" && typeof fn === "function") {
SomeObject.prototype[name] = function() {
return fn.apply(this.toString(), arguments);
};
}
});
var objInstance = new SomeObject('this', 'that');
console.log(objInstance + '') // this that
//console.log(("" + objInstance).split('')) // [ 't', 'h', 'i', 's', ' ', 't', 'h', 'a', 't' ]
console.log(objInstance.split(''));
I'm having a lot of trouble with this and cannot seem to find the correct answer anywhere. I'm creating an object A with various properties, and one of those properties is the sum of two others, like below:
var A = {
a:0,
b:0,
c: this.a + this.b
};
Where my issue comes in is that at run time when I reference A.c, I get NaN instead of 0, or whatever value it should be based on what I have assigned to a and b.
Please he;p. I'm completely confused.
Because the context this is not a reference of object A, rather is a reference
of the enclosing scope, i.e window.
So, this.a + this.b --> undefined + undefined --> NaN.
Example to illustrate the enclosing scope (in this case the object window):
var a = 5;
var b = 5;
var A = {
a: 0,
b: 2,
c: this.a + this.b
};
console.log(A.c);
An alternative is binding a function to that property c using a getter.
var A = {
a: 0,
b: 2,
get c() {
return this.a + this.b
}
};
console.log(A.c);
A.a = 33;
console.log(A.c);
Wrap A's c value (A.c) into a function like this:
var A = {
a:9,
b:2,
c:function() {
return this.a + this.b
}
};
console.log(A.c());
var obj = {
evtChange: function (v) { /* event on any (a, b) changes */
console.log("property changed >> " + v)
},
_a: 70,
_b: 80,
set a(v) {
if (v !== this._a) { /* to prevent unwanted recalculation for complexe calcul statements */
this._a = v;
this.c = this._a + this._b;
this.evtChange(this.c);
}
},
get a() {
return this._a;
},
set b(v) {
if (v !== this._b) { /* to prevent unwanted recalculation for complexe calcul statements */
this._b = v;
this.c = this._a + this._b
this.evtChange(this.c);
}
},
get b() {
return this._b;
},
/* using getter memo
** if we call obj.c first, getter methode will be replaced with a property.
** getter methode will be replaced too on any setters (a, b) call
*/
get c() {
delete this.c; // delete getter
return this.c = this._a + this._b // replace getter imediately with c property
}
};
console.log(obj);
console.log(obj.c);
console.log(obj);
obj.a = 500;
obj.b = 2000;
console.log(obj.c);
console output:
/*obj*/
{evtChange: ƒ, _a: 70, _b: 80}
/*obj.c*/
150
/*obj*/
{evtChange: ƒ, _a: 70, _b: 80, c: 150}
/*obj.a = 500*/
property changed >> 580
/*obj.b = 2000;*/
property changed >> 2500
/*obj.c*/
2500
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 years ago.
Improve this question
I heard that multiple inheritance is not supported in JavaScript.
Does the below example can be considered as Multiple Inheritance if no then can anyone please explain why...?
function A () {
this.a = 'a'
};
function B () {
this.b = 'b'
};
function AB () {
A.call(this);
B.call(this);
};
var obj = new AB();
console.dir(obj);
//Output: {a: "a", b: "b"}
Can the below example be considered Multiple Inheritance?
No
Can anyone please explain why?
Your AB (which I will call C from here on out) function doesn't actually extend A nor does it extend B:
function A () {
this.a = 'a';
}
function B () {
this.b = 'b';
}
function C () {
A.call(this);
B.call(this);
}
a = new A();
console.log('a is A', a instanceof A);
b = new B();
console.log('b is B', b instanceof B);
c = new C();
console.log('c is A', c instanceof A, 'c is B', c instanceof B);
You don't have any inheritance at all in that example. You do have function composition.
If you wanted to have inheritance, the C function would need to have a prototype that points to an instance of either A or B:
function A () {
this.a = 'a';
}
function B () {
this.b = 'b';
}
function C () {
A.call(this);
B.call(this);
}
C.prototype = new A();
//or
//C.prototype = new B();
a = new A();
console.log('a is A', a instanceof A);
b = new B();
console.log('b is B', b instanceof B);
c = new C();
console.log('c is A', c instanceof A, 'c is B', c instanceof B);
Note that because the C function has a single prototype you can only have single inheritance.
For object composition, it would be common to see a pattern along the lines of:
function A () {
this.a = 'a';
}
function B () {
this.b = 'b';
}
function C () {
this.a = new A();
this.b = new B();
}
a = new A();
console.log('a is A', a instanceof A);
b = new B();
console.log('b is B', b instanceof B);
c = new C();
console.log('c.a is A', c.a instanceof A, 'c.b is B', c.b instanceof B);
What you have done is called composition and it is often an alternative to multiple inheritance.
Here are some references that might help you
Prefer composition over inheritance?
https://softwareengineering.stackexchange.com/questions/134097/why-should-i-prefer-composition-over-inheritance
Here is the code that I got from this Named parameters in javascript:
var parameterfy = (function () {
var pattern = /function[^(]*\(([^)]*)\)/;
return function (func) {
// fails horribly for parameterless functions ;)
var args = func.toString().match(pattern)[1].split(/,\s*/);
return function () {
var named_params = arguments[arguments.length - 1];
if (typeof named_params === 'object') {
var params = [].slice.call(arguments, 0, -1);
if (params.length < args.length) {
for (var i = params.length, l = args.length; i < l; i++) {
params.push(named_params[args[i]]);
}
return func.apply(this, params);
}
}
return func.apply(null, arguments);
};
};
}());
var myObject = {
first: "",
second: "",
third: ""
};
var foo = parameterfy(function (a, b, c) {
//console.log('a is ' + a, ' | b is ' + b, ' | c is ' + c);
myObject.first = a;
myObject.second = b;
myObject.third = c;
console.log("first " + myObject.first + " second " + myObject.second + " third " + myObject.third);
});
foo(1, 2, 3); // gives 1, 2, 3
foo({a: 11, c: 13}); // gives 11, undefined, 13
foo({ a: 11, b:myObject.second, c: 13 }); // in order to avoid undefined, this is
Note that, in second instance of foo, I got undefined as I didn't pass b so I had to work around using third instance where I passed the current value of b.
Is there anyway to make it so that if I don't have to pass a value, for example, value of b in this case so that it still updates the given values of a and c but retains the value of b?
Something like the below may work:
var foo = parameterfy(function (a, b, c) {
//console.log('a is ' + a, ' | b is ' + b, ' | c is ' + c);
if(typeof a != 'undefined'){myObject.first = a;}
if(typeof b != 'undefined'){myObject.second = b;}
if(typeof c != 'undefined'){myObject.third = c;}
console.log("first " + myObject.first + " second " + myObject.second + " third " + myObject.third);
});
Here's the named parameter standard that has been successfully used for years and you should stick with it:
function myFunction(options) {
console.log(options.first);
console.log(options.second);
console.log(options.third);
}
myFunction({
first: 1,
second: 2,
third: 3
});