How to use only parenthesis without the function in javascript? - javascript

The question may not be clear, so I will clear that here. I am using require.js to import a script in script. Here is a piece of code :
var vr = {};
vr.example = function(func) {
return require(["https://example.com"], func);
};
So, now I am able to call it by :
vr.example( function() { .... });
But, I am thinking about not writing the function everytime I have to call it. I would like to write something like this :
vr.example({ ... });
And the result should be same. But I can't understand how to do it. So please help
Thanks in advance.

The thing you want can't be done in JavaScript ! But there is a way to do, by making an interpreter. Here is a basic example. I don't really recommend it, well I am showing you just a possibility ;)
window.InterpretData = function() {
var el = document.querySelectorAll("script[type='text/test']") // You can change it anyway !
for(var i = 0; i < el.length; ++i) { // You can use i++ instead of ++i, but ++i is much optimised for this function, watch out their differences in the internet.
var val = el[i].innerHTML
var crt = document.createElement("script")
crt.id = "InterpretedScript"
document.getElementsByTagName("body")[0].appendChild(crt) // Creating a new script element
val = val.replace(/\.example\(\{([\S\s]*?)\}\)/gm, function(_, a) { // Wish you are familiar with regular expressions
a = ".example( function() {" + a + "})"
document.getElementById("InterpretedScript").innerHTML += a;
}
}
}
Now you can do :
<!DOCTYPE html>
<body>
<script type="text/test">
// Defining
var vr = {};
vr.example = function(func) {
return require(["https://example.com"], func);
};
// Calling
var.example({ ... })
<script>
<script>
new InterpretData()
</script>
</body>
</html>
Output :
vr.example({ ... }) converts to vr.example( function() { ... })
Well, remember this example is just to give you an idea about a possibility to solve your problem. It's not the perfect solution though you can't again declare the "example()" to any other constant / variables, that contain different parameters ! So, the only way lies to either use ES6's fat arrows (=>) or just declare the function earlier and go on reusing it ! If you have to support old browsers than go with reusing technique shown by #mbojko, or just go with ES6's fat arrows, said earlier by #deceze. So, want do you think ?

So, you want to pass a block of code not wrapped with a function? Short answer: you can't do that in JavaScript. And require.js does expect a callback function at any rate.
If the callback function is reusable, you can declare it once and reuse it like:
function myReusableCallback(args) {
//...
}
vr.example(myReusableCallback);
And that's pretty much it.

Because the require() function returned from the vr.example() takes a callback function and since this callback function is usually provided by the invocation of vr.example, it, therefore, means you can't necessarily call it with and object as you want to. So you can only use an object if there is no callback expected by the require() an or if you have a static function that you want to be executed all the time then you can implement the function inside of the vr.example and then just pass the object which you need to use inside the function.

It's not possible because {} is not a function, it's an object.
You can try it out yourself using typeof({}) and compare it to typeof(() => {}) or typeof(function() {})

Related

Accessing var function within function in another file

I have 2 JS files - one with the functions I would like to access and the other that I'd like to call the function with.
(function($) {
var Place = function() {
var Location = function(id, duration, check) {
//Should access this function
}
}
})(jQuery);
I'm trying to access it with:
Place.Location(markerId, 600);
But all I'm getting is that it's not defined. Simple issue but can't quite figure this one out.
As it's a jQuery plugin, maybe there's a way I can access it via another method?
$.fn.place = function(params) {
var len = this.length;
return this.each(function(index) {
var me = $(this),
key = 'place' + (len > 1 ? '-' + ++index : ''),
instance = (new Place).init(me, params);
});
};
The way you are defining Location, it is a private variable inside the function Place. If you want to access it as an attribute of Place, you should replace var Location = ... with this.Location = ...
It's going out of scope. Because you wrapped your Place object in function($) {}, now anything outside that wrapper will no longer have access to variables inside the wrapper. If $ stands for jQuery, it should be a global anyways and you can take the wrapper out.
The solution is a combination of the other two answers.
You define Place as a variable in the (anonymous) function. It can't be used outside the scope of that function. (This function doesn't use jQuery, either, so the wrapper is unnecessary).
Place is a function. It executes code that sets local variable Location to a function, but doesn't export that function, so Location() is inaccessible outside the Place function.
You probably mean to make Place an object (instead of a function), and give it a Location method. Here's one way to write it:
var Place = {
Location: function(id, duration, check) {
// do something with id, duration, & check
}
};
// execute
Place.Location(someId, someDuration, someCheck);
(It doesn't look like you've posted all your code, like the Place.init() method, but there are plenty of ways to write this so that it works correctly; this should solve your immediate problem.)

JavaScript IIFE

I'll admit I'm pretty green when it comes to JavaScript and it doesn't help that every time I think I'm getting it some weird curve ball throws me right off.
I've got a js file something like this:
(function (myiife, $) {
var myArrayOfThings = [];
myiife.myFunction = function (id) {
var cachedThing = myiife.getFromArray(id);
if (cachedThing === null) {
// get from server
} else {
// do something with cached item
}
};
myiife.getFromArray = function (idToFind) {
for (var i = 0, len = myArrayOfThings; i < len; i++) {
if (myArrayOfThings[i].Id=== idToFind) {
return myArrayOfThings[i]; // Return as soon as the object is found
}
}
return null;
};
}(window.myiife= window.myiife|| {}, jQuery));
What really confuses me is the proper way to expect to be able to call things. I guess I really don't understand the scope of things yet and I'm struggling to be honest.
Is it expected that if I want to call myFunction from the page it would HAVE to look like this?
onclick="myiife.myFunction(1)"
I've read stuff on scope but I'm obviously still missing something very fundamental in my understanding of it all.
From the examples I've seen I don't see others that seem to have to prefix function names with the iife name in order to execute things from the page.
Any good recommended reading would be appreciated as well.
The global scope in Javascript (in a browser at least) is window. So what you've done is you've attached myiife to window and myiffe has a function called myFunction. So if you want to call it from the global scope (i.e. window) then, of course, you need to specify myiffe.myFunction().
What you may have seen other people do is something like this:
var myFunction = (function() {
var counter = 0;
return function() {
counter++;
console.log(counter);
};
})()
Where they have an IIFE return something (in this case a function, in many other case people will return an object). In this case, since myFunction is a global variable, they can call it with just myFunction(). What they have achieved with the IIFE is to basically make the counter variable private. Only things inside the IIFE have access to it.
Of course, if you don't define myFunction inside of an IIFE, then it will just be a function in the global scope and can be called directly from the global scope.
function myFunction() {
// do something
}
myFunction();
But to your question on using this in an event handler - better practice would be to not inline your event handler in your HTML in the first place and instead bind it in code. This gives you more flexibility, cleaner separation and more maintainable code.

How do I make a nonexistent (non-member, non-global) method invocable without using eval?

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.

How to conceal the functions

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

Node.js modules: correct way to refer to sibling functions

This is my current code:
var PermissionsChecker = {};
PermissionsChecker.check = function(id) {
PermissionsChecker.getPermissions(id);
}
PermissionsChecker.getPermissions = function(id) {
// do stuff
}
Two questions:
Is this the right way to construct node.js functions?
Is that line in .check the correct way to refer to a sibling function?
Thanks!
It's perfectly fine. Some notes:
Sibling function isn't really any standard term for methods of the same object. Minor note, but could cause confusion.
When a function is called as a method on some object, then the value of this inside that function refers to the object on which it was called. That is, calling check like this:
PermissionsChecker.check()
...allows you to write the function like this:
PermissionsChecker.check = function(id) {
this.getPermissions(id);
}
...which is more succinct and probably more common.
Nothing about your question is specific to node.js. This applies to JavaScript in the browser (or anywhere else), too.
You could save some typing by rewriting your example like this:
var PermissionsChecker = {
check: function(id) {
this.getPermissions(id);
},
getPermissions: function(id) {
// do stuff
}
};
So long as the function is called with PermissionsChecker.check(), you can refer to the object with this.
CodePad.
What you've done above is called an object literal, but you could choose the prototypal way also (when you need to instantiate objects - OOP stuff).
You can call this inside to refer to another object property:
PermissionsChecker.check = function(id) {
this.getPermissions(id);
}

Categories

Resources