Hi,
I have my main file in which I include my javascript file.
In my javascript file I have this
$(document).ready(function(){
//some functions here
});
I want all the functions just available to this page and I know you can kinda conceal them to outside world of javascript by doing something like
(function(){
$document.ready(function(){
//my functions
)};
}).init();
but I am not 100% sure how would it be called or whether its even the right way.
Anyone shedding light on this would be a great help!
In javascript everything declared inside a function is only available inside that function (except for when you declare a variable without the keyword var).
So everything inside the function that you pass to $().ready() is only available inside that function.
$(document).ready(function () {
//all code here is scoped inside this function, so it can't be accessed
// outside of this function
});
Like the first comment says you can't hide them from the user, if they really want to see it, they will see it.
You can clean them up in a way if you really wanted to, something like
var mySpace = {};
mySpace.init = function() {
// your init functions here
};
in doc ready you just call
mySpace.init();
I am not sure if this is what you wanted but it is the way I understood the question
(function(){
var secret1 = function(msg) {console.log("Secret Message:" + msg);}
$document.ready(function(){
secret1("this can only be called from within");
)};
})();
secret1("this will cause a script error");
It sounds like the thing you are looking for is a 'javascript obfuscator'. Here is an example one. It makes the code much harder to read and copy. But as others have said, you can't actually fully hide javascript.
The problem here is that JavaScript is intrinsically a client-side scripting language unless using a server-side javascript application such as node.js.
As long as JavaScript is being used in this way, the entirety of your code will be downloaded much like downloading a .txt file from a website. The only real difference is that the ".js" extension and its inclusion in html <script> tags or in an AJAX call will force the user's browser to render it as JavaScript.
If you want to make the script a little harder for the user to find, however, this is doable. I recommend having your website retrieve the script via AJAX and appending it to the DOM. You can do this with require.js or by using Kickstrap and making your script into an "app." The script won't appear as a link in the DOM and the user would really have to search for it. You can make it even more difficult (without compromising the integrity of your site) by minifying the script. This will make it run faster while inadvertently making it less human-readable on the front end.
In JavaScript there is only function scope (the exception argument in try-catch being an exception). ES5 will let you use let (no pun intended) to achieve block scope but it wont be usefull untill majority of UAs implement it.
So your functions are concealed from the outside world, if with outside you mean outside the dom ready event.
$( document ).ready( function () {
var myFunc = function () {};
} );
myFunc();// <- ReferenceError: myFunc is not defined
You can't really hide the functions, as it's in the source code of a file downloaded by the client, but you can make it so they can't access your functions from javascript.
(function() {
var doStuff = function() {
// Not Accessible
console.log('You can\'t reach me!');
}
return {
'init': function() {
// Accessible
doStuff();
}
}
})().init();
If you are talking about Access Modifiers like public, private etc. Then check out this article on how Javascript handles this. Here are the key components:
//constructor function (class)
function Maths(x, y) {
//public properties
this.x =x;
this.y = y;
//public methods
this.add = function () { _sum = x + y; return _sum; }
this.mod = function () { _mod = x % y; return _mod; }
//public method calls private method
this.show = function () {
this.add();
this.mod();
showResult();
}
//private variables
var _sum=0;
var _mod=0;
//private methods
function showResult() {
alert( "sum: " + _sum + ", mod: " + _mod );
}
}
//end function
//create instance
var plus = new Maths(3, 4);
plus.show();
//static method multiply, you can use it without instance of Maths
Maths.multiply = function (x,y) { return x * y; }
//call static method by constructor function (class) without instance of Maths
var result = Maths.multiply(5,7);
alert(result);
//output: 35
Related
Im building a webapp where i load the main page with its own javascript file in the index.html then the nav is calling all other pages in a div without a browser refresh using $.ajax and attaching specific script for each page in the div too with $.getScript.
Sometimes i needs to access a method declared in the main page javascript from within the div loaded javascript so what i generally do is attach the main method to document, exemple, instead of just:
let doThis = function(num){
// do your stuff
}
i do this
document.doThis = function(num){
// do your stuff
}
This way i can easily access it from any other javascript file loaded at different levels.
Thing is i feel its not a good practice, what would then be the good practice? or is it acceptable one?
If you are not using any bundler,then 'Revealing Module Pattern' can be used as a good practice here. This will allow the syntax to be more consistent and in this case, will make it easier to tell which of the functions can be accessed globally.
window.mainPageModule = (function () {
var privateVar = "abcd",
function privateFunction() {
//Do some private stuff here
}
function publicSetValue(value) {
privateVar = value;
}
function publicGetValue() {
return privateVar;
}
// Reveal desired functions to public
return {
doThis: publicSetValue,
getThis: publicGetValue
};
})();
Then, to access the public function anywhere globally
mainPageModule.doThis("1234")
Are there any (non-trivial/ugly hack) ways to call a 'private' method from outside a class/module itself?
Please don't ask why I need this.
Just my personal curiosity and trust in power of doing anything in JS :)
function Module () {
var privateMethod = function () {
alert('1');
};
var publicMethod = function () {
privateMethod();
alert(2);
};
return {
pm: publicMethod
};
}
var m = new Module();
m.pm(); // can i call m.privateMethod() here somehow?
DON'T TRY THIS AT HOME
So you've been warned, now look at this (fiddle; I've replaced all the alerts with console.log() for the greater good):
var methodName = 'privateMethod';
var mSource = Module.toString();
var methodPattern = new RegExp(methodName + '\\s*=\\s*function[^]*?\\{([^]+?)\\};');
var privateMethodSource = mSource.match(methodPattern);
var privateMethodRebuilt = new Function([], privateMethodSource[1]);
privateMethodRebuilt();
It's one possible way to do this with HUGE number of restrictions. First, this particular snippet doesn't even try to parse the arguments, assuming that the method in question doesn't need any. Second, you won't be able to access the other private variables defined within the Module (as the code rebuilds only the particular function, not the environment).
Surely, you can take it further - and rebuild the Module itself, making the target method public (for example, by adding the private function into the exposed methods' list). The question is, WHY on Earth do you even think about needing such thing as using the private method outside the module?
I have tried searching through a lot of S.O. pages but nothing has touched EXACTLY on this top while also NOT USING JQUERY.... I am trying to stick to pure JavaScript as I want to learn it 115% before advancing my current knowledge of JQuery.
I have an object called ScreenResizeTool like this...
function ScreenResizeTool(currImg) {
window.addEventHandler('resize', function() {
listen(currImg);
}, true);
}
and a method like this...
ScreenResizeTool.prototype.listen = function(currImg) {
//Random Code For Resizing
};
My trouble is probably obvious to an experienced JavaScript user but I am having trouble not making this into a messy dirty awful OOP set. I have done various tests to show and prove to myself that the this inside the addEventHandler changes when it becomes bound to the window. This much I assumed before testing but I was able to see that once window.resize event happens the listen method is gone and not a part of the global window variable....
I have also tried adding a this capture such as this.me = this inside the object constructor however it also couldn't see the me variable once it ran. Once the window took the function over it no longer knew anything about the me variable or any reference to my class methods....
I am aware that I could separate this differently but my goal here is to learn how to fully encapsulate and use as many clean OOP structures as possible as I just came from the .NET world and I need it in my life.
I am also aware that I could make messy calls and or store this object or access to the methods inside the window variable but that seems outright wrong to me. I should be able to fully encapsulate this object and have its events and methods all implemented in this class structure.
I also know that the currImg variable is not going to be seen either but lets start small here. I assume once I figure out my incorrect train of thought on scope for JavaScript I should be fine to figure out the currImg problem.
I know there's 1000 JavaScript programmers out there waiting to rip me a new one over asking this simple question but I gotta know...
Thoughts anyone?
this inside a function bound to a DOM Object (like window) will always refer to that object.
this inside a constructor function will always refer to the prototype.
A common practice to circumvent the this issue, as you mentioned, is to cache it in a variable, often called self. Now you want the variables and properties of your object available after instantiation, so what you need is the return keyword, more specifically to return the parent object itself. Let's put that together:
function ScreenResizeTool() {
var self = this;
// method to instantiate the code is often stored in init property
this.init = function() {
window.addEventListener('resize', function() {
self.listen(); // self will refer to the prototype, not the window!
}, true);
};
return this;
}
ScreenResizeTool.prototype.listen = function() { // Dummy function
var h = window.innerHeight, w = window.innerWidth;
console.log('Resized to ' + w + ' x ' + h + '!');
};
Pretty easy huh? So we have our prototype now, but prototypes can't do anything if there's not an instance. So we create an instance of ScreenResizeTool and instantiate it with its init method:
var tool = new ScreenResizeTool();
tool.init();
// every time you resize the window now, a result will be logged!
You could also simply store the listen & init methods as private functions inside your constructor, and return them in an anonymous object:
function ScreenResizeTool() {
var listen = function() { ... };
var init = function() { ... };
// in this.init you can now simply call listen() instead of this.listen()
return {
listen: listen,
init: init
}
}
Check out the fiddle and make sure to open your console. Note that in this case I'd rather use the first function than the second (it does exactly the same) because prototypes are only useful if you have multiple instances or subclasses
The whole concept of this in JavaScript is a nightmare for beginners and in my code I usually try to avoid it as it gets confusing fast and makes code unreadable (IMHO). Also, many people new to JavaScript but experienced in object-oriented programming languages try to get into the whole this and prototype stuff directly though the don't actually need to (google JS patterns like IIFE for example as alternatives).
So looking at your original code:
function ScreenResizeTool(currImg) {
window.addEventHandler('resize', function() {
listen(currImg); // global function listen?
}, true);
}
ScreenResizeTool.prototype.listen = function(currImg) {
//Random Code For Resizing
};
First off, you probably mean addEventListener instead. In its callback you refer to listen but as a global variable which would look for it as window.listen - which doesn't exit. So you could think to do this:
function ScreenResizeTool(currImg) {
window.addEventHandler('resize', function() {
this.listen(currImg); // what's this?
}, true);
}
As you want to use the prototype.listen function of ScreenResizeTool. But this won't work either as the event listener's callback function is called with a different this and not the this that is your function scope.
This is where something comes in which makes most programmers cringe, you have to cache this, examples from code I've seen:
var _this = this;
var that = this;
var _self = this;
Let's just use the latter to be able to refer to the function within the event callback:
function ScreenResizeTool(currImg) {
var _self = this;
window.addEventListener('resize', function() {
_self.listen();
}, true);
}
Now this will actually work and do what you want to achieve: invoke the prototype.listen function of ScreenResizeTool.
See this JSFiddle for a working example: http://jsfiddle.net/KNw6R/ (check the console for output)
As a last word, this problem did not have anything to do with using jQuery or not. It's a general problem of JS. And especially when having to deal with different browser implementations you should be using jQuery (or another such library) to make your own code clean and neat and not fiddle around with multiple if statements to find out what feature is supported in what way.
Let's start from the code:
function say(name) {
var ghost=function () {
function ghost() {
alert('!');
};
return body;
};
eval("var body=''+"+name+';');
eval(name+('=('+ghost).replace('body', body)+')();');
eval(name+'();');
}
function Baal() {
if ('undefined'===typeof ghost) {
say('Baal');
return;
}
ghost();
}
say('Baal'); // or just Baal();
Looks like that saying the devil's name invoke his presence (well, maybe he needs somebody for spiritual possession) ..
As you can see the ghost doesn't exist along with Baal, but we can invoke it since there're evals in say(name).
say(name) reassigns Baal to its code body as a closure and makes it captured a ghost method, that's how things work. But I'm trying to avoid eval ..
So .. let me reword the question:
How do I make a nonexistent(and not a member or global) method invocable without using eval?
Let me rephrase your question, just to make sure I’ve got it. Given a function, you want to put a new variable in its scope, without that scope being the global scope or a scope shared between the caller and the subject, without using eval (or the equivalent new Function and other hacks depending on the environment).
You can’t.
In the case you just mentioned, you could define one function, base(), that uses arguments.callee.caller.
Don’t do that.
The short answer: You don't.
That scope is not available. If you were to attach the scope then it would be available inside of the scope used. You could then access the method handles. I assume this is not what you were looking for, but here is what that would look like. demo
function say(name){
var methods = {};
methods.Baal = function(){
alert("!");
};
return methods[name];//this could invoke as well: methods[name]()
}
var handle = say('Baal');
handle();
What your evals break down to is something along these lines (although with dynamic content from string building - this is the end result)
function say(name) {
var Baal = (function () {
function ghost() {
alert('!');
};
return function(){
if ('undefined'===typeof ghost) {
say('Baal');
return;
}
ghost();
}
})();
Baal();
}
say('Baal'); // or just Baal();
Note that the meat of what happens here is from the function Baal, namely that it calls a hardcoded ghost() which in turn calls a hardcoded alert. Why go through all of this trouble to access a hardcoded function?
A better way would be to inject this function as a callback which expects some parameters to be injected.
jsFiddle Demo
function say(callback){
var params = "!";
if( typeof callback == "function" ){
callback(params);
}
}
say(function(params){
alert(params);
});
It's very difficult for me to read through your code and figure out what you are trying to accomplish with it, but it appears that you are trying to introduce a variable into the current scope so that you can call it. You cannot do this in javascript with the method that you demonstrated. Scoping only ever "flows down". By that I mean that a variable or function defined within a function will only be available to that function and any other functions defined therein. Your function named ghost will only ever be available within the function where it is defined, regardless of when that function is evaluated.
What you can do, however, is write a function that returns a function. You can then call that function and assign the result to a variable in the scope where you want to expose functionality. Doing that would look something like this.
function defineSpecialAlert() {
return function(name) {
alert(name + "!");
};
}
var newlyDefinedMethod = defineSpecialAlert();
newlyDefinedMethod("Baal");
So if I understand, it seems like you want to create an alias of eval: Something like
#Note this code is not intended as a solution, but demonstrates
#an attempt that is guaranteed to fail.
#
function myAlias(ctx) {
eval.call(ctx, 'var ghost = 42');
}
myAlias(this);
alert(ghost);
Javascript allows many funky sleight-of-hand tricks especially with closures, but this is maybe the one impossible thing that javascript cannot do. I've tried at length to do this exact same thing, and I can tell you that you'll run into nothing but complaints from the browser, saying that eval cannot be re-contexted or aliased in any way.
Im designing an API that requires my users to download a javascript file from my server and then load it on their pages. Inside this file there is a function call generic(), if my users include this js and for some reason they have a piece of js on their page where there is another function call generic() this will represent an issue. Im not a front end dev, I know that with php you can solve this creating a class and putting all your functions inside, so you can call them like $myclass->myfunction();, but how can i solve this on js? Is this even a good approach on js? (no jquery please.)
You will obviously always have to expose at least one identifier globally, but a common approach is to wrap everything in an immediately-invoked function expression:
var YourNamespace = (function () {
var privateData = 10; // Not accessible outside the IIFE
// Expose public properties (these functions can access the private data)
return {
someMethod: function () {
// Do stuff
},
anotherMethod: function () {
// More stuff
}
};
}());
This will expose a single identifier, YourNamespace, as an object with properties that can be used as methods. You can use it like this:
YourNamespace.someMethod();
Wrap your code inside a wrapper object/ or function.
var MyLibrary = {
global1: 123,
global2: 'abc',
doSomething: function(a){
// ...
},
somethingElse: function(b){}
};
If u are looking for Encapsulation in Javascript, then u are looking for Closures