Javascript detect when a property is re-declared with var keyword - javascript

Is there any way in Javascript of knowing when a property already defined gets re-declared as a variable, resulting in name collision? For example:
self.test = function() {
return "this is a test";
};
var test = "another test";
console.log(test());
This code results in Uncaught TypeError: test is not a function.
I want to somehow detect this before the error happens.
I tried using Object.defineProperty to include a getter and setter and fire a callback when the property gets changed, but that only works if the variable is assigned, not when it is redeclared with var keyword.
As a last resource, I think using a regex parser in the JS code to detect these situations could work, but that doesn't seem like a good solution at all.
Any suggestions?

Generally speaking, to catch errors like this and many others, you should use a linter. I use eslint.
For the problem of redeclaring variables specifically, see the const keyword if you're targeting modern browsers or want to use a transpiler.

If you're targeting ES6, use let or const instead of var.
Re-declaring a let/const variable inside the same scope will give you an error. If declared in a different block, it will refer to a different variable.

This is not exactly about detecting if property is redeclared. You can prevent property to be redeclared if this works for you in this case. You can use Object.defineProperty for that
var self = {};
Object.defineProperty(self, "test", {
configurable: false,
writable: false,
value: function() {
return "this is a test";
}
});

Related

Why to declare variable in the class, even assigning that variable to this in the constructor

In the code below, as you can see I declared a variable constObj in the Test class. And at the same time assigning constObj object to this in the constructor.
Why do we need to declare the variable again, even though we already assigning it to this in the constructor?
In the webstorm IDE, it is throwing error doesn't have the property constObj, if I do this.constObj, if the variable is not declared. But the code is working fine without issues.
Is declaring the variable mandatory, even if we are assigning that to this
const constObj = {
a: function() {
console.log("sivakumar");
}
};
class Test {
constObj: any; // Is this line mandatory? I mean declaring it???
constructor() {
Object.assign(this, {
constObj
});
}
callMethod() {
this.constObj.a();
}
}
new Test().callMethod();
Please let know, what will happen, if we don't declare.
Is declaring the variable is mandatory...
It's not a variable, it's a property.
The answer for TypeScript: Yes, it's mandatory, so that TypeScript knows that Test has that property for the purposes of doing its static type checks. (Note that the way you've done it is just one of the possible ways of declaring that property. But you do need to declare it.)
The answer for JavaScript: No, it's not mandatory¹, because JavaScript doesn't do static type checks.
¹ (and it's not possible per the current specification, but it soon will be and is commonly transpiled with tools like Babel)

In jQuery closure, how to get window property descriptor?

I want to see window property ‘otherName’ descriptor into jQuery closure. But
into jQuery closures 'otherName' descriptor is showing undefined, I think may
be getOwnPropertyDescriptor() did not get window object. Am i right? If I use
this code in plain js—
var otherName = "ckMe";
var result = Object.getOwnPropertyDescriptor(window, "otherName");
console.log(result);
// Object { value: "ckMe", writable: true, enumerable: true, configurable:
//false }
This is fine. But when this code in jQuery, I have got result = undefined.
(function ($) {
$(window).on("load", function (event) {
var otherName = "ckMe";
var result = Object.getOwnPropertyDescriptor(window, "otherName");
console.log(result);//undefined
});
}(jQuery));
Or if I use this code same result, undefined.
(function ($) {
$(function () {
var otherName = "ckMe";
var result = Object.getOwnPropertyDescriptor(window, "otherName");
console.log(result);//undefined
});
}(jQuery));
I want to use this code in jQuery closure because my all codes in there. I
was already searched this problem on google, but did not get any best
solution. Please help me. Thanks to all.
And sorry If I have anything wrong.
In your second two code blocks, otherName isn't a property of window. window only gets properties for var declarations at global scope. In your second two code blocks, the var declaration isn't at global scope, so otherName isn't a property of anything¹, it's just a local variable. They don't have property descriptors, because they aren't properties.
¹ "isn't a property of anything" - in specification terms, local variables are bindings on a Lexical Environment object. Bindings are a bit like properties, but they aren't properties (in the sense of JavaScript's object properties), and they don't have property descriptors (nor can you access the Lexical Environment object directly anyway — in fact, it may well not literally exist in any particular JavaScript engine).

How to distinguish between a variable that is not declared and a varrable that is declared but not be assigned any value?

Both scenario, the typeof the variable will be "undefined".
But undeclared variable will raise a exception.
Is there a easy way to handle this?
You may find the question (and my answer) in How to check if a variable or object is undefined? relevant. In general, I view any access to an "undeclared variable" a programming error.
However, this particular case can *only** be detected with the use of detecting for a ReferenceError exception. But, yuck, yuck, yuck! Remember variable declarations are a static lexical construct, ignoring the quirks with property-variables of the global object.
ReferenceError, and now "strict", exist for a reason and I suspect this is an X-Y problem. I do not even recommend the use of typeof for this purpose: fix the code :-)
Happy coding.
*It has been pointed out that "variable" in window will also [and only] work for global "variables" (they are really just properties that don't need be qualified in all contexts).
if property we want to check in object whether that it exists or not, even if its undefined.
we will use one of these:
'prop' in obj(to check for properties from prototype chain) or
obj.hasOwnProperty('prop')
we need to use methods above to check if property exists as accessing property that has not been declared in object will also return undefined.
var o={};
o.c=undefined;
o.c===undefined; //is true
o.a===undefined; //is true as well even though c exists while a doesn't
commonly not a problem as nobody really declare undefined properties much, but when do so do it like this.
o.c=''; //when it can be string or
o.c=null; //to clearly indicate that its nothing.
then
o.c === undefined will return false!
note!!!
null == undefined //true while
null === undefined //false that's why use three equals to test
For variables not declared and are not inside object. When accessed The compiler will return (reference)error.
If it doesn't it means its being treated as a global property, window object property, and was not declared, at least in all parent scope, so it will be undefined just as o.a was at top. it will become window.prop.
so x; //error
but x=3; //no error assumed to be global object.
just like o.abcd = 3; would...
make(declare) a property abcd in object o valued(assigned) 3 all at once.
To avoid properties to become a global variable we use var keyword inside function, like this var k;
One thing you can do about this catch the reference error when throw for a variable that doesn't exist and are thought to be a variable itself.
try {
x
} catch(e){//code to run when x is not declared let alone defined.}
You can try:
var a;
try {
a;
alert('a');
} catch(e) { /* a not defined */ }
try {
b;
alert('b');
} catch(e) { /* b not defined */ }
alert('done');
DEMO
You should never be attempting to access undeclared vars if you're writing clean JS. To avoid such pitfalls (among many others) start LINTing your JS with http://www.jslint.com/ or http://jshint.com/ .
A good read to help you understand the LINT tools and reasoning behind their findings is Crockford's Book, JavaScript: The Good Parts ( http://www.amazon.com/gp/aw/d/0596517742 ).

How can I set a Global Variable from within a function

How can I set a Global Variable from within a function?
$(document).ready(function() {
var option = '';
$("[name=select_option_selected]").change(function() {
var option = $(this).val();
alert(option); // Example: Foo
});
alert(option); // Need it to alert Foo from the above change function
});
Declare it outside the scope of your jQuery onready
var option = '';
$(document).ready(function() {
$("[name=select_option_selected]").change(function() {
option = $(this).val();
alert(option); // Example: Foo
});
alert(option); //This will never be "Foo" since option isn't set until that select list changes
});
if you want to initialize this to the current selected value try this:
var option = "";
var $select_option_selected = null;
$(function() {
$select_option_selected = $("[name='select_option_selected']")
$select_option_selected.change(function() {
option = $(this).val();
});
option = $select_option_selected.val();
});
The Bad Way
As the other answers point out, it's not a good idea to create global variables. And as they point out, you can create a global variable by:
Declaring variable outside of all functions
Initializing your variable without the var keyword
Or, declaring it as a property of the window object: window.options = 'blah';
Using jQuery's Data() Method
But there is a better way of creating a globally accessible value using jQuery (and other libraries). In jQuery, use the data() method to store values associated with DOM elements:
// store 'blah' at document root
$(document).data('mysite.option', 'blah');
// retrieve value
alert($(document).data('mysite.option'));
Notice "mysite"... it is a good idea to namespace your data keys for the same reason it is good to namespace global variables in javascript.
$(document).ready(function() {
var option = '';
$("[name=select_option_selected]").change(function() {
option = $(this).val(); //no declaration of new variable, JavaScript goes to what encloses the function
alert(option); // Example: Foo
});
alert(option); // Need it to alert Foo from the above change function
});
Are you sure you want to? global variables are generally to be avoided. In the browser, window is the global object, so if you do window.option = ..., then option will be available globally.
I highly recommend naming a global variable something more unique than "option", to avoid clobbering existing stuff.
Another option, which I also don't recommend: leave off var
myvariable = 'foo';
If myvariable has never been delcared before, it will be declared as a property on window, making it global. This is generally considered to be (very) bad practice however.
You can use the window. prefix to access a global variable from within the scope of a function
window.option = ...;
Two approaches not mentioned by anybody else, applicable when you: 1. don't have access to the global LexicalEnvironment,10.2.3 and 2. are trying to write code that you wish to support systems wherein a direct reference to the global object15.1 (such as window in the HTML DOM, or GLOBAL in Node[1]) isn't guaranteed:
Make an indirect15.1.2.1.1 call to eval, by wrapping it in a superfluous PrimaryExpression, thus: (1,eval)(...) (the digit and comma operator are meaningless) … and then calling the result thereof. This forces the code to be run in the global execution context.10.4.2
We can then declare10.5 a new variable in the global lexical environment, as suggested above; or, for that matter, do anything else that we desire within that environment:
function global_define(ident, value){
(1,eval) ("var "+ident+"; (function(v){ "+ident+" = v })") (value) }
To be less round-about (and, to boot, avoid the FUD-ridden eval call), we can directly access the global object and set a property4.2 on it, which will then be available as a global variable elsewhere in our code.[2]
Instead of taking the eval approach above and gaining access to the global object via code we've written in the global context, it turns out we can access the global object as the this value10.4.3 within any function that is called with null:
var global = (function(){ return this }).call(null)
global[ident] = value
Phew.
Okay, more reading, for those of you who haven't fainted from specification links and eval calls, yet:
#kangax covers all of the bases quite thoroughly. Seriously, read that if you have any questions I haven't answered here (including those relating to the all-important idiosyncrasies browser support!)
Obviously, the relevant sections of the ECMAScript 5 specification itself, to get an idea for how things are intended to work in an ideal world. No, really though; I know that specifications are a scary idea, but the ES (“JavaScript”) specifications are one of the easiest-to-read and most comprehensible specs I've ever seen. They're truly excellent. Of immediate note, and in no particular order,
10.4, Establishing an Execution Context: Covers how ‘global code’ and ‘eval code’ are handled, specifically.
10.2, Lexical Environments: These describe “where variables are stored.” (The ‘Global Environment’ of interest is one of these.)
10.1, Types of Executable Code: Covers what ‘global code’ and ‘Program’s are.
15.1, The Global Object: Unfortunately, far less relevant than its title makes it sound. Still worth a skim.
[1]: The discussion in other answers, suggesting that exports in Node.js and other CommonJS-compliant systems is somehow related to the global object, about which this question asks, is misleading. In terms of system-design, one might be better suited to using their environment's module tools than poking around on the global object … but that's a discussion for another Stack Overflow post. (=
[2]: For those of you following along in the spec, it's harder to demonstrate that property-members of the global object are accessible as Identifier dereferences. Start with 10.2.1.2 Object Environment Records and 10.2.3 The Global Environment to understand how the global object is linked to an environment, then hop on over to 18.12.3, 18.12.2, and 18.12.1 in that order, collectively describing [[Get]] on the global object.
Nota bene: At no point in this elaboration did I suggest that doing either of these things was a good idea. Or, for that matter, that interacting with the global scope at all is a good idea. Of no relation to the question at hand, but proffered to soothe my own conscience, I add that I wrap all of my own code in a IIFE beginning immediately at the top of the file; this, along with religious application of the var keyword, ensures that I never interact with JavaScript's handling of the global object at all. A huge mess, avoided. You should do that. I said so. I'm smart. (;
just declare a global object
var obj={};
function my_function()
{
obj['newVariable'] = 'someValue';
}
in this way i achieved global variable.
http://jsfiddle.net/Kba5u/
var foo = 'bar';
function changeFooToBaz(){
foo = 'baz';
}
// changeFooToBaz();
console.log(foo); #=> 'bar'
Now, uncomment the call to changeFooToBaz:
var foo = 'bar';
function changeFooToBaz(){
foo = 'baz';
}
changeFooToBaz();
console.log(foo); #=> 'baz'
changeFooToBaz has indeed changed the contents of foo, a variable that was declared at a higher scope than the function.

Javascript function change variables scope

I am attempting to declare a function outside of anonymous function but still have acess to all of the anonymous functions variables
Below is demonstrating what I'm talking about.
I just need to get rid of eval.
//Used to determine where the variable is being stored
var variableScope = "global";
(function(window){
var variableScope = 'insideFunction',
appearingToBeGlobalFunction = function(){
alert("This Function appears Global but really isn't");
};
window["addFunction"]=function(funName,fun){
//window[funName] = fun; Doesn't work
eval("window[funName]="+fun+";");
}
})(window);
addFunction("alertTest",function(){
alert(variableScope);
appearingToBeGlobalFunction();
});
//should alert "insideFunction" and "This Function appears Global but really isn't"
alertTest();
Edit: The goal of this question was to ultimately keep the global scope clean from tons of variables, but still have the convenience of accessing, set and calling as if they were global. I have concluded there is a way to doing what I'm after but it requires a deprecated functionality in javascript.
Here is some example code showing how to accomplish the above without eval.
This article discusses how to use "with".
var variableScope = "global";
var customScope = {
variableScope : 'insideFunction',
appearingToBeGlobalFunction : function(){
alert("This Function appears Global but really isn't");
}
};
function alertTest(){
with(customScope){
alert(variableScope);
appearingToBeGlobalFunction();
}
};
//should alert "insideFunction" and "This Function appears Global but really isn't"
alertTest();​
You can't get rid of eval and still expect it to work. That's the only way to take a look at members of the scope after it's been "closed." I've messed around with something similar in the past, but I would never actually use it anywhere. Consider an alternate solution to whatever you're trying to accomplish.
eval("window[funName]="+fun+";");
Oh dear Lord.
The reason this “works” is that you are converting the function fun (alertTest) into a string to put it in the eval argument.
It happens that in most desktop browsers, a native JS function's toString() result will be a string that looks like a function expression containing the same code as the original declaration. You're turning a function back into a string and re-parsing that string in the context of the new enclosing function, so the new function value is the same code but with a different closure.
However, it is not required that Function#toString work like this, and in some cases it won't. It is not safe to rely on function decomposition; avoid.
You can certainly only do this kind of horrific hackery using eval, although there is no reason the window[funName]= part has to be inside the eval. window[funName]= eval('('+fun+')'); would work equally well (badly).
I am attempting to declare a function outside of anonymous function but still have acess to all of the anonymous functions variables
Whyever would you do something crazy like that?
you could force the variables to be in the global scope eg instead of var variableScope = 'insideFunction' you use window.variableScope = 'insideFunction'
The goal of this question was to ultimately keep the global scope clean from tons of variables, but still have the convenience of accessing, set and calling as if they were global. I have concluded there is a way to doing what I'm after but it requires a deprecated functionality in javascript.
Here is some example code showing how to accomplish the above without eval.
This article discusses how to use "with".
var variableScope = "global";
var customScope = {
variableScope : 'insideFunction',
appearingToBeGlobalFunction : function(){
alert("This Function appears Global but really isn't");
}
};
function alertTest(){
with(customScope){
alert(variableScope);
appearingToBeGlobalFunction();
}
};
//should alert "insideFunction" and "This Function appears Global but really isn't"
alertTest();​

Categories

Resources