AJAX In Action [150]
Let’s play with the object model a bit. In the script below, we create three objects:
1
jim, a Person
2
whiskers, a Cat
3
fido, a Dog
Licensed to jonathan zheng JavaScript memory footprint 305 First, we instantiate a Person (step 1): var jim=new Person("jim"); Next, we give that person a pet cat (step 2). Whiskers is instantiated inline in the call to addPet(), and so that particular reference to the cat persists only as long as the method call. However, jim also makes a reference to whiskers, who will be reachable for as long as jim is, that is, until we delete him at the end of the script: jim.addPet(new Cat("whiskers")); Let’s give jim a pet dog, too (step 3). Fido is given a slight edge over whiskers in being declared as a global variable, too: var fido=new Dog("fido"); jim.addPet(fido); One day, Jim gets rid of his cat (step 4): jim.removePet("whiskers"); Later, he gets rid of his dog, too (step 5). Maybe he’s emigrating? jim.removePet("fido"); We lose interest in jim and release our reference on him (step 6): jim=null; Finally, we release our reference on fido, too (step 7): fido=null; Between steps 6 and 7, we may believe that we have gotten rid of jim by declaring him to be null. In fact, he is still referenced by fido and so is still reachable by our code as fido.owner. The garbage collector can’t touch him, leaving him lurking on the JavaScript engine’s heap, taking up precious memory. Only in step 7, when fido is declared null, does Jim become unreachable, and our memory can be released. In our simple script, this a small and temporary problem, but it serves to illustrate that seemingly arbitrary decisions affect the garbage-collection process. Fido may not be deleted directly after jim and, if he had the ability to remember more than one previous owner, might consign entire legions of Person objects to a shadow life on the heap before being destroyed. If we had chosen to declare fido inline and the cat as a global, we wouldn’t have had any such problem. To assess the seriousness of fido’s behavior, we need to ask ourselves the following questions: Licensed to jonathan zheng 306 CHAPTER 8 Performance 1 How much memory might he consume in terms of references to otherwise deleted objects? We know that our simple fido can remember only one Person at a time, but even so, that Person might have a reference to 500 otherwise-unreachable pet cats, so the extra memory consumption might be arbitrarily large. 2 How long will the extra memory be held? In our simple script here, the answer is “not very long,” but we might later add extra steps in between deleting jim and deleting fido. Further, JavaScript tends toward eventdriven programming, and so, if the deletion of jim and of fido takes place in separate event handlers, we can’t predict a hard answer, not even a probabilistic one without performing some sort of use-case analysis. Neither question is quite as easy to answer as it might seem. The best that we can do is to keep these sorts of questions in mind as we write and modify our code and to conduct tests to see if we’re right in our assumptions. We need to think about the usage patterns of our application while we code, not solely as an afterthought. This covers the general principles of memory management. There are specific issues to be aware of in an Ajax application, so let’s address them next. 8.3.2 Special considerations for Ajax So far, we’ve covered some ground that is common to the memory management of most programming languages. Properly understanding concepts such as footprint and reachability are important when developing Ajax applications, but there are also issues that are specific