Calling property of One Function From Inside Another Javascript - javascript

I'm using functions as representations of classes.
function ClassOne()
{
this.doFunc = function() {
console.log("doFunc output");
}
}
function ClassTwo()
{
this.one = ClassOne();
console.log(this.one); // == undefined ???
this.init = function() {
this.one.doFunc();
}
this,init();
}
ClassTwo();
But I'm struggling to use one function inside another.
For example, the above code returns "Cannot read property 'doFunc' of undefined"
Why is this.one == undefined?

If you assign to a property of this inside a function, generally that indicates that the function is intended to be called as a constructor with new, eg:
this.one = new ClassOne();
Otherwise, if the function doesn't return anything... then, well, nothing gets returned (=> undefined)
function ClassOne()
{
this.doFunc = function() {
console.log("doFunc output");
}
}
function ClassTwo()
{
this.one = new ClassOne();
console.log(this.one);
this.init = function() {
this.one.doFunc();
}
this.init();
}
ClassTwo();
Or, you can have ClassOne explicitly return an object with a doFunc property, allowing it to be called without new:
function ClassOne()
{
return {
doFunc() {
console.log("doFunc output");
}
}
}
function ClassOne() {
return {
doFunc() {
console.log("doFunc output");
}
}
}
function ClassTwo() {
this.one = ClassOne();
console.log(this.one);
this.init = function() {
this.one.doFunc();
}
this.init();
}
ClassTwo();

Related

catch missing method call with javascript proxy

How can I get this code to work. I want to intercept all missing method calls on my function, and redirect them to a "catch all" kind of method on said function.
var foo=function(){
this.bar=function(){
return "found!";
}
this.not_found=function(){
return "method not found.";
}
}
var p = new Proxy(foo, {
get: function (target, prop) {
if (Object.keys(target).indexOf(prop) !== -1) {
// should call existing method.
//return target[prop]; <-- does not work.
}else{
// here i want to call "not_found() on foo() if prop doesnt exist
}
}
});
console.log(p.bar()); // should print out: found!;
console.log(p.foo()); // should print out: method not found;
thanks in advance!
foo is a function. As deepak said, if you create an object from it, it will work:
var Foo = function () {
this.bar = function () {
return "found!";
}
this.notFound = function () {
return "method not found.";
}
};
var p = new Proxy(new Foo, {
get: function (target, prop) {
if (Object.keys(target).indexOf(prop) !== -1) {
return target[prop];
} else {
return target['notFound'];
}
}
});
console.log(p.bar()); // prints: found!;
console.log(p.foo()); // prints: method not found;
Since Foo is acting like a constructor, I wrote it with a capital letter. Also, the convention is to use camel case for names. Took the liberty to change these.
A slightly cleaner version (using in):
var Foo = function () {
this.bar = function () {
return "found!";
}
this.notFound = function () {
return "method not found.";
}
};
var foo = new Foo();
var p = new Proxy(foo, {
get: function (target, prop) {
if (prop in target) {
return target[prop];
} else {
return target['notFound'];
}
}
});
console.log(p.bar()); // prints: found!;
console.log(p.foo()); // prints: method not found;

Overriding a function on a javascript object's property

How would you override a function on a javascript object when the function is on another object within the parent object.
Example:
function TestingABC() {
this.events = { finish: function() { console.log("FINISHED"); } };
}
function TestingXYZ() {
TestingABC.call(this);
}
TestingXYZ.prototype = Object.create(TestingABC.prototype);
How would I override the events.finish function on TestingXYZ to run the parent (TestingABC) code along with some new code that I need to write?
Because the events object is property of the instance, not on the prototype, you could employ a technique similar to monkey patching, where you store a reference to the current function, then override the current function with one that can call the old one in addition to doing other stuff.
e.g.
function TestingABC() {
this.events = { finish: function() { console.log("FINISHED"); } };
}
function TestingXYZ() {
TestingABC.call(this);
var superEvents = this.events;
this.events = {
finish: function () {
superEvents.finish();
doMyStuff();
}
};
}
TestingXYZ.prototype = Object.create(TestingABC.prototype);
.events is an instantiated property of the TestingABC() constructor - so you can amend the value once you have an instantiation of it.
Perhaps something like this is what you're after?...
function TestingABC() {
this.events = {
finish: function() {
console.log('ABC FINISHED');
},
other: function() {
console.log('ABC OTHER');
}
};
}
function TestingXYZ() {
TestingABC.call(this);
}
TestingXYZ.prototype = Object.create(TestingABC.prototype);
TestingXYZ.prototype.callEvents = function() {
this.events.finish();
this.events.other();
}
var test1 = new TestingABC();
var test2 = new TestingXYZ();
test2.events.finish = function() {
console.log('XYZ FINISHED');
};
test1.events.finish();
test1.events.other();
//-> ABC FINISHED
//-> ABC OTHER
test2.callEvents();
//-> XYZ FINISHED
//-> ABC OTHER

scope of "this" in async function of ionic angular app

I'm trying to execute a function, which is not found, UNLESS I save a reference to the function in a seperate variable:
function updateCheck() {
if (this.isNewVersionNeeded()) {
var buildFunc = this.buildObject();
this.updateBiography().then(function(){
buildFunc();
})
}
};
The buildObject function only executes if I save it before executing this.updateBiography (async function) and execute it via the variable I saved it in (buildFunc).
The following does NOT work:
function updateCheck() {
if (this.isNewVersionNeeded()) {
this.updateBiography().then(function(){
this.buildObject();
})
}
};
I expose all functions via a service object:
var service = {
all: all,
updateBiography: updateBiography,
get: get,
updateCheck: updateCheck,
isNewVersionNeeded:isNewVersionNeeded,
buildObject:buildObject
};
return service;
When I log the "this" object while Im right before the execution of buildFunc, it logs window/global scope. Why is this and how should I deal with this? I do not want to save all my async methods in a seperate variable only to remember them. How should I deal with this problem and why does it not work?
The entire service:
(function () {
angular
.module('biography.services', [])
.factory('Biography', Biography);
Biography.$inject = ['$http'];
function Biography($http) {
var biographyObject = { } ;
var service = {
all: all,
updateBiography: updateBiography,
get: get,
updateCheck: updateCheck,
isNewVersionNeeded:isNewVersionNeeded,
buildObject:buildObject
};
return service;
var self = this;
function updateCheck() {
if (this.isNewVersionNeeded()) {
this.updateBiography().then(function(){
self.buildObject();
})
}
};
function updateBiography() {
return $http.get("Apicall adress")
.then(function (resp) {
window.localStorage.setItem('biography', resp.data);
window.localStorage.setItem('biographyTimeStamp', Date.now());
}, function (err) {
console.log('ERR', err);
});
}
function all() {
return biographyObject;
}
function get(name) {
var biography = biographyObject;
for (var i = 0; i < biography.length; i++) {
if (biography[i].name === name) {
return biography[i];
}
}
return null;
}
function buildObject() {
var temp = JSON.parse(window.localStorage.getItem('biography'));
biographyObject = temp;
};
function isNewVersionNeeded() {
prevTimeStamp = window.localStorage.getItem('biographyTimeStamp');
var timeDifference = (Date.now() - prevTimeStamp);
timeDifference = 700000;
if (timeDifference < 600000) {
return false;
}
else {
return true;
}
}
}
})();
The context (different from function scope) of your anonymous function's this is determined when it's invoked, at a later time.
The simple rule is - whatever is to the left of the dot eg myObj.doSomething() allows doSomething to access myObj as this.
function updateCheck() {
if (this.isNewVersionNeeded()) {
this.updateBiography().then(function() {
// whichever object has this anonymous function defined/invoked on it will become "this"
this.buildObject();
})
}
};
Since you're just passing your function reference, you can just use this
function updateCheck() {
if (this.isNewVersionNeeded()) {
this.updateBiography().then(this.buildObject);
}
};
and if this.buildObject is dependent on the context (uses the this keyword internally), then you can use
function updateCheck() {
if (this.isNewVersionNeeded()) {
this.updateBiography().then(this.buildObject.bind(this));
}
};
this is determined by whatever context (object) the function is invoked on, and it appears that an anonymous function, or a function not referenced through an object defaults to having a window context. the bind function replaces all instances of this with an actual object reference, so it's no longer multi-purpose
same function invoked in different contexts (on different objects)
var obj = {
a: function () {
console.log(this);
}
};
var aReference = obj.a;
aReference(); // logs window, because it's the default "this"
obj.a(); // logs obj
The reason is here 'this' refers to callback function.You can't access 'this' inside callback.Hence solution is,
function Biography($http) {
var self = this;
function updateCheck() {
if (this.isNewVersionNeeded()) {
this.updateBiography().then(function(){
self.buildObject();
})
}
};
Using ES6 syntax:
function updateCheck() {
if (this.isNewVersionNeeded()) {
this.updateBiography().then(()=>{
this.buildObject();
})
}
};

Javascript, groovy like invoke method?

I was wondering if there is a way having for instance:
var klass = {
getName : function () { return "myname"; }
}
and doing klass.getName();
having a method fire before getName is actually called? In Groovy all method calls can for instance be listened to if an invoke method is added:
var klass = {
invoke function() { console.log("fires before getName()") ; },
getName : function () { return "myname"; }
}
I know this a long shot, but worth a try.
Not interested in altering the way the method is actually invoked: klass.getName()
The obvious answer is to simply call invoke in your getName method. If, for whatever reason, you don't wanna do that, you can proxy the methods of klass afterwards:
// loop through all properties of klass
for (var i in klass) {
// skip if it's not a custom property, not a function or the invoke function
// (to prevent infinite nested calls)
if(!klass.hasOwnProperty(i) || typeof klass[i] !== 'function'
|| i === 'invoke') {
continue;
}
// add the invoke() method as a proxy to the current method
var old = klass[i];
klass[i] = function () {
klass.invoke.apply(this, arguments);
return old.apply(this, arguments);
};
}
You can also put everything together neatly like this:
var klass = (function () {
this.invoke = function () {
console.log('called invoke()');
};
this.getName = function () {
return "called getName()";
};
(function (_this) {
for (var i in _this) {
if (!_this.hasOwnProperty(i) || typeof _this[i] !== 'function'
|| i === 'invoke') {
continue;
}
var old = _this[i];
_this[i] = function () {
_this.invoke.apply(_this, arguments);
return old.apply(_this, arguments);
};
}
})(this);
return this;
})();
console.log(klass.getName());

How to get interface name in implemented function

Below is the code I have used to achieve interface concept in javascript:
function Interface1(ImplementingClass) {
return {
implementedFunction : ImplementingClass.implementedFunction
}
}
function Interface2(ImplementingClass) {
return {
implementedFunction : ImplementingClass.implementedFunction
}
}
function ImplementingClass() {
this.implementedFunction = function() {
// How to get implemented interface name, for
// example here interface name should be Interface1???
}
}
function Test() {
this.test = function() {
return new Interface1(new ImplementingClass());
}
}
var test = new Test();
test.test().implementedFunction();
Question: How to get interface name in implemented function, for example in java we use instance of operator
if(this instance of Interface) {
// Do something
}
No, instanceof won't work - it's only for prototypical inheritance from a constructor function's prototype object. If you need information about your interface, you will need to place it on your interface object:
function Interface(implementingInstance) {
return {
interfaceName: "MyInterface",
implementedFunction : implementingInstance.implementingFunction
}
}
function ImplementingClass() {
this.implementingFunction = function() {
console.log(this.interfaceName);
}
}
/* maybe helpful:
ImplementingClass.prototype.interfaceName = "noInterface"; // real instance
*/
function Test() {
this.test = function() {
return Interface(new ImplementingClass());
}
}
new Test().test().implementedFunction();
// calls `implementingFunction` on the object with the `interfaceName` property

Categories

Resources