I have a function declared
x.funstuff = function(){
}
When I want to call it within a file I simply declare
x = {};
However when I call it from another file I get issues. Even after I use x = {};
in that seperate file.
How does one call this function from another file?
If you are doing it in the order specified then you are overwriting your x variable with a new object.
x.funstuff = function() {};
means that x = { funstuff: function() {} };
then x = {}; replaces it
If you are trying to call the function do it as:
x.funstuff();
Related
How can I make a function which was originally defined elsewhere in my code be denied or limited access to certain objects when it gets assigned to an object?
Short Example
var func = function() {
console.log(window.screenX); // <-- this should work
document.createElement("div"); // <-- this should fail (ideally in
// some graceful way)
};
var makeObj = function(pFunc) {
var window = {
"screenX": window.screenX
};
var document = null;
var rObj = {};
rObj.func = pFunc;
return rObj;
};
var obj = makeObj(func);
obj.func(); // <-- want it to have no access to document and
// limited access to window
func is defined by privileged users as a sort of plugin but I want to limit what they can do such as not creating new elements but still be able to access certain variables and functions they will need (such as window.screenX)
I'm sure that there are tons of possible answers, my answer make use of the Function-constructor so that window and document are defined locally within the scope of an also locally defined function. This is very important because you do not want to overwrite both objects globally.
But lets come to this answer. Within makeObj all allowed objects in func are defined with the first and second param of a new Function-Constructor.
The third param is used to create an "anonymous" function that contains certain assignments to those allowed objects. These assignments were created locally by using serializeFakeObject.
In other words, the first and second param with new Function are going to be the params (header or signature) while the third param is going to be the body of the „anonymous“ function.
Please note that this "anonymous" function is created dynamically and looks like this afterwards:
function anonymous(window,document) {
// overwrites allowed objects
window = {"screenX":-8};
document = {};
document.createElement = function (){ throw Error("document.createElement is not allowed"); };
// this function must take assignments above
// no chance to use the globally defined objects window or document
return function (){
console.log(window);
console.log(document.createElement());
}();
}
This anonymous function is dynamically created within makeObj and after that executed by calling obj.func() at the end.
Lets put all together:
var func = function (){
console.log(window); // has just got screenX
console.log(document.createElement()); // throws an error "document.createElement is not allowed"
};
var makeObj = function(pFunc) {
var serializeFakeObject = function(name,obj){
var serializedObject = "";
// when its a property of type function then omit JSON.stringify otherwise it gets undefined
if(obj.__proto__.constructor === Function)serializedObject = obj;
else serializedObject = JSON.stringify(obj);
return name + ' = ' + serializedObject + ';';
};
var fakeWindow = serializeFakeObject("window", { "screenX": window.screenX });
var fakeDocument = serializeFakeObject("document", {});
// create property createElement of document that should fail in a graceful way
var fakeDocumentProperty = serializeFakeObject("document.createElement", function (){ throw Error("document.createElement is not allowed"); });
// if you like you can add more properties here....
var concatFakeObjects = fakeWindow+fakeDocument+fakeDocumentProperty;
var rObj = {};
// the line below creates the "anonymous" function described above
rObj.func = new Function('window', 'document', concatFakeObjects +'return '+pFunc+'();');
return rObj;
};
var obj = makeObj(func);
console.log(obj.func());
If I create a callback within a function, can I get that callback to access the local variables within that function?
Obj.prototype.outerFunc = function()
{
var x = 0;
var callback = this.innerFunc;
callback();
}
Obj.prototype.innerFunc = function()
{
x++;
}
x naturally is not within the scope of innerFunc and will produce an error if called by itself. But if I call it from outerFunc can I extend innerFunc's scope in order to access x?
Edit: Should've mentioned that I don't want to pass arguments into the function or make x and instance of Obj. I'm more looking to treat innerFunc as though it was declared locally in outerFunc. Similar to what can be done below:
Obj.prototype.outerFunc = function()
{
var x = 0;
var callback = function() {
x++;
}
callback(); // works
}
Yes: this is exactly what function parameters are for. They allow you to pass a value from one scope into another.
Obj.prototype.outerFunc = function()
{
var x = 0;
var callback = this.innerFunc;
x = callback(x);
}
Obj.prototype.innerFunc = function(x)
{
x++;
return x;
}
Note that the value is sent to the other function, not the variable. So you need to return the value and assign it in order to use it.
If you're using prototypes, just set an instance property:
// constructor
var Obj = function () {}
Obj.prototype.outerFunc = function()
{
this.x = 0;
var callback = this.innerFunc.bind(this);
callback();
}
Obj.prototype.innerFunc = function()
{
this.x++;
}
var instance = new Obj()
instance.outerFunc()
console.log(instance.x) // returns 1
Edit: But #lonesomeday's answer is a much better solution as it takes a more functional approach avoiding side effects :)
The preffered way of doing this is to assign x to the scope of the object then all functions can access it, via this.x
Obj.prototype.outerFunc = function()
{
this.x= 0; // set x to zero
this.innerFunc();
}
Obj.prototype.innerFunc = function(x)
{
this.x++;
return this.x;
}
This is a bit hard to solve without knowing why you don't want to pass a parameter; if you just want to have a specific function signature, maybe a higher-order function might help?
Obj.prototype.outerFunc = function()
{
var x = 0;
var callback = this.innerFunc(x);
callback();
}
Obj.prototype.innerFunc = function(x)
{
return function () { /* use x in here */ };
}
This way you have two functions one inside the other. The outer one takes the parameter, and the inner one can access the variable that is passed to the outer one.
This of course only gives you half of what you demonstrate in your example: You can access the local variable but not modify it.
You can never access any function's internal variables from outside the function under any circumstances, in an OOP context or otherwise.
The only sort-of-exception is that a function A defined inside a function B, and returned from that function B, continues to have access to the variables in function B--the basic notion of closure.
I have no idea why you don't want to use instance variables. That's what they're for--sharing data across methods. I have no idea why you don't want to pass values in or out--that's what parameters and return values are for.
can I extend innerFunc's scope in order to access x?
No, you can't, whatever that means. There is no such notion in JS.
The closest you can come to what you seem to maybe want to do is to define the variable in the constructor:
function Obj() {
var x = 0;
this.outerFunc = function() {
var callback = this.innerFunc;
callback();
};
this.innerFunc = function() {
x++;
}
}
However, this will not work as-is because this.innerFunc is missing its context. Therefore, you would need to write
var callback = () => this.innerFunc();
However, it's a mystery why you would want to do this instead of just writing this.innerFunc().
I'm creating simple jquery library, actually I just learn about creating my own library with jQuery, I need to access variable inside lib function from outside main function. Here short code, I want to access variable page and loading from $.fn.beyondScroll.reset function. How I accomplish this task? I have tried to access via $.fn.beyondScroll.page; but it return undefinded. Thanks.
(function ($) {
$.fn.beyondScroll = function (options) {
var settings = $.extend({}, $.fn.beyondScroll.defaults, options);
var complete = false; // need access this variable
var page = 1;
return this.each(function () {
var loading = false; // and this variable
});
};
$.fn.beyondScroll.reset = function(){
// access those variables from here
var currentPage = $.fn.beyondScroll.page; // return undefined
}
}(jQuery));
This question already has answers here:
Understanding Node.js modules: multiple requires return the same object?
(7 answers)
Closed 7 years ago.
I have two files. I am creating the multiple object of one file into other.
module1.js
var a = 5;
var check1 = function(){
a = a + 10;
console.log(a);
}
exports.check = check1;
module2.js
var c = require('../module1');
var d = require('../module1');
c.check();
d.check();
The output is 15 & 25.
When you declare a variable using var, the scope is local. And i am creating two instances of module.js. So why is it getting declared at global level because the output is 15 & 25?
I need output as 15 & 15 as i want to use this variable as object level variable. What should i do?
Whenever you do a require, it returns a reference to the module that has already loaded into memory if there is any. Otherwise, it'll load the module first, then return the reference to it. More info in docs.
So, both your variables are actually pointing to the same object. You can verify this by requireing any modules.
var a = require('http');
var b = require('http');
console.log(a==b); // true
That is to prevent infinite loops while loading cyclic dependencies.
Depending on your module's code, you can do several things to solve the issue.
You can move the variable definition inside your function for example:
var check1 = function(){
var a = 5;
a = a + 10;
console.log(a);
}
exports.check = check1;
Or you can write a function that creates a new object each time you call it.
var create = function () {
var a = 5;
var check1 = function(){
a = a + 10;
console.log(a);
}
return {
check1: check1
}
}
exports.create = create;
And in your main file:
// or you can store require('./module1') to a single variable
var a = require('./module1').create();
var b = require('./module1').create();
a.check1();
b.check1();
NodeJS module system uses caching to return same instance for all references to the same module (Reference).
This results in your code having the same object instance in c & d.
If you want to have 2 separate instances, try like this:
module1.js
function Check() {
var a = 5;
return {
check: function() {
a = a + 10;
console.log(a);
}
};
}
exports.Check = Check;
module2.js
var Check = require('../module1').Check;
var c = Check();
var d = Check();
c.check();
d.check();
I'm developing a web framework for node.js. here is the code;
function Router(request, response) {
this.routes = {};
var parse = require('url').parse;
var path = parse(request.url).pathname,
reqRoutes = this.routes[request.method],
reqRoutesLen = reqRoutes.length;
..... // more code
};
Should I change all the var to this, like so:
function Router(request, response) {
this.routes = {};
this.parse = require('url').parse;
this.path = this.parse(request.url).pathname;
this.reqRoutes = this.routes[request.method];
this.reqRoutesLen = this.reqRoutes.length;
..... // more code
};
Any comments?
Add properties to this when you want the properties to persist with the life of the object in question. Use var for local variables.
edit — as Bergi notes in a comment, variables declared with var don't necessarily vanish upon return from a function invocation. They are, and remain, directly accessible only to code in the scope in which they were declared, and in lexically nested scopes.
It on depends what you want to do.
If you declare the variables with var, then they are local to the function and cannot be accessed outside.
If you assign the variables to this, then they will be set as properties of the context object the function is called on.
So if e.g. if you write:
var obj = new Router();
then obj will have all the variables as properties and you can changed them. If you call
somobject.Router()
then all the variables will be set as properties of someobject.
You can think of properties hung from this sort of like instance variables in other languages (sort of).
It looks like you're creating a constructor function and will likely add some prototype methods. If that's the case, and you need access to routes, you've got it, but not path.
Router.prototype = {
doSomething: function(){
this.routes; // available
path; // not available
}
}
Using var in the constructor is usually used for private variable while using this. is used for public variable.
Example with this. :
function Router() {
this.foo = "bar";
this.foobar = function () {
return this.foo;
}
}
var r = new Router();
r.foo // Accessible
Example with var :
function Router() {
var _foo = "bar";
this.foobar = function () {
return _foo;
}
}
var r = new Router();
r._foo // Not accessible