PDF In-Depth

The Trouble with 'this'

July 20, 2001

Advertisement
Advertisement
 

You may be doing more typing than necessary

Programming requires a lot of repetitive typing of variable and method names (have you noticed?), which in turn invites typos, so I like to look for ways to cut down on needless typing (hence needless typo-chasing). At the risk of being pelted with overripe vegetables, I'd like to take to the soapbox for a minute to tell you about my latest recommendation for eliminating needless keystrokes while writing JavaScript for PDF.

Very simply, stop using 'this' where it's not needed. Which is practically everywhere.

I've come to the reluctant conclusion that we've all been witless saps for typing 'this' in front of Doc object properties and methods all these years. (At least, it feels like years...) You know what I'm talking about:

    var name = this.getField('name').value;

This is a typical example of the (unnecessary) use of 'this' as an object specifier. We use 'this' on the front of Doc object methods and properties, ostensibly, to specify the current document's Doc object. In theory, one could obtain a remote PDF document's Doc object reference (by communicating via globals) and use it to 'scope' methods or properties to the remote document. But in fact, no one programs this way. And if you do, you're going against Adobe's recommendations. Adobe recommends against using any Doc object reference(s) to any remote document(s), for the simple reason that such references can be invalidated suddenly, without warning, if a file closes while the Doc reference is still open.

To deal with the "dangling Doc reference" problem, Adobe has come up with publish() and subscribe() methods for Acrobat 5.0 (available now, undocumented, in 4.05).

So if you're not supposed to use a Doc object reference other than 'this', what good is 'this'? It is no help to the JavaScript runtime engine. By default, Acrobat's JavaScript interpreter always tries to scope methods like getField(), and properties like zoom and pageNum, to the current Doc object, which is associated with the document in which the code is executing. The use of 'this' as a scoping hint is therefore meaningless, unless you're going against Adobe's advice on remote doc manipulations.

A New Style of Coding

You might as well get used to the fact that code referencing Doc-object methods will work just fine without 'this' on the front. Use no object specifier at all. You can just write:

   
    // set page magnification to 83%:
    zoom = 83;
    
    // take the user to page 12:
    pageNum = 12;
    
    // fetch a field value:
    var name = getField('field_name').value;
    
 // give all fields a red background color:
    for (var i = numFields; i; i--)
      getField(getNthFieldName(i - 1)).bgColor = color.red;

Acrobat will not complain and your user will never know the difference. Your code will be cleaner, you'll eliminate a lot of typing (which, for me, means fewer typos), and the JavaScript interpreter won't barf. No men with black sunglasses will come to your door. No certified letters will arrive. The Thought Police will just add it to your existing rap sheet.

When I asked a JavaScript expert at Adobe why anybody should use 'this' as a Doc scoping hint, given that it's not at all necessary, the (non)answer I got was "Code just seems to read better with 'this'..."

Why 'this' Can Be Dangerous

I'm going to go a step further and maintain that not only does 'this' serve no useful purpose whatsoever as a Doc reference in Acrobat JavaScript, it can actually be dangerous under certain circumstances. Let me show you an example.

Suppose you are creating a custom object, called a Circle. Your constructor might be:

 
     function Circle(r) {
     
        this.radius = r;
        this.circumference = Math.PI * 2 * r;
        this.area = r * r * Math.PI;
     }

To create a Circle object with a radius of 5, you would do:

 
    var c = new Circle(5);

At that point, you could inspect the value of c.area (and you'd find that it's 78.5398163397448).

But notice one thing. Inside our constructor function, we've used 'this' to refer to the current object. The word 'this', in this context, refers to the object created by the constructor, not the Doc object.

In fact, if you try to call a Doc object method or property, such as this.zoom or this.calculateNow(), from inside the Circle() function, your code will fail.

To call an Acrobat method from inside the Circle constructor, you'd have to do something like:

 
    global.mydoc = this; // grab Doc object reference
    
    function Circle(r) {
     
        this.radius = r;
        this.circumference = Math.PI * 2 * r;
        this.area = r * r * Math.PI;
        
        global.mydoc.getField('radius').value = r;
     }

The only other way to get any Doc object methods or properties to work properly in the code for Circle() is to leave off the 'this' specifier.

On the other hand, if you want, you can call getField() completely bare, inside the Circle() function. (Ditto for zoom, pageNum, and all the rest.) If you put 'this' on the front, Doc object calls fail.

A Different Kind of Global

In Acrobat JavaScript, there are actually two types of globals: those attached to the Global object (whose reference is the lowercase 'global'), and those attached to the Doc object (whose reference is 'this'). The scope is different, obviously, in each case. Globals attached to 'global' are visible from any open PDF document (even across sessions, if made persistent). Variables attached to 'this' are visible from anywhere in the current PDF document, but not other documents.

Let's say you want to create a Doc-level global called myAnswers, that you want to share between functions, but you don't want other open PDF documents to have access to this variable. Obviously, if you create myAnswers as a 'global' property in the usual way, it becomes visible to other PDF documents (which you don't want). To limit the scope to just the current document, do:

 
    this.myAnswers = new Array('3.14','Sacramento','1812');

Now, any time you want to access the myAnswers array, from *any* function in the current document (top-level, field-level, or what-have-you) you can simply inspect this.myAnswers, or (remembering not to type 'this') just myAnswers.

In fact, since 'this' is never necessary as a reference to the current Doc, you can declare Doc-level globals by simply leaving off the 'var' declarator:

 
   reply = "Good";  // Doc-level variable
   
   var reply = "Bad";  // local variable

   app.alert(reply); // guess which one displays?
   

If you've followed this discussion of 'this' this far, you can probably guess which "reply" value displays in a call to app.alert(reply). The answer is, if the local variable is still in scope, the local "reply" value ("Bad") will display in the alert dialog. Otherwise, the Doc-level "reply" will display. Why? In JavaScript, as in all languages, local variables take precedence over higher-level variables of the same name.

Having said all this, maybe it's going too far to suggest that you should always avoid using 'this' as a Doc reference. Go ahead and keep using it if you want. (Some of us don't like to type so much.) Just remember that inside a constructor, 'this' doesn't have the meaning you thought it did.

I call 'this' interesting, to say the least.

PDF In-Depth Free Product Trials Ubiquitous PDF

Debenu Quick PDF Library

Get products to market faster with this amazing PDF developer SDK. Over 900 functions and an equally...

Download free demo

Back to the past, 15 years ago! Open Publish 2002

Looking back to 2002, it's amazing how much of the prediction became a reality. Take a read and see what you think!

September 14, 2017
Platinum Sponsor





Search Planet PDF
more searching options...
Planet PDF Newsletter
Most Popular Articles
Featured Product

Debenu PDF Aerialist

The ultimate plug-in for Adobe Acrobat. Advanced splitting, merging, stamping, bookmarking, and link control. Take Acrobat to the next level.

Features

Adding a PDF Stamp Comment

OK, so you want to stamp your document. Maybe you need to give reviewers some advice about the document's status or sensitivity. This tip from author Ted Padova demonstrates how to add stamps with the Stamp Tool along with related comments.