Подтвердить что ты не робот

Ошибка JSLint: неожиданно 'this'

Не удается понять, почему JSLint удивляется моим использованием this в следующем коде:

function testConstr (x) {
    'use strict';
    this.joker = "Whyyy sooo seriousss?";
    this.x = x;
}
4b9b3361

Ответ 1

Ваш код может быть совершенно правильным (это может быть проблематично, в зависимости от того, как вы вызываете testConstr).

Мое предложение: скажите JSLint заткнуться

enter image description here

Или вообще не используйте JSLint.

Ответ 2

Иными словами, JSLint автоматически не ожидает, что я буду использовать шаблон конструктора?

Знаешь, я думаю, ты прав. Ваш вопрос прослушивал меня, и я подписался на дискуссионную группу Crockford JSLint и спросил. Он ответил, но проигнорировал решение, которое я собираюсь представить ниже, что, я думаю, означает, что все в порядке, так же, как JSLint не жалуется, если что-то пройдет.

(Я все еще жду обновления Good Parts.

Это предостережение в стороне, вот что я предлагаю сделать для JavaScript OO, который передает Beta JSLint (на сегодняшний день, так или иначе).

Я собираюсь переписать пример из MDN-страницы, Введение в объектно-ориентированное программирование, который сам использует this либерально.

С this

Здесь исходный, незакрепленный MDN-пример из раздела, связанного выше:

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"

Это следует за конвенциями, которые мы знаем и любим.

Без this

Довольно легко понять, как сделать "конструкторы", которые не следуют этому шаблону, но мы теряем использование prototype, если я чего-то не упускаю и должен включать все методы объекта в наш конструктор, который мы хотим, чтобы все наши Peep делились.

/*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();

Итак, есть альтернативная альтернатива. Это делает, кроме return peep; и внутреннего определения методов, делает JavaScript действительным, как многие OO-первые языки, с которыми вы могли столкнуться. По крайней мере, это не так.

Отсутствие доступа к prototype не является ужасным; это действительно плохие новости, чтобы изменить prototype где-то, что не так, рядом с конструктором, так как ваш код будет идти спагетти. "У некоторых Person есть sayGoodbye(), а некоторые нет, в зависимости от того, исправим ли мы прототип в момент их построения". Это ужасно. Таким образом, это альтернативное соглашение имеет свои преимущества.

Вы все же можете, конечно, добавить функции к одному экземпляру Peep позже, но я не уверен, как вы получите доступ к firstName без использования this, поэтому, возможно, он хочет, чтобы мы прекратили воспроизведение объекты после строительства.

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

(я имею в виду, мы также могли бы еще обезьян-патч Peep изменить его в середине процесса, но это ужасное, глупое программирование. Обычно.)

Наследование (без this)

И наследование достаточно просто, я думаю.

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: См. также этот ответ, где позже выяснилось, что Крокфорд предложил средство создания OO javascript. Я пытаюсь убедить этого парня удалить этот Q & A и переместить A здесь. Если он этого не сделает, я, вероятно, добавлю его материал и сообщество wiki сюда.


РЕДАКТИРОВАТЬ: Смотрите это из MDN, почему он работает:

(Обычно конструкторы не возвращают значения, но они могут выбрать поэтому, если они хотят переопределить процесс создания обычного объекта.)

Ответ 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;

}());

Ответ 4

В строгом режиме this ссылка установлена ​​на undefined.

Таким образом, оба ваших утверждения вызовут свойства чтения объекта undefined, что приведет к исключению.

Как мне исправить мой код?

Удалите обе строки.

UPD: то, что я заявляю выше, - это то, как JSLint обрабатывает ваш код, а не как я это делаю.

Ответ 5

JSLint говорит: Неожиданно 'this'. Как мне изменить код?

Нет необходимости исправлять код.

На странице справки для JSLint в разделе для директивы /*jslint*/," < в таблицу доступных опций добавлен параметр strong > Tolerate this:

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

Итак, чтобы подавить жалобы на использование this, поместите следующую директиву в исходный файл перед первым утверждением:

/*jslint
    this
*/

(Обратите внимание, что другие параметры /*jslint*/ могут следовать за this, вставив запятую между опциями. См. справочную страницу JSLint.)

Также см. ответ @Oriol, чтобы включить параметр "Tolerate this" в пользовательском интерфейсе для JSLint.