JSLint Error: Unexpected ‘this’

JSLint Error: Unexpected ‘this’

Having trouble understanding why JSLint is surprised by my use of this in the following code:

function testConstr (x) {
‘use strict’;
this.joker = “Whyyy sooo seriousss?”;
this.x = x;
}

For both property assignments, JSLint says: Unexpected ‘this’. How do I correct my code?

Solutions/Answers:

Solution 1:

Your code might be perfectly correct (it might also be problematic, depending on how you call testConstr).

My suggestion is: tell JSLint to shut up

enter image description here

Or don’t use JSLint at all.

Solution 2:

So in other words, JSLint doesn’t automatically expect me to use a constructor pattern?

You know, I think you’re right. Your question bugged me, and I signed up for Crockford’s JSLint discussion group and asked. He replied, but ignored the solution I’m going to present, below, which I think means that it’s okay, the same way JSLint doesn’t complain if something passes muster.

(I’m still waiting for an updated Good Parts, though.)

That caveat aside, here’s what I’d suggest doing for OO JavaScript that passes Beta JSLint (as of today, anyhow).

I’m going to rewrite an example from MDN’s page, “Introduction to Object Oriented Programming,” which itself uses this liberally.

With this

Here’s the original, unlinted MDN example from the section linked, above:

var Person = function (firstName) {
  this.firstName = firstName;
};

Person.prototype.sayHello = function() {
  console.log("Hello, I'm " + this.firstName);
};

var person1 = new Person("Alice");
var person2 = new Person("Bob");

// call the Person sayHello method.
person1.sayHello(); // logs "Hello, I'm Alice"
person2.sayHello(); // logs "Hello, I'm Bob"

That follows the conventions we know and love.

Related:  In Javascript, how do I check if an array has duplicate values? [duplicate]

Without this

It’s pretty easy to figure out how to make “constructors” that don’t follow that pattern, but we lose use of prototype, if I’m not missing something, and have to include all of the object’s methods in our constructor that we want all of our Peeps to share.

/*jslint white:true, devel:true */
var Peep = function(firstName) {
    "use strict";
    var peep = {};
    peep.firstName = firstName;

    peep.innerSayHello = function() {
        console.log("Hello, I'm " + peep.firstName + ".");
    };

    return peep;
};

var peep1 = new Peep("Bob");
var peep2 = new Peep("Doug");

peep1.innerSayHello();
peep2.innerSayHello();

So there’s a lintable alternative. That does, other than the return peep; and the inner definition of methods, make JavaScript act like many OO-first languages you might encounter. It’s not wrong, at least.

Not having access to prototype isn’t horrible; it’s really bad news to change prototype somewhere that’s not right beside the constructor, as your code would go to spaghetti. “Some Persons have sayGoodbye() and some don’t, depending on if we’d amended the prototype at the point of their construction.” That’s awful. So this alternative convention has its advantages.

You can still, of course, add functions to a single instantiation of Peep later, but I’m not sure how you’d access firstName without using this, so perhaps he wants us to stop munging objects after construction.

person1.sayGoodbye = function (other) { 
    console.log("Goodbye, " + other + "."); 
};

(I mean, we could also still monkey-patch Peep to change it mid-process, but that’s horrible, stupid programming. Usually.)

Inheritance (without this)

And inheritance is easy enough, I think.

Related:  How to get rid of underline for Link component of React Router?
var PeepWithGoodbye = function (firstName) {
    "use strict";
    var peepWithGoodbye = new Peep(firstName);

    peepWithGoodbye.innerSayGoodbye = function (otherPeep) {
        if (undefined === otherPeep) {
            otherPeep = { firstName: "you" };
        }
        console.log("This is " + firstName 
            + " saying goodbye to " + otherPeep.firstName + ".");
    };

    return peepWithGoodbye;
};

var pwg1 = new PeepWithGoodbye("Fred");
pwg1.innerSayHello();           // Hello, I'm Fred.
pwg1.innerSayGoodbye(peep1);    // This is Fred saying goodbye to Bob.
pwg1.innerSayGoodbye();         // This is Fred saying goodbye to you.

EDIT: See also this answer where the asker later found Crockford’s suggested means of creating OO javascript. I’m trying to convince that guy to delete that Q&A and move the A here. If he doesn’t, I’ll probably add his stuff and community wiki it here.


EDIT: See this from MDN for why it works:

(Normally constructors don’t return a value, but they can choose to do
so if they want to override the normal object creation process.)

Solution 3:

'use strict';

var SudoConstructor = (function () {

    /* We need bind, < IE9 needs a (tiny) polyfill */

    function protoEsqDeclare(sudoThis) {
        return sudoThis;
    }

    function protoEsqSet(sudoThis, newValA, newValB) {
        sudoThis.valA = newValA;
        sudoThis.valB = newValB;
    }

    function instanceCreator(valA, valB) {
        var sudoThis = {
            valA: valA,
            valB: valB
        };

        return {
            declare: protoEsqDeclare.bind(null, sudoThis),
            set: protoEsqSet.bind(null, sudoThis)
        };

    }

    return instanceCreator;

}());

Solution 4:

In a strict mode this reference is set to undefined.

So both your statements will cause reading properties of the undefined object, which will lead to an exception.

How do I correct my code?

Remove both those lines.

Related:  Define global variable in a JavaScript function

UPD: what I state above is how JSLint treats your code, not how I do that.

Solution 5:

JSLint says: Unexpected ‘this’. How do I correct my code?

There is no need to correct your code.

In the help page for JSLint, in the section for the /*jslint*/ directive, a “Tolerate this” option has been added to the table of available options:

+---------------+------+---------------------------------+
| Tolerate this | this | true if this should be allowed. |
+---------------+------+---------------------------------+

So, to suppress complaints about the use of this, place the following directive into your source file before the first statement:

/*jslint
    this
*/

(Note that other /*jslint*/ options may follow this by inserting a comma between options. See the JSLint help page.)

Also see the answer by @Oriol to enable the “Tolerate this option in the user interface for JSLint.

Solution 6:

An old question I know, but in case it helps anyone, I was watching a talk by Douglas Crockford in which he says (at about 23mins) that he took it out because an attacker could run a method as a function and get access to the global scope with the ‘this’ keyword.

He says it also meant not using Object.create anymore either – a feature he helped introduce to the language!

References