Resharper not detecting global variables inside angular services - javascript

I want to detect places in my code, where globals are used, so I can do something about it.
I have a service like this:
myApp.service("myService", function () {
function f1() {
var a = global.someVar;
}
function f2() {
global.f();
}
function f3() {
global = "a";
}
});
Problem is, variable "global" in f1() isn't detected as global variable, in f2() it also isn't detected, but in f3() case I get "Assignment to implicitly declared global variable", while it should be detected in all 3 cases.
In Resharper JS Inspection sererity options, I have all turned on.
I tried to wrap my code in self invoking function, but still no success. Am I doing something wrong? Is there a way to make Resharper detect globals in theese situations?

Related

How to access a scoped function

I'm trying to find a way of accessing a scoped function - take this code for example:
(function() {
one();
console.log('IIFE END');
function scoped() {
console.log('scoped');
}
scoped();
})();
function one() {
console.log('one');
}
scoped(); // error
How can I access the call to the function to prevent the error? Using the return keyword fails
What you're doing is more or less saying "I locked the keys in the car. How do I access the keys." You can't. You locked them up in a way that makes them impossible to retrieve (well, unless you break the window, but you get my point). If you could simply open the door to get the keys there wouldn't be any point to locking the car.
That "scoped" function is the keys locked in the car.
What you want to do, is declare "scoped" outside of that anonymous function (before it, actually). Now, you can call it from within your anon function and outside of it.
You could either:
let scope;
...in anon function...
{
scope = { ...some function };
}
or
const scope = { some function }
... in anon function
scope();
Either way, outside of the anon function, you can now call "scope ()".
I guess I would add, that in JS, it's almost always possible to grab something that isn't intended to be grabbed. You could probably work with a top-level "this", or something, or just name your anon function (so essentially creating a named object that is of type function) and accessing the members of it by bracket notation. You would probably have to remove the immediate return though and call it in another line of code (after the function declaration).
But that's all hackery voodoo. You're breaking the window. In the day to day, what you say you want to do here is by design verboten.
Depending on how flexible you are, you can do this:
const scoped = (function() {
one();
console.log('IIFE END');
function scoped() {
console.log('scoped');
}
scoped();
return scoped;
})();
function one() {
console.log('one');
}
scoped(); // NO error :)
Or if your function's return is reserved for something else, just do this:
var scoped; // If you don't want this pre-declaration, you can just use a global scope instead (e.g. window.scoped)
(function() {
one();
console.log('IIFE END');
scoped = function() {
console.log('scoped');
}
scoped();
})();
function one() {
console.log('one');
}
scoped(); // NO error :)

How to call/use this module in other JS files/modules

I read some JS module design patterns recently. I came across this small code snippet as below.
(function(window) {
var Module = {
data: "I'm happy now!"
};
window.Module = Module;
})(window);
Still not quite understand this code well, my questions are:
How to use/call this module outside this particluar JS file? Need I
assign a variable to this module? e.g. var module1 = (...)(...);
Could anyone explain what the window parameter here stands for?
Is it a good practice to have two/three such kind of modules in the
same file?
The main reason to create an anonymous function in this case is to prevent global object pollution. It's not really a module pattern.
The problem arise when you declare a variable. Without the function scope, the variable will be added to the global object (window). If you were to declare the variables within a function. It would add the variable to the function scope without polluting the global object window.
What happen is that a javascript file could add a variable named foo and on a different file use that variable named foo too. Unless you really want to have a variable shared by two javascript files, it would probably create conflicts and bug that are difficult to fix.
For example: a.js
var foo = "one"
b.js
var foo = "two"
c.js
alert(foo)
In this case, the alert box might show either "one" or "two", depending of the order in the javascript files are included.
But having this a.js:
(function () {
var foo = "one"
})()
b.js
(function () {
var foo = "two"
})()
c.js
(function () {
alert(foo)
})()
This would create an error as you cannot alert a non declared variable.
One way to detect undefined variables, is to make sure to execute the javascript code in strict mode.
To do that, add the string "use strict" at the top of the file or function.
function () {
"use strict"
...
}
Undeclared variable will raise errors and it should be possible to fix the code that way.
Also, if you forget to declare a variable with the var keyword, it might end up adding the variable to the global scope even if the code is scoped into a function. The only way to prevent global scope pollution is to run the code in strict mode.
In the code snippet that you provided, the module with name Module is explicitly added to the window object. You can access the window object from any place in javascript unless the window name is ghosted by an other variable.
Now, back to the modules. If you want to define modules, it can be done in many ways. As an exemple, you could create an object on the window object called modules. In this object, you'll insert your modules.
module.js
window.modules = {}
foo.js
(function (window) {
var module = {}
...
window.modules.foo = module
})(window)
This variant isn't super good as you have to manually add the module to the modules object. You have to manually modify the window object, and that can be subject to errors.
modules.js
window.modules = {}
function define(name, constructor) {
var module = {exports: {}}
constructor(module)
window.modules[name] = module.exports
}
function require(name) {
return window.modules[name]
}
foo.js
define("foo", function (module) {
module.exports.one = function () {
return 1
}
module.exports.plus = function (a, b) {
return a + b
}
})
bar.js
define("bar", function (module) {
module.exports = function () {
var foo = require("foo")
return foo.plus(foo.one(), foo.one())
}
})
This is a module definition that looks a bit like module defined with http://requirejs.org/. It is quite basic as it doesn't take into account module dependencies so if bar is loaded and used before foo. Then the require method won't be able to return the module.
Also, if you want to store modules without having them visible into the global scope, you can only define the require and define method on the window object and hide modules into an anonymous scope like this:
(function (window) {
var modules = {}
function define(name, constructor) {
var module = {exports: {}}
constructor(module)
modules[name] = module.exports
}
function require(name) {
return modules[name]
}
window.define = define
window.require = require
})(window)
This way, define and require are the only function that can give you access to modules. Other modules won't be able to modify other modules without requiring them first. This can be useful when using third parties script that could conflict with your module system.
In fact this is not a module, but a Self-Invoking Ananymous function or an Immediate function which gets an object in parameter and assign a Module property to it:
The page window is a parameter passed to this function.
So an object named Module containing a data property is assigned to window.
JavaScript Self-Invoking Functions:
A self-invoking expression is invoked (started) automatically, without being called.
Function expressions will execute automatically if the expression is
followed by ().
You cannot self-invoke a function declaration.
You have to add parentheses around the function to indicate that it is
a function expression
So As you can see Immediate Functions can't be called as its name states it will be immediately executed and by its self, no other function or scope can execute it.
For better reference take a look at :
Javascript Self Invoking Functions.
Self-Invoking Functions section in JavaScript Function Definitions.
And concerning your last question about its benefits and good practices as shown on the given Article reference:
Where to use self-executing functions?
One obvious situation is when you want to auto-run a function like I
showed in above example but that is trivial. If you are in a situation
where you want to run a piece of code repeatedly like updating
something in the database based on user interaction or fetching
records from database every 10 seconds or you want to load new stories
via ajax similar to how facebook does on its homepage or some other
similar situation, one would normally go for setInterval function
something like this:
setInterval(doStuff, 10000);
Above, doStuff function will get called every 10 seconds. That is the
normal approach most developers seem to go with. However, there is a
huge problem with that.
The setInterval will call doStuff function exactly at specified time of 10 seconds again and again irrespective
of whether doStuff function actually finished doing what it is
supposed to do. That is bad and will certainly get you into unexpected
results.
That is one example of where setInterval is "bad" and should be
avoided.
This is exactly where self-executing functions come in handy. We can
do the same task with the help of self-executing function along with
setTimeout like this:
function foo(){
// your other code here
setTimeout(foo, 10000);
}();
This code will also repeat itself again and again with one difference.
setTimeout will never get triggered unless doStuff is finished. A much
better approach than using setInterval in this situation.
Calling it from another file:
And if this function is on another file it will be called automatically if this file is included.
Why do we use Self-Invoking Functions in JavaScript?
And if you ask yourself why do we use these functions, self-invoked function are used to manage Variable Scope.
Take a look at the answer here for further information.

Default binding of `this` is different from Chrome browser and Node.js

I was reading Chapter 2: this All Makes Sense Now! from You Don't Know JS, and decided to do this experiment.
I have this simple enough script foo.js:
var a = 'foo';
var output;
// lets find a way to output strings in both
// Chrome and Node.js
if (typeof alert === 'undefined') {
output = console.log;
} else {
output = alert;
}
function getA() {
return this.a;
}
var foo = getA();
output(foo);
I am expecting following things when getA() is called:
Since the call site of getA is in global scope, getA() will be bound to global object.
Since var a is declared in global scope, I take it that global object will have a property named a, and this property is same as the variable a.
Because of that, I expect this.a to refer to variable a.
Thus I expect output(foo) to print the string foo.
However, when run in Node.js (non-strict mode), this is the output:
$ node foo.js
undefined
Then I included the same script in a simple HTML page, and loaded it in chrome.
<html>
<head>
<script src="foo.js" type="text/javascript"></script>
</head>
<body>
</body>
</html>
Chrome alerts the string foo, just as expected.
Why does the output of Chrome differ from Node.js?
Since the call site of getA is in global scope, getA() will be bound to global object.
This is a misunderstanding of the this binding rules from my book. The call site's location (aka "in global scope") is entirely irrelevant. It's the manner in which the call is made, and only that.
It's not where getA() happens that matters, but that getA() is a plain normal function call. THAT is what determines that you'll get the global object bound to the this for that call.
The other answers here are correct... the scope your node main program runs in is actually a module (function wrapped), not a real global scope.
Since the call site of getA is in global scope, getA() will be bound to global object.
no, that's not true for node - your script is wrapped into a function here so your example is actually this code:
(function (exports, require, module, __filename, __dirname) {
var a = 'foo';
var output;
// lets find a way to output strings in both
// Chrome and Node.js
if (typeof alert === 'undefined') {
output = console.log;
} else {
output = alert;
}
function getA() {
return this.a;
}
var foo = getA();
output(foo);
})(exports, require, module, 'file.js', '/dir/name');
NodeJS behaves differently than browsers. The top-level scope is not the global scope, it's the scope within that file or module. Drop the "var" and your code will work (a will become truly global) in a node environment and it will console.log the string 'foo'.
See the following page for a full reference: http://nodejs.org/api/globals.html
OR
How to use global variable in node.js?

How to access javascript function in the eval() scope

I use eval() to execute javascript that is returned by an ajax request from the server. However, I cant call a function that was created with eval() and got a ReferenceError: function is not defined.
Is it something normal that functions inside a javascript that was executed with eval() cannot be accessed? Is there a way to access such functions?
I think this simple jsFiddle illustrate the problem: http://jsfiddle.net/M2GLs/
The created function isn't in the correct scope. So your onclick can't 'see' it. Use
window.addFeatureToTable = function() {
// definition
}
to force it in the window-scope.
Working JsFiddle
To answer your question in the comment:
What you actualy have is something like this code:
function a()
{
function b(where) {
alert('b can be called inside a, but not outside, we are now ' + where);
}
b('inside');
}
a();
b('outside');
b is defined in the scope of a, and can only be accessed within this scope (demo). In your case the function-definition is within an eval, but the same rule aplies there. In that case within the scope of function(r). You can't access the scope of this function from within the a.onclick, so you have to change the function-definition. Alternatively you can bind the on-click just after the eval (jsFiddle), since it is then still in scope:
js = "function someFunction() { alert('function called') }"
eval(js)
document.getElementById('myA').onclick = someFunction;

JavaScript: declaring and defining a function separately?

If I want to give a JavaScript variable global scope I can easily do this:
var myVar;
function functionA() {
myVar = something;
}
Is there a similarly simple and clean way -- without creating an object -- to separate the "declaring" and the "defining" of a nested function? Something like:
function functionB; // declared with global scope
function functionA() {
functionB() { // nested, would have local scope if declared here
CODE;
}
}
I should clarify that I'm referring to the scope of the function name itself -- so that if it is in an iframe it can be called from a script in the parent document. (Nothing to do with scope of variables inside nested functions.)
You can create global variables and functions by creating instances on the window object:
function _A()
{
// scoped function
function localFunctionInTheScopeOf_A()
{
}
// global function
window.globalFunctionOutsideTheScopeOf_A = function ()
{
};
}
In your case, though, all you need to do is this:
var myFn; // global scope function declaration
function randomFn()
{
myFn = function () // global scope function definition
{
};
}
Note: It is never a good idea to clog up the global scope. If you can; I'd recommend that you re-think how your code works, and try to encapsulate your code.
Perhaps I'm misunderstanding the question, but it sounds like you want something like this:
var innerFunc;
function outerFunc() {
var foo = "bar";
innerFunc = function() {
alert(foo);
};
}
You cannot globalize variables/functions cross windows/iframes that way. Each window/iframe has it's own global scope and to target variables/functions in another window/iframe, you need explicit accessor code and conform to the same origin policy. Only variables/functions inside the windows/iframes global scope are accessible.
code in top window.
var iframe = document.getElementById('iframeId');
var iframeContext = iframe.contentWindow || iframe;
// this will only work if your iframe has completed loading
iframeContext.yourFunction();
You could also possibly define functions/variables in the top window instead and simply work in one scope by binding the stuff you need from the iframe through a closure. Again, assuming you meet the same origin policy. This will not work cross domain.
code in iframe.
var doc = document;
var context = this;
top.myFunction = function(){
// do stuff with doc and context.
}
It is also important to note, that you need to check if your iframe content and it's scripts are fully loaded. Your top page/window will inadvertidly be done and running before your iframe content is done, ergo variables/functions might not be declared yet.
As for exposing a private function, others have awnsered this, but copy/pasting for completeness.
var fnB;
var fnA = function(){
var msg = "hello nurse!";
fnB = function(){
alert(msg);
}
}
I have the habbit of declaring stand alone functions as variables (function expression) and only use function statements to signify constructors/pseudo-classes. It also avoids a few possible embarrasing mistakes.. In any case, fnB resides in the global scope of the iframe and is available to the top window.
Why exactly you want this beats me, seems it makes matters more complicated to debug or update a few months later.
You can kind of do what you want.
You can create a function that acts like a namespace for properties and methods, and then you could essentially call either...
functionB();
or
functionA.functionB();
There is an article on how to do it here:
http://www.stevefenton.co.uk/Content/Blog/Date/201002/Blog/JavaScript-Name-Spacing/
In response to the update...
Is the iframe on the same domain as the parent site? You can't call JavaScript across the domain boundary, which may explain the problem.

Categories