How can i set an object under another by constructor - javascript

I have a construcrtor simply like
function foo() {
this.bar = function() {
return "fubar";
}
}
here no problem when i call new foo().bar();
But if I wanna make something like this
function foo() {
this.bar = function() {
function subbar() {
return "subbar";
};
}
}
I've tried the versions below but none of them works.
function foo() {
this.bar = function() {
this.bar.subbar() {
return "subbar";
};
}
}
function foo() {
this.bar = function() {
this.bar.prototype.subbar() {
return "subbar";
};
}
}
How can i reach subbar like new foo().bar().subbar()

Just return an object with the inner most function:
function foo() {
this.bar = function() {
return { subbar: function subbar() {
return "subbar";
};
}
}
}
Alternatively, you could just return the function without the object:
function foo() {
this.bar = function() {
return function subbar() {
return "subbar";
};
}
}
Then you would call it like this: this.bar()() The second set of parens calls the returned subbar() function
Since functions are objects, when you call bar(), the return value will be the function subbar()

What you want is to return an object with a function attached to it.
function foo() {
this.bar = function() {
return {
subbar: function() {
return 'subbar';
}
};
};
}

Related

QML - How to call overloaded function from child

I have the QML component Rect.qml:
Rectangle {
id: prntRect
property var foo: function() {
console.log("FOO");
}
function bar() {
console.log("BAR");
}
}
and have created one in main.qml:
Rect {
id: chldRect
property var foo: function() {
console.log("FOO CHILD");
}
function bar() {
console.log("BAR CHILD");
}
}
Its possible to call prntRect's foo/bar implementations from within chldRect? If yes how?
Thanks!

AngularJS factory: Best way to call parent in literal?

If I have
var test = {
return {
foo: function() {
return 1
},
sub: {
bar: function() {
var foo = this.foo() // <--- here, does obviously not work
}
}
}
}
What is the recommended and best way to access foo() from within sub.bar() ...?
To clarify, I want to split an angularjs service into sections.
"Real" code:
angular.module('myApp').factory('Service' function() {
return {
foo: function() {
return 1
},
sub: {
bar: function() {
var foo = this.foo() // <--- here, does obviously not work
}
}
}
})
Since you are using an angular factory, you can Use the Revealing Module Pattern:
angular.module('myApp').factory('Service' function() {
function foo() {
return 1
}
var sub = {
bar: function() {
var foo = foo()
}
}
return {
foo: foo,
sub: sub
}
})
This is not ok:
return {
foo: function() {
return 1
}
}
You need to remove that return statement and within the function bar you can access the function foo using the name of the variable test as follow: test.foo()
var test = {
foo: function() {
return 98989;
},
sub: {
bar: function() {
var foo = test.foo();
console.log(foo);
}
}
};
test.sub.bar();
Another way is using the function bind, but it's overkill:
var test = {
foo: function() {
return 98989;
},
sub: {
bar: function() {
var foo = this.foo(); // Using the object 'this'
console.log(foo);
}
}
};
test.sub.bar.bind(test)();
Now, you can declare a variable service and use that variable:
angular.module('myApp').factory('Service'function() {
var service = {
foo: function() {
return 1
},
sub: {
bar: function() {
var foo = service.foo();
^^^^^^^
}
}
};
return service;
});

call a function within exports.run()

I have a file called something.js with this code:
exports.run = (args) => {
function foo() {
console.log("foo");
}
}
Now I want to call foo from another file.
My code looks like this with errors attached as comments:
const something = require("./something.js");
module.exports = {
callFoo: function() {
something.foo(); //TypeError: something.foo is not a function
something.run.foo(); //TypeError: something.run.foo is not a function
}
Is it possible to call such a function which is apparently not a function?
You assign an arrow function to exports.run and in that function, you define the foo function, but this function is not reachable from outside of the arrow function. Yur code is nearly equivalent to:
exports.run = function(args) {
function foo() {
console.log("foo");
}
}
You most likely want to write:
exports.run = {
foo() {
console.log("foo");
}
}
Or
exports.run = {
foo : function() {
console.log("foo");
}
}

How to get the parent function name of the function being called

I am trying to get the name of the parent function of the function being called.
For example if I have these functions:
var functions = {
coolfunction1: {
add: function () {
},
delete: function () {
},
save: function () {
}
},
coolfunction2: {
add: function () {
// i want to console.log() the name of the parent of this function,
// output: coolfunction2
},
delete: function () {
},
save: function () {
}
}
}
When I call functions.coolfunction2.add(), is there a way to log the name of the parent function that was run?
I know I can use the variable this but that only outputs the names of the children functions, add(), delete(), save().
How can I know that the coolfuntion2 was run?
I know this can be done manually, by rewriting the function name in the add() function, but is there a way to get the name dynamically?
You can add a getter to those methods as
Object.keys(functions).forEach(t =>
Object.keys(functions[t]).forEach(t2 => {
var func = functions[t][t2]; //save a reference to function since it won't be a function anymore once a getter is assigned
Object.defineProperty(functions[t], t2, {
get: function() {
console.log(t); //print the name of parent property or grand-parent property, etc
//func();
return func; //return the reference to this function
}
});
})
);
Demo
var functions = {
coolfunction1: {
add: function() {
},
delete: function() {
},
save: function() {
}
},
coolfunction2: {
add: function() {
console.log("a is invoked");
},
delete: function() {
},
save: function() {
}
}
};
Object.keys(functions).forEach(t =>
Object.keys(functions[t]).forEach(t2 => {
var func = functions[t][t2];
Object.defineProperty(functions[t], t2, {
get: function() {
console.log(t);
//func();
return func;
}
});
})
);
functions.coolfunction2.add();
functions.coolfunction2.add();
functions.coolfunction1.add();

typescript: context preservation. Is it a good idea to do it such way?

I want to keep this in class methods.
I can use arrow functions, but I want to override some methods in extended class.
Now I have this solution and it works:
class Foo {
bar = "Context preserved.";
constructor() {
this.foo = this.foo.bind(this);
}
foo() {
alert(this.bar);
}
}
class Foo2 extends Foo {
foo() {
alert(this.bar + " Class extended");
}
}
class Bar {
bar = "Context lost.";
}
let foo = new Foo2();
let bar = new Bar();
foo.foo.apply(bar); // Context preserved. Class extended
Is it a good practice to do it such way? If it is, is there some keyword in typescript to do it automatically?
like
class Foo() {
public conserved foo() { }
}
which generates:
var Foo = (function () {
function Foo() {
this.foo = this.foo.bind(this);
}
Foo.prototype.foo = function () { };
return Foo;
}());
It's a valid practice and it's being used.
I'm unaware of a way to tell typescript to do this automatically, but you can search the issues for something like it.
You can have a decorator that does that for you, for example:
function construct(constructor: Function, methods: string[], args: any[]) {
var c: any = function () {
return constructor.apply(this, args);
}
c.prototype = constructor.prototype;
let instance = new c();
methods.forEach(name => {
instance[name] = instance[name].bind(instance);
});
return instance;
}
function BindMethods(constructor: Function) {
const methods = [] as string[];
Object.keys(constructor.prototype).forEach(name => {
if (typeof constructor.prototype[name] === "function") {
methods.push(name);
}
});
return (...args: any[]) => {
return construct(constructor, methods, args);
};
}
#BindMethods
class Foo {
bar = "Context preserved.";
foo() {
console.log(this.bar);
}
}
let foo = new Foo();
setTimeout(foo.foo, 10);
(code in playground)
I tested it with this simple use case and it worked just fine.

Categories

Resources