Set variable to function but that function should not get executed - javascript

I am setting some variable in someMethod1 and want to pass that variable to someMethod2. Here I just want to set variable to someMethod2 function but that method should not get called. It needs to be called later on some event(click). How can I achieve this one? Please help me.
someMethod1 = function() {
var test = "testText";
someMethod2(test)
};
someMethod2 = function(check) {
var a = check;
};

You can do it with saving variable in global scope:
var sharedVars = {};
function someMethod1() {
sharedVars.a = 'testText';
}
function someMethod2(check) {
var a = (check)? check : sharedVars.a;
}
or creating some object that stores and returns value by key:
var sharedStorage = {
data: {},
set: function(key, value) {
this.data[key] = value;
return this;
},
get: function(key, fallback) {
return this.data[key] || fallback;
}
};
function someMethod1() {
sharedStorage.set('a', 'testText');
}
function someMethod2() {
var a = sharedStorage.get('a');
}

Declare var test outside, then set it inside someMethod1(). Now you can call someMethod2() on a click event and set test to a.
var test;
someMethod1 = function() {
test = "testText";
};
someMethod2 = function() {
var a = test;
};

Related

How to overwrite default value from properties of this object with call or apply method in JS

I've started learning call, apply and bind and now i want to use it but have some problems:
I have a function:
let addTableRow = function() {
let template = HtmlTemplatesTelephony.ks.renderTableRow;
this.id = "";
this.creationDate = "";
this.address = "";
this.numberOfUser = "";
this.accessExisting = true;
$(DOM.tableBodyContainer).append(template(this));
};
I declared the this properties as default values
Here i invoke the function either with .call() or without:
let updateTable = function() {
let locations = userData().locations;
if(locations.length > 0) {
for(let location of locations) {
UIController.addLocation.call(location);
}
} else {
UIController.addLocation();
}
};
My idea was to use the 'this' values in the 'addTableRow' as default values in case of invoking the function without .call(). And when calling it with .call() I want to overwrite the 'this' default values. But exactly the opposite happens.
I know I could pass the object as parameter and set default object, but is there an other way to do it with .call()? Or is it the wrong use case for .call()?
Thanks for help!
***** UPDATE ******
Sorry, it is written in module pattern and i forgot to mention that the function 'addTableRow' is called 'addLoaction' in the return object. Here's some more code:
My UI controller:
let UIController = (function() {
let DOM = {
tableHeadContainer: $('thead'),
tableBodyContainer: $('tbody'),
inputNumberLocations: $('#numberLocations'),
inputAddress: $('.js-location-address'),
inputUser: $('.js-location-user'),
inputVpn: $('.js-location-vpn'),
btnDeleteLocation: $('.js-delete-location'),
};
let addTableRow = function() {
let template = HtmlTemplatesTelephony.ks.renderTableRow;
this.id = "";
this.creationDate = "";
this.address = "";
this.numberOfUser = "";
this.accessExisting = true;
$(DOM.tableBodyContainer).append(template(this));
};
return {
getDOM: DOM,
addLocation: addTableRow,
removeLocation: removeTableRow
}
})();
And my main controller:
let Controller = (function(dataController, UIController) {
let updateTable = function() {
let locations = userData().locations; // locations has the same properties as in function 'addTableTow'
if(locations.length > 0) {
for(let location of locations) {
UIController.addLocation.call(location);
}
} else {
UIController.addLocation();
}
};
return {
init: function() {
setupEventListeners();
updateTable();
},
}
})(dataController, UIController);
I hope it's more clear now.
When you .call(obj), you are starting your function with this being equal to that object. When you say this.id = "", you are overriding the id that you already had.
This may be a solution to your problem:
if (!this.id) {
this.id = "";
}
if (!this.property) {
this.property = "default";
}
// etc.

private object not setting data

Hi I'm trying to implement a LinkedList in Javascript. When i assign a value to my node it doesn't seem to store it when I use my getter. For example:
var Node =function() {
var _data;
var _next ={};
var that = this;
that.getData = function() {
return _data;
};
that.setData = function(data) {
that._data = data;
};
that.getNext = function() {
return _next;
};
that.setNext = function(next) {
that._next = next;
};
return that;
};
Will not work with:
var nodeObj = new Node();
nodeObj.setData("hello");
console.log(nodeObj.getData());
_data is not the same as that._data, you must do this:
that.getData = function() {
return that._data;
};
OR you could do this instead:
that.setData = function(data) {
_data = data;
};
the benefit of the second approach being that you're simulating a private variable (because you cannot do nodeObj._data in the second case but you can in the first)
also var that = this; is unnecessary, you can simply do this._data in this case.
For your case here, you can assume that if you're calling a function like yourObject.someFunction(), then within someFunction the value of this equals yourObject. (And this isn't always true in javascript but since you're starting off you should think about it this way for now. If you pass a function to another function as a variable and then call it then this wouldn't be the case).

How to create a Javascript function that inspects objects/ function based on property names that will survive minifcation?

Suppose I have a function proxyThrough like this:
function proxyThrough(parentClass, childObjPropertyName, methodName) {
parentClass.prototype[methodName] = function() {
this[childObjPropertyName][methodName].apply(this[childObjPropertyName], arguments);
};
}
childPropertyName and methodName are both strings, and it looks up the functions by name.
I know that this will not survive minification as a result.
How can I get functions like this to survive minification?
Example
This is what I am doing currently:
var BaseView = require('./BaseView');
var FooView = require('./FooView');
function BarView() {
this._fooView = new FooView();
}
BarView.prototype = Object.create(BaseView.prototype);
BarView.prototype.constructor = BarView;
BarView.prototype.anAction = function() {
this._barView.anAction.apply(this._barView, arguments);
};
BarView.prototype.anotherAction = function() {
this._barView.anotherAction.apply(this._barView, arguments);
};
This is what I would like to do instead:
var BaseView = require('./BaseView');
var FooView = require('./FooView');
function BarView() {
this._fooView = new FooView();
}
BarView.prototype = Object.create(BaseView.prototype);
BarView.prototype.constructor = BarView;
function proxyThrough(parentClass, childObjPropertyName, methodName) {
parentClass.prototype[methodName] = function() {
this[childObjPropertyName][methodName].apply(this[childObjPropertyName], arguments);
};
}
['anAction', 'anotherAction'].forEach(proxyThrough.bind(null, BarView, '_fooView'));
I guess it depends on how the minifier works, but if it renames the same property name consistently, you could use a helper function to get the minified property name:
function minifiedName(obj) {
for (var prop in obj) {
return prop;
}
}
[
minifiedName({anAction: null}),
minifiedName({anotherAction: null})
].forEach(proxyThrough.bind(null, BarView, '_fooView'));

Sync Objects to changed parameters

I want to bind the parameters of an Object to another Object, so they update whenever the other one updates aswell.
Object1 =
x: 1
Object2 =
x: Object1.x
y: 0
so that Object1.x = 2; updates Object2 aswell. (And the other way round)
How do I do that efficiently? I could use .watch and update the other one on each change, but I doubt that is a smart solution. Am I missing something?
Depending on the environment this has to run, a getter might be a suitable solution:
Object.defineProperty(Object2, 'x', {
get: function() {
return Object1.x;
},
enumerable: true
});
You might also want to define a setter to sync changes back.
You need to implement the observer/observable pattern.
I could use .watch and update the other one on each change, but I
doubt that is a smart solution
How you notify the other part if something changes? Why isn't a smart solution? It's just the solution!
Check this code listing I did to show you a possible implementation of objects capable of listening changes of other objects creating a base ObservableObject prototype (also available in JSFiddle!):
var ObservableObject = function () {
this._handlers = [];
this._disablePropertyChangeNotification = false;
};
ObservableObject.prototype = {
get disablePropertyChangeNotification() {
return this._disablePropertyChangeNotification;
},
set disablePropertyChangeNotification(value) {
this._disablePropertyChangeNotification = value;
},
listenPropertyChange: function (handler) {
this._handlers.push(handler);
},
notifyPropertyChange: function (propertyName) {
if (!this.disablePropertyChangeNotification) {
this._handlers.forEach(function (handler) {
handler(propertyName);
});
}
},
};
var A = function () {};
A.prototype = new ObservableObject();
Object.defineProperty(A.prototype, "name", {
get: function () {
return this._name;
},
set: function (value) {
this._name = value;
this.notifyPropertyChange("name");
}
});
var B = function () {};
B.prototype = new ObservableObject();
Object.defineProperty(B.prototype, "name", {
get: function () {
return this._name;
},
set: function (value) {
this._name = value;
this.notifyPropertyChange("name");
}
});
var someObjectA = new A();
var someObjectB = new B();
someObjectA.listenPropertyChange(function (propertyName) {
// This will prevent an infinite loop where
// property from A is set by B and viceversa
someObjectA.disablePropertyChangeNotification = true;
someObjectB[propertyName] = someObjectA[propertyName];
someObjectA.disablePropertyChangeNotification = false;
});
someObjectB.listenPropertyChange(function (propertyName) {
// This will prevent an infinite loop where
// property from A is set by B and viceversa
someObjectB.disablePropertyChangeNotification = true;
someObjectA[propertyName] = someObjectB[propertyName];
someObjectB.disablePropertyChangeNotification = false;
});
// We set name on A instance, and we print B instance name value
someObjectA.name = "hello world";
$(document.body).append("<p>someObjectB.name: " + someObjectB.name + "</p>");
// We set name on B instance, and we print A instance name value
someObjectB.name = "hello world changed";
$(document.body).append("<p>someObjectA.name: " + someObjectA.name + "</p>");

Multiple Factories in Node?

Trying to create multiple factories in Node. Do they have to be in separate files? If they are, how do I make sure to access both?
index.js
var myFunc = function () {
this.data = {
thingOne: null,
thingTwo: null,
thingThree: null
};
this.fill = function (info) {
for (var prop in this.data) {
if (this.data[prop] !== 'undefined') {
this.data[prop] = info[prop];
}
}
};
this.triggerAction = function () {
//make some action happen!
};
module.exports = function (info) {
var instance = new myFunc();
instance.fill(info);
return instance;
};
When I add another function below that it breaks the existing code with an object [object Object] has no method 'triggerAction:'
var myFunc2 = function () {
this.data = {
thingOne: null,
thingTwo: null,
thingThree: null
};
this.fill = function (info) {
for (var prop in this.data) {
if (this.data[prop] !== 'undefined') {
this.data[prop] = info[prop];
}
}
};
this.triggerAction2 = function () {
//make some action happen!
};
};
module.exports = function (info) {
var instance = new myFunc2();
instance.fill(info);
return instance;
};
So do I have to put the second function in a separate file? And if I do, how do I modify package.json to make sure it sees the second file? Thanks!
The short answer is no.
The error you are seeing is caused because you are overwriting the value of the exports property of the module - effectively replacing the first assignment with the last.
If you want these to be in the same module, you would need to export them separately:
module.exports.factoryA = function(...) {...}
module.exports.factoryB = function(...) {...}
To reference these from another module either of these patterns would work:
var factories = require('./myfactories');
var factoryAResult = factories.factoryA(...);
var factoryBResult = factories.factoryB(...);
or
var factoryA = require('./myfactories').factoryA;
var factoryAResult = factoryA(...);

Categories

Resources