Javascript copies objects by reference, rather than literally. For example:
var myObject = {};
var myCopy = myObject;
myObject.foo = "bar";
alert(myCopy.foo); //alerts "bar"
But I am really struggling to think of practical, real world reason for this other than giving developers a way to make code slightly more readable (as you can give different uses for the same object different names).
The most likely thing is I have missed the point, so can anyone tell me what that point is?
After writing:
var myObject = {};
There is an object out in memory somewhere that you can refer to by the name myObject. The following assignment:
var myCopy = myObject;
...says that myCopy now refers to that same object, wherever it may be. This is the same thing that happens when you give an argument to a function:
function somefunc(localName) {
// body
}
someFunc(myCopy);
Now there is a variable called localName that is local to someFunc that also refers to that same object out in memory.
This is the fundamental way in which we pass around references to an object, so that it can be referred to by different names, in different scopes.
We could copy the entire structure into a new location in memory. There was nothing stopping the designers from creating a language that did that. But it's less efficient -- think of deeply nested objects -- and generally not what you want to do. For example, if a function modified one property of an object, it would need to return the entire object for that change to persist outside of the function. And the caller would need to handle that return value, deciding whether the old object needs to be kept or if the newly created, slightly different copy can overwrite it.
Again, there's nothing wrong with this design direction in principle; it's just not how JavaScript was designed.
It depends; in your case it might be rather confusing since it doesn't serve a real purpose. However, for longer paths to the object it can be advantageous to store the object in a separate variable, because it requires less typing for each statement that uses the object, such as in this example:
var style = document.getElementById("foo").style;
style.color = "red";
style.font = "sans-serif";
// ...
My opinion (and it's nothing more than that) is that creating an object by reference (rather than copy) is generally more useful and what the user wants. If you pass an object as a param to a method, you're (almost always) interested in the object being worked on and altered by that method, rather than by working on a copy (and leaving the original untouched). Obviously there are circumstances where this is not true and it would be nice to have the option to choose, but I've can't recall ever finding myself wishing that I could just pass an object copy to a method, and am usually very grateful that the thing I'm working with is THE thing.
Related
First of all, I want to clarify, I know that with is deprecated, and using it is generally a bad practice.
However, my question is about a special case: using a special Proxy object as the parameter of with.
Background
I'm working on a project, where I have to limit access of a piece of code to the global scope.
One approach might be to use a loop with eval, that creates constant variables with the value of undefined for each property of the global object, but that seems even worse than using with, and cannot limit access to variables created with let and const.
The idea
The idea is to use a Proxy as the argument of with, whose...
has trap always returns true, therefore it doesn't allow any lookups or assignments to go beyond the with statement
get trap operates normally, except that it throws ReferenceErrors when trying to access a non-existing variable (i.e. property)
set trap operates normally (or maybe contains some custom logic)
target object has no [[Prototype]] (i.e. it was created with Object.create(null))
target object has an ##unscopables property, with the value of an empty object, to allow scoping of every property
So, something like this code:
const scope = Object.create(null)
Object.assign(scope, {
undefined,
console,
String,
Number,
Boolean,
Array,
Object,
/* etc. */
[Symbol.unscopables]: Object.create(null)
})
const scopeProxy = new Proxy(scope, {
get: (obj, prop) => {
if (prop in obj)
return obj[prop]
else
throw new ReferenceError(`${prop} is not defined`)
},
set: Reflect.set,
has: () => true
})
with(scopeProxy) {
//Sandboxed code
foo = Number('42')
console.log(foo) //42
try{
console.log(scopeProxy) //Inaccessible
}catch(e){
console.error(e) //ReferenceError: scopeProxy is not defined
}
}
Avoiding contras
There are several contras listed on the MDN's page about the with statement, but this usage of it gets rid of each.
1. Performance
The problem:
Looking up identifiers that aren't a member of with statement's parameter object is less performant.
Avoidance:
No lookups can go beyond the parameter object.
2. Ambiguity
The problem:
It is hard to decide, which identifier gets looked up of those with the same name.
Avoidance:
All lookups and assignments retrieve or modify the property of the parameter object.
3. Forward compatibility
The problem:
The properties of the parameter object or its prototype might change in the future.
Avoidance:
The parameter object is initially empty and has no prototype, therefore no properties can change.
Question
The above code works perfectly, and the contras listed on MDN don't seem to apply to this case.
So, my question is:
Is it still a bad practice to use the with statement, and if so, what are the downsides of using it in this specific case?
Note: I know that this approach in itself is not secure and can be bypassed. However, this question is limited only to whether it's considered bad for some reason to use the abovementioned Proxy-with combination. In this question, I'm not concerned about security (that's a related, but different question).
Sounds like the good old lexical vs dynamic scope topic. In general lexical scope is more safe but in some situations dynamic scope makes sense, because it simplifies some solutions very much. I would say your example is one of the cases, where it may be useful.
I have some questions about my prototypal inheritance pattern that I am using for my app. First of all take a look at the pattern that I am using;
const myObjectProto = (function() {
const proto = Object.create( parentProto );
// private variables
let title = 'Some String';
// private functions
const addEmoticon = function() {
return title + ' ';
}
proto.getTitle = function() {
return addEmoticon();
}
return proto;
})();
And when I want to use it, I will use it like below:
const firstObject = Object.create( myObjectProto );
const secondObject = Object.create( myObjectProto );
// call a public function
firstObject.getTitle();
secondObject.getTitle();
My first question is this: assume that we are creating 100 objects from its corresponding proto; As far I know title is shared among them. That means if a function change it, it will be changed for all created objects. I am a little worried about the memory in this case. Do I use memory efficient with this pattern? Can someone clarify how Object.create treats with title?
My second question is about the memory leak; Let say that we want to set the firstObject to null;
firstObject = null;
Based on the fact that we have shared variables like title and even proto, I think it does nothing and I have memory leak. Am I right? If this is true, how can I fix it?
title is a local variable. It will exist as long as some code can access it. It will only exists once, as the IIFE only executes once, thus only one variable gets created. The function inside addEmoticon can access title, in other words it closures over it. As it is a local itself, it will also only exist as long as it can be accessed. It gets accessed inside the function stored inside proto.getTitle, which again closures over addEmoticon. proto.getTitle exists as long as proto can be accessed. As the value of proto gets stored inside the global variable const myObjectProto, it can always be accessed thus it will live forever (as well as every value that can be accessed through it, e.g. title).
Do I use memory efficient with this pattern?
Well, you allocate a few bytes once. Assuming that you have a few Megabytes available, thats not a lot.
As far I know title is shared among them
Yes.
Based on the fact that we have shared variables like title and even proto, I think it does nothing and I have memory leak.
You loose the reference to the instance stored in firstObject, thus making it viable for garbagge collection. That might free a few bytes. As the prototype is still available via secondObject and myObjectProto, it will continue living.
I have memory leak. Am I right?
A memory leak is a noticible amount of memory, that is still allocated although the values in it don't need to be used anymore. Under the assumption that you want to work with secondObject, and create new instances from myObjectProto, everything you've stored is still needed. Your code is perfectly fine.
So, say I have a class (not a great example but it works for this purpose):
function Apple (type) {
this.getInfo = function() {
alert('this apple is green');
};
this.getInfo();
}
and I want to create an instance of it, so I would typically do:
var apple = new Apple();
However, in my scenario, because the instance will execute immediately, I don't need the variable, so I just want to do:
new Apple();
which I know is possible, but what I don't know is what javascript will do behind the scenes. Will it create a memory reference anyway? Will it put some token into global variables? Or does it just run a one time executing class instance?
essentially, I'm asking what the harm in just using "new Apple();" is.
Update
Since this is clearly too ambiguous to get the advice i was looking for let me be more specific. At my company we use a standard classing structure for javascript files simply for consistency. This is the structure i'm talking about (mind you uses the class design from http://ejohn.org/blog/simple-javascript-inheritance/):
MyClassName = Class.extend({
init: function (/*param1, param2, etc*/) {
// this method is called immediately when the class is instantiated.
},
destroy: function () {
// this is your clean up method.
}
});
There are times when MyClassName will not need to be assigned to a variable simply because the intent is for the init method to start the whole thing, so short of lint picking up the usage of "new MyClassName();" to be an error what will core Javascript do is my ultimate question.
Most JS linters will flag instantiating a class without assigning it to a variable or property, because it indicates that either:
You made a mistake, and actually need a reference, or
You're calling the constructor for its side-effects (as is the case here), in which case you'd be better off calling a function instead.
In the latter case, it is likely (though it depends on the JS environment) that you are allocating memory you won't use by instantiating an object you don't reference. It's also (though this is opinion) usually a Bad Idea to have side effects in your constructor, as they undermine developer expectations about what creating an instance will do, and they can lead to hard-to-find bugs. It's usually simpler to put the side-effect code in a method and call it:
function Apple (type) {
this.getInfo = function() {
alert('this apple is green');
};
}
var a = new Apple();
a.getInfo();
People have already addressed why you shouldn't so I'll say what actually happens. Since your object uses this a new memory reference will be created. Assuming you don't pass that reference to anything (i.e., store a reference to the object in another object or in a closure context) and it doesn't reference any external, persistent values (anything in a closure context that is used elsewhere) then it will be collected during the next garbage collection cycle.
This article specifically talks about V8's memory model but most Javascript engines follow a similar model.
TL;DR It's not considered good practice but assuming you don't store any references to the new object, you won't be any worse for wear.
I've seen this syntax for creating an anonymous constructor function in JavaScript:
var Application = Application || {};
!function(window, Application) {
Application.property = {/*...*/}
Application.method = function(){/*...*/}
}(window, Application);
I want to understand what the following parts here:
What is the advantage of using first line (i.e. var o = o || {};) vs just stating var o = (function(){})();?
Why ! is used in front of function?
Why would I pass window or Application as parameters when they are global object?
Is this the most convenient way for anonymous constructor function and how is this better than:
4a)
var Application = {
property: {},
method: function(){}
}
or 4b)
var Application = (function() {
var method = function(){/*...*/}
return {method:method};
}());
The first line is to ensure that Application always exists, and is generally used in cases where it's expected that Application already should exist, and the function just augments the existing object. If it doesn't exist, this makes sure that we don't get an error for accessing properties of undefined. Your examples are only equivalent in the case where Application does not yet exist. In all other cases, your code will obliterate the existing Application, which is almost certainly not the intent.
The comment from Vatev explains what the ! does. It's another syntax for making the function in question become a self executing anonymous function. (Incidentally, it also takes the return value of the function - which is currently undefined, and flips its truthyness, so it evaluates as true. Since the result isn't stored in any variable, though, that's clearly not the purpose.)
Finally, why pass window and Application into the function and use it there? This is a safety feature, in case other code changes window or Application later on. It guarantees that within the anonymous function, window and Application are exactly what you expect it to be. In the shorthand example you gave, this may appear to not matter - after all, why protect these variables if you're using them immediately and not storing them? In many cases, you return something from this function, and then window and Application would be stored in the closure, so you'd retain the variables. It makes it safe from people who later on decide to say Application = {...}.
I don't know all of the answers but I'll try to answer what I can.
Using var Application = Application || {}; simply means that you are dealing with scope. If the "Application" variable has already be defined, it will just mean that it inherits and is now available in the current scope. If not, the "||" part (means OR) means that it will be created as an empty object. You are dealing with creating an object and then acting on it, not just having the result given back raw. That's why you shouldn't use "o = (function() {...});". "o" would then be the result of the function and not the object.
The use of "!function" causes it to be treated as an expression, but this can be tricky because you may have to think in opposites. E.g. !null means you are checking that it isn't null, not that you are checking for it to be null.
Passing in the window and Application objects deal with scoping, again. It is explicitly passing them into the function, then returning them at the end. Think of this as putting clothes in the washing machine. You put them in, stuff can happen, then you get them back out. It's a really crude idea and isn't the best example, but it's how I thought of it a while back. You put clothes in, call then rinse function, then soap function, then rinse again, then spin to drain water.
Hopefully someone else can answer that, I'm not sure what the differences are.
Since two answers so far neglected these two details: A pattern used by libraries like jQuery is using the following two parameters:
(function (window, undefined) {
window.myPlugin = ...;
})(window);
There are two things going on here:
undefined is specified as a parameter, but not passed in. This way, undefined is guaranteed to have th expected value within the inner scope. This is only necessary for older browsers which allowed overwriting undefined (though it has always been considered bad practice to do so – it's just what libraries like jQuery do to avoid other code interfering with their code).
Aliasing a global object like window within the scope allows the code to be minified more (also works for undefined). Obviously, the more references you have to the aliased object(s), the more you will save:
.
(function(w,u){w.myPlugin=...;w.somethingElse=...;if(whatever===u){return;}})(window);
compared to
(function(){window.myPlugin=...;window.somethingElse=...;if(whatever===undefined){return;}})();
You won't save much with window since typically you don't wanna clutter the global object up anyway. But aliasing undefined can save you quite some space.
Coming from C++ it is hard grained into my mind that everytime I call new I call delete. In JavaScript I find myself calling new occasionally in my code but (hoping) the garbage collection functionality in the browser will take care of the mess for me.
I don't like this - is there a delete method in JavaScript and is how I use it different from in C++?
Thanks.
var component = new Component();
component = null; // delete this at next garbage collection
Incidentally, the "new" keyword isn't really necessary in javascript, and has nothing (directly) to do with allocating memory. All "new" does is pass a new, empty object called "this" (this = {}) as a hidden argument to the function.
var MyClass = function(){
// fresh empty object "this" gets passed to function
// when you use the "new" keyword
this.method = function(){}
}
var myInstance = new MyClass();
Javascript can get kind of hairy with nested closures and multiple "this" variables floating around in different scopes. I prefer to do it this way:
var MyNoNewClass = function(){
// I find this more explicit and less confusing
var self = {}
self.method = function(){}
return self;
}
var myNoNewInstance = MyNoNewClass()
All JavaScript memory is referenced, but not in the traditional sense. Memory is referenced not by memory address but by a string. In this code:
var x = new someObj();
That object is referenced by the string "x" from that point forward. x is not a pointer to some memory on the heap at that point. If you assigned x a property then:
x.someProp = 42;
Then someProp is a string in memory referencing the value 42. Consequently that lets you use array notation to access it by it's string representation:
x["someProp"]++;
It's also why variables can hold any value as they don't have need of size.
Memory is collected in JavaScript, effectively, when no more strings (aka variables or property names) are referencing it. That object will be collected when x is assigned any other value. You could set it to null, undefined, or anything else and that memory will be collected.
That is, it will be collected when the browser or whatever JavaScript engine gets around to it.
Delete only removes properties from objects. From then on attempting to access that property will return undefined. For the most part, the following 2 lines of code are equivalent:
x["someProp"] = undefined;
delete x.someProp;
Edit: Ok, internally the two lines aren't the same. The delete operator will remove the "someProp" reference from memory, while setting it to undefined won't. I think. I can't find anything in the specs about setting a variable or property to undefined, but I don't think doing so does anything special.
The important thing to note is that you won't be able to delete properties that have a certain flag set, but you can set them to null or undefined (if they're not wrapped by a setter and even allow that to happen).
Taken outside of the context (the browser) the javascript is fully capable of reclaiming the memory through garbage collection. Going back to reality garbage collection in combination with DOM model can cause memory leaks.
Here is one article http://www.ibm.com/developerworks/web/library/wa-memleak/ you can find more details about it
To avoid memory leaks
Ensure you remove all event handlers, so if you add like a mouse down event handler ensure you remove it when you finish
if you add elements to the DOM, remove them when done
if you have an object that points to another object, remove the reference when the object is done with.
when you are finish with any object set it to null.
deletes just gonna remove a property from an object.
There is a delete. However, an actual need for it will be rare. It's not like C++ delete, though.
delete in JavaScript will remove a property from an object. Subsequent accesses of that property will return undefined. I assume it will be able to free any associated memory on subsequent garbage collects.
Don't use delete in JavaScript unless you are removing event handlers. Even then, we only do this because there is a memory leak associated with this practice in older versions of IE. Douglas Crockford explains this pretty well. In his case, he doesn't even use delete. He simply sets the values in question to null.
From the MDC:
The delete operator deletes a property of an object, or an element at a specified index in an array.
The delete operator in my opinion is only useful when you want to remove a property from an object. But since there might be other references to the property that it were referencing, it wont be really GCed. If you want something to be GCed, you need to remove all pointers pointing at it and also free the closures containing references to it (more info on the topic).
new creates objects from a constructor. delete removes properties from an object. These are two very different things.
You don't have to delete objects you created. The GC takes care of this.
delete o.fu is different from o.fu = undefined. Try this:
var o = {};
alert(o.hasOwnProperty('fu')); // -> false
o.fu = undefined;
alert(o.hasOwnProperty('fu')); // -> true
delete o.fu;
alert(o.hasOwnProperty('fu')); // -> false
There is a delete in Javascript, but trust me: it's way different than delete in something like C++. I recommend you don't even think about using it until you're more comfortable with Javascript.
Garbage collection works, though it doesn't defeat the problem of memory leaks.
The "new" keyword has nothing to do with memory. It's purpose is only to setup the prototype chain.
// C++
Foo* foo = new Foo(); // allocate and construct
// JS "sugar" using the new keyword
var foo = new Foo(); // allocate and construct
assert(foo instanceof Foo);
// JS constructing objects without "new"
var foo = Object.create(Foo.prototype); // allocate with prototype
Foo.call(foo); // construct
assert(foo instanceof Foo);
// construct Foo with missing prototype
var foo = {}; // allocate without prototype
Foo.call(foo); // construct without prototype
assert(!(foo instanceof Foo));
// so the corollary operations in JS are
foo = {};
foo = null;
// where-as this is an error (or most certainly not what you want)
delete foo;
// and this is how delete is used
foo = {bar: 42};
assert(foo.bar === 42);
delete foo.bar;
assert(foo.bar === undefined);
// but by deleting a property, you remove the reference to the object
foo = {bar: {baz: 31}};
delete foo.bar; // remove only reference to "bar" object
// JS GC will now take over
So no, you can't delete objects. But you can delete references to objects, which may trigger object deletion by the GC. But of course, local variables (and global) can't be deleted. They simply go out of scope, de-referencing any associated objects, and potentially freeing memory, but only if the object wasn't returned or is still referenced elsewhere.
It's important to realize that because JS doesn't support pointers, GC can be perfect. At any point, the GC can simply walk the entire set of objects "seen" from any in-scope function and guarantee it doesn't miss anything like cycles, etc.
As long as you use JS in a functional style and don't try to build global god objects which tie everything together, memory management should be a non-issue.