How come a properly declared global variable can't be deleted?
I don't know if this is across all program languages, but I know that in JavaScript it can't be deleted.
Source: Javascript the Definitive Guide O'Reilly.
When you use global variables and you want to be able to delete them, you should easily define them in a global object, without using var in your statement, like:
let's say you want to define a global varible in your code, and you need to be able to delete them whenever you want, so if you do:
function myfunc(){
var name = "Robert";
console.log(delete name);
}
and call it in your console you would have, false as the result of delete statement, which means it has not got deleted, but if you do it like:
function myfunc(){
var obj = {};
obj.name = "Robert";
console.log(delete obj.name);
}
then your result would be true, which means it gets deleted now.
now for global object if you create it like:
window.myobj = {};
then you can delete it and it actually get deleted:
delete window.myobj;
or
delete window["myobj"];
The thing is when you create your variable using var, in the window context, although it is on object in the window, but it doesn't get deleted, for instance if you do:
var myobj = {};
in the browser dev console, it gets defined in the window, and you can have it like:
window.myobj
but you can not delete it, because you have defined it in a var statement.
But do not forget to set it to null, if you really want it to get deleted from memory:
window["myobj"] = null;
delete window["myobj"];
As was stated in this answer by user Eric Leschinski
Delete a variable in JavaScript:
Summary:
The reason you are having trouble deleting your variable in JavaScript
is because JavaScript won't let you. You can't delete anything created
by the var command unless we pull a rabbit out our bag of tricks.
The delete command is only for object's properties which were not
created with var.
JavaScript will let you delete a variable created with var under the
following conditions:
You are using a javascript interpreter or commandline.
You are using eval and you create and delete your var inside there.
or you can set null to an variable which will behave like a deleted object
When variable is created in global scope then automatically DontDelete property is added to the variable and set to the true. That is the reason global variables (or functions too) can not be deleted.
For other variables that property is false so those can be deleted.
For more clarity you can refer the article : understanding delete
With ECMAscript 5, the properties added to an object now have attributes which allow you more control over the object. These attributes are:
value - The actual value of the property
writable - If the property can/cannot be changed.
configurable - If set to false,any attempts to change its attributes will fail in strict mode (and will return false in non-strict mode)
enumerable - if the property can be iterated over when the user does for (var prop in obj) {}
These attributes can be checked with another API exposed by Ecmascript 5 called:
Object.getOwnPropertyDescriptor(obj, prop)
Now, when you create a global variable WITHOUT the 'var' keyword, like so:
sum = function (a, b) { return a + b; }
then this property 'sum' get created on the window object with configurable attribute set to true.
console.log(Object.getOwnPropertyDescriptor(window, "sum"))
... and therefore this property CAN be deleted from the window object.
delete window.sum //returns true
But when you create a property with the var keyword, then configurable property is set to false like so:
var multiply = function (a, b) { return a * b; }
console.log(Object.getOwnPropertyDescriptor(window, "multiply"))
... and now, this property CANNOT be deleted.
delete window.multiply //returns false in non-strict mode
Courtesy: John Resig
Related
I'm having issues understanding scoping/access of fields defined with a JavaScript object.
Consider the following sample JavaScript object definition:
function SampleObject(controlName) {
var _controlName = controlName;
this.Display1 = function() {
console.log(_controlName);
}
this.Display2 = function() {
Display3();
}
Display3 = function () {
console.log(_controlName);
}
}
Now consider running the above object with the following example:
var a = new SampleObject("Bob");
var b = new SampleObject("Fred");
a.Display1(); //==> Displays "Bob"
b.Display1(); //==> Displays "Fred"
a.Display2(); //==> Displays "Fred"
b.Display2(); //==> Displays "Fred"
What I'm having difficulty understanding is how to access object fields (properties) from within private functions defined within my object.
Within my example, I am confused as to why _controlName has the value "Fred" when it is displayed via Display2() for both objects a and b.
I suspect that is either an issue with how _controlName and/or Display3() is defined or I am unclear how scoping would work in this instance. Can someone please share some light on this?
Thanks,JohnB
In some other languages such as Java (where I hail from), when you are inside a method on an object, the this is implicit. In Javascript, this is NOT the case.
When you are assigning to this.Display1 and this.Display2, you are creating properties with those names on the object pointed at by this. Because of new, this is a different object each time.
However, what's happening when you assign to Display3 is that you are assigning to a global variable. If it doesn't exist, it is created for you. When you call new SampleObject("Fred"); the function which originally logged "Bob" is now gone, replaced by one which prints "Fred".
If you add 'use strict'; to the top of your SampleObject function, which suppresses this "implicit global" behavior, you get a reference error when you try to assign to the never-declared variable Display3.
Here's the explanation.
In the first call, new SampleObject("Bob"); the global variable Display3 gets set to a function that console-logs the value Bob.
In the second call, new SampleObject("Fred"); the global variable Display3 gets set to a function that console-logs the value Fred.
Now your Display1 is actually a method. Every object you create gets its own Display1 property. So Bob's Display1 logs Bob and Fred's logs Fred.
But because the Display2 methods each call the global Display3 method, they will all log what the function in the last assignment fo Display3 says to log, and that will always be Fred.
This is really tearing apart my JS concept. What's wrong at all here?
const NAME = 'chusss';
var name = 123;
console.log(typeof name); // string, wasnt it supposed to print number?
console.log(name); // 123
The name variable actually belongs to window.name which lets you set the name of the window.
From MDN
The name of the window is used primarily for setting targets for
hyperlinks and forms.
Further down it's written:
Don't set the value to something unstring since its get method will
call the toString method.
Thus you always get a string returned.
If you still want to use the name variable but dont want to have the collision with window.name, then wrap your code inside a immediate invoked function expression (IIFE) and benefit from the functional scope.
Demo
(function() {
var name = 123;
console.log(typeof name);
console.log(name);
})();
If you run this code in node.js you won't observe that behaviour as name is not a property of the global object and thus not defined in global scope.
If functions are objects, where does the function's body go?
Let me clarify what I am confused about. Functions are objects, okay. I can think of an object as a hash map consisting of string keys and arbitrarily typed values. I can do this:
function Square(size) {
Rectangle.call(this, size, size);
}
Square.prototype = new Rectangle();
I just treated Square like a regular object and messed with its prototype property by assigning a new value to it. However, if functions are just objects (or hash maps for that matter), where is the function's body (in this example Rectangle.call(this, size, size);) being stored?
I figured it must be stored as the value of some property, something like the following maybe:
console.log(Square.executableBody); // "Rectangle.call(this, size, size);"
Obviously, this is not the case. Interestingly, while reading "The Principles of Object-Oriented JavaScript" by Nicholas C. Zakas, I stumbled upon this:
[...] functions are actually objects in JavaScript. The defining characteristic of a function - what distinguishes it from any other object - is the presence of an internal property named [[Call]]. Internal properties are not accessible via code [...] The [[Call]] property is unique to functions and indicates that the object can be executed.
This might be the property I was looking for above. It does not go into detail, though. Is the function's body actually stored within the [[Call]] property? If so, how does execution work? Unfortunately I was unable to find out more about [[Call]], Google mostly came up with information on a function's call method...
Some clarification would be much appreciated! :)
It becomes the value of another internal property, called [[Code]]:
13.2 Creating Function Objects
Given an optional parameter list specified by FormalParameterList, a body specified by FunctionBody, a Lexical Environment specified by Scope, and a Boolean flag Strict, a Function object is constructed as follows:
[...]
Set the [[Code]] internal property of F to FunctionBody.
If so, how does execution work?
Calling a function basically calls the internal [[Call]] method, which is described in http://es5.github.io/#x13.2.1. I guess the important step is:
Let result be the result of evaluating the FunctionBody that is the value of F's [[Code]] internal property.
Basically, for all practical purposes you can consider the function in its entirety to be the object. You can study the JS spec or JS engine source code to learn about how the function body is actually stored in an internal property on the object, but this won't really help you understand how it works as a JS programmer. You can see the body as a string by evaluating fn.toString. You cannot otherwise access the body other than to execute it or bind to it or call other methods on Function.prototype. However, because it's an object, it can also have properties attached to it like any other object.
Why would I want to attach a property to a function? Here is an example of a memoization function (deliberately simplified):
function memoize(fn) {
var cache = {};
function memoized(x) {
return x in cache ? cache[x] : cache[x] = fn(x);
};
memoized.clear = function() { cache = {}; };
return memoized;
}
So we are placing a function clear as a property on the returned function. We can use this as:
memofied = memoize(really_long_calculation);
result = memofied(1); // calls really_long_calculation
result = memofied(1); // uses cached value
memofied.clear(); // clear cache
result = memofied(1); // calls really_long_calculation again
The function is enough of an object that Object.defineProperty can be called on it, allowing us to write the memoization function above as follows, if we really wanted to:
function memoize(fn) {
var cache = {};
return Object.defineProperty(function (x) {
return x in cache ? cache[x] : cache[x] = fn(x);
}, 'clear', {value: function() { cache = {}; } });
}
(since Object.defineProperty returns the object.) This has the advantage that clear takes on the default non-enumerable and non-writeable properties, which seems useful.
I could even use a function as the first (prototype) argument to Object.create:
someobj = Object.create(function() { }, { prop: { value: 1 } });
but there's no way to call the function serving as prototype. However, its properties will be available in the prototype chain of the created object.
I need to delete one object in my case. so i am using "delete" keyword but after using it, I am able get the value again
var test= {};
test[0]="111";
test[1]="555";
delete test;
alert(test[0])
You can't delete a local variable that has been declared with var.
You can only delete properties of objects - this happens to also include global variables which are implicit properties of the window object.
You can delete properties on objects, you can't delete variables.
Either assign undefined or let the variable fall out of scope.
As has been mentioned, you can't delete a variable that has been declared with var.
For example, if you were to change your code to the following - so that test is an explicit property of window - the delete will work.
window.test = [];
window.test[0]="111";
window.test[1]="555";
delete window.test;
alert(window.test[0]);
Whenever delete, it returns a boolean that tells wether it could delete the var or not. In this case, it returns false:
delete test; // false
You can just set test to undefined:
test = undefined;
you can use test = undefined to make remove object value
I've been reading through quite a few articles on the 'this' keyword when using JavaScript objects and I'm still somewhat confused. I'm quite happy writing object orientated Javascript and I get around the 'this' issue by referring the full object path but I don't like the fact I still find 'this' confusing.
I found a good answer here which helped me but I'm still not 100% sure. So, onto the example. The following script is linked from test.html with <script src="js/test.js"></script>
if (!nick) {
var nick = {};
}
nick.name= function(){
var helloA = 'Hello A';
console.log('1.',this, this.helloA);
var init = function(){
var helloB = 'Hello B';
console.log('2.',this, this.helloB);
}
return {
init: init
}
}();
nick.name.init();
What kind of expected to see was
1. Object {} nick.name, 'Hello A'
2. Object {} init, 'Hello B'
But what I get is this?
1. Window test.html, undefined
2. Object {} init, undefined
I think I understand some of what's happening there but I would mind if someone out there explains it to me.
Also, I'm not entirely sure why the first 'console.log' is being called at all? If I remove the call to the init function //nick.name.init() firebug still outputs 1. Window test.html, undefined. Why is that? Why does nick.name() get called by the window object when the html page loads?
Many thanks
Also, I'm not entirely sure why the first 'console.log' is being called at all?
nick.name = function(){
// ...
}();
Here you define a function, call it immediately (hence ()) and assign its return value ({init: init}) to nick.name
So the execution is:
Create a variable called nick if there isn't one with a non-falsey value already
Create an anonymous function that…
Creates a variable called helloA in its own scope
Outputs data using console.log containing "1" (as is), this (the window because the function is executing in the global context instead of as a method), and this.helloA (window.helloA, which doesn't exist.
Defines a function called init
Returns an object which gets assigned to nick.name
Then you call nick.name.init() which executes the init function in the context of name.
This defines helloB
Then it console.logs with "2" (as is), this (name), and this.helloB (nick.name.helloB - which doesn't exist)
So the first output you get is from console.log('1.',this, this.helloA);
I think your main problem is that you are confusing this.foo (properties on the object on which a method is being called) with variable scope (variables available to a function)
It's much simpler if you think about this as a function, not as a variable. Essentially, this is a function which returns current "execution context", that is, the object the current function was "applied" to. For example, consider the following
function t() { console.log(this)}
this will return very different results depending upon how you call it
t() // print window
bar = { func: t }
bar.func() // print bar
foo = { x: 123 }
t.apply(foo) // print foo
this is defined on a per-function basis when the function call is made. When you call a function as o.f(), this will be o within the function, and when you call it as f(), this will be the global object (for browsers, this is the window).
You wrote nick.name = function(){...}(); and the right-hand part is of the form f(), hence the Window.
var foo = bar; defines a local variable. It may not be accessed as this.foo (well, except when you're at global scope, but that's silly). To define a member, you usually write this.foo = bar; instead.
This is what your code does:
It creates an object and assigns to the variable nick.
It creates an anonymous function.
It calls the function (in the window scope).
It assigns the return value (an object containing the init property) to the name property of the object.
It gets the value from the init property, which is a method delegate, and calls the method.
The anonymous function does this:
It declares a local variable named helloA and assigns a string to it. (Creating a local variable doesn't add it as a property to the current object.)
It logs this (window) and the helloA property (which doesn't exist).
It creates an anonymous function and assignes to the local variable init.
It creates an object with the property init and the value from the local variable init.
The anonymous function assigned to the init property does this:
It declares a local variable named helloB and assigns a string to it. (Creating a local variable doesn't add it as a property to the current object.)
It logs this (the object from the name property, not the nick variable), and the helloB property (which doesn't exist).