2011-06-10 5 views
52

удается получить следующий пройти JSLint/jshintСтрогого Нарушение использование этого ключевого слова и выявление шаблон модуля

/*jshint strict: true */ 
var myModule = (function() { 
    "use strict"; 

    var privVar = true, 
     pubVar = false; 

    function privFn() { 
     return this.test; // -> Strict violation. 
    } 

    function pubFn() { 
     this.test = 'public'; // -> Strict violation. 
     privFn.call(this); // -> Strict violation. 
    } 

    return { 
     pubVar: pubVar, 
     pubFn: pubFn 
    }; 

}()); 

myModule.pubFn(); 

Я понимаю, что это было вызвано использованием this в объявлении функции, но я читал что-то Крокфорд написал и он сказал, что нарушение предназначено для предотвращения глобального переменного загрязнения - но единственной глобальной переменной здесь является тот, который я явно определяю ... myModule. Все остальное хранится в непосредственной функциональной области, и я должен иметь возможность использовать this для ссылки на модуль.

Любые идеи, как я могу получить этот шаблон для прохождения?

Update: если я использую выражение функции вместо декларации, это похоже на работу, т.е.

var pubFn = function() { ... 

Я не поклонник этого формата, хотя, предпочитают иметь имя функции и именованные параметры ближе, и декларация выглядит/чувствует себя чище. Я, честно говоря, не понимаю, почему это бросает нарушение - нет причин для этого в этом шаблоне.

+1

Звучит как один из тех случаев, когда вы можете просто игнорировать жалобы jslint. Как в стороне, как работает 'pubVar' при доступе как' myModule.pubVar'? Это действительно не дает код за пределами модели доступа к переменной в модуле? Я бы подумал, что если вы хотите получить/установить текущее значение переменной модуля, вам понадобятся функции getter и setter. – nnnnnn

+0

Ты прав, я подумал, что это выглядит немного смешно. Если вы попробовали 'myModule.pubVar = true', вы просто переписывали бы свойство объекта. Внутренний 'pubVar' останется как' false' –

+2

Re ваше обновление: я предпочитаю 'var foo = function() {}' to 'function foo() {}', потому что это помогает избежать проблем с хостингом. Кроме того, мне нравится, что он делает * функции, которые больше похожи на другие вары, поскольку в JS нет никакой разницы между функцией или любым другим значением - они являются первоклассными. Личные предпочтения, я знаю, но я думал, что выброшу некоторые мысли. – JAAulde

ответ

79

JSHint имеет option под названием validthis, который:

[...] подавляет предупреждения о возможных жестких нарушений, когда код работает в строгом режиме и вы используете this в не-конструктор функции [. ..], когда вы уверены, что ваше использование this действует в строгом режиме.

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

function privFn() { 
    /*jshint validthis: true */ 
    return this.test; // -> No Strict violation! 
} 

function pubFn() { 
    /*jshint validthis: true */ 
    this.test = 'public'; // -> No Strict violation! 
    privFn.call(this); // -> No Strict violation! 
} 

Казалось бы, как боль, чтобы указать, что в каждой функции, где это применяется, но если вы установите опцию в верхней части своей функции модуля, вы можете скрыть подлинных нарушений строгого режима от вас самих.

4

К сожалению, это предполагаемая ошибка для этой установки, поскольку jslint/jshint не знает, что функция, объявленная в глобальном контексте, должна быть позже использована как метод объекта.

+1

Но эти функции не объявлены в глобальном коде. Они вложены внутри выражения функции (которое вы используете для упаковки кода вашего модуля). –

23

Реальная проблема здесь состоит в том, что, если вы звоните privFn внутри контекста в модуля (внутри IIFE), this будет undefined, когда в строгом режиме; window если нет в строгом режиме. Увы, функция не сработает, если вызвана из IIFE.

Это потому, что функции не имеют владельца (объект), когда вызывается из внутри IIFE, тогда как возвращаемого объект модуля является владельцем функций, когда они вызываются из вне контекста IIFE, например, this === myModule при вызове myModule.pubFn().

Как строгий режим, так и JSHint/JSLint пытаются помочь вам, и вы никогда не должны просто игнорировать ошибки/предупреждения, созданные ими, но вместо этого выяснить, почему они предупреждают вас.

Если вы на 100% уверены, что privFn, pubFn и т. Д. Не будут вызываться нигде, кроме внешнего модуля, просто введите комментарий /*jshint validthis: true */ в любые функции, которые генерируют предупреждение. В качестве альтернативы, один комментарий в IIFE не позволит JSHint генерировать эту ошибку для любой функции внутри модуля.


Одна из многих возможных решений

Магазин объем thisself в данном примере) явно относятся к модулю. Это покажет и обеспечит ваши намерения.

/*jshint strict: true */ 
var myModule = (function() { 
    "use strict"; 

    var privVar = true, 
     pubVar = false, 
     self = this; 

    function privFn() { 
     return self.test; 
    } 

    function pubFn() { 
     self.test = 'public'; 
     //privFn.call(this); // Will have no effect, as `privFn` does not reference `this` 
     privFn(); 
    } 

    return { 
     pubVar: pubVar, 
     pubFn: pubFn 
    }; 
}()); 

myModule.pubFn(); 
+1

Полностью согласен с вашим ответом, просто хочу добавить еще одну вещь. Если вы используете «это» внутри функции, начинающейся с заглавной буквы, это не даст вам никаких предупреждений. Поскольку функция начинается с заглавной буквы, вы собираетесь использовать ее как конструктор с новым ключевым словом. Вы разрешили использовать это в конструкторе даже в строгом режиме :) – Tarun

+0

У меня такая же проблема для обратного вызова массива (обратного вызова, контекста), который используется в разных местах. «this» имеет в этом случае совершенно правильное использование, поскольку оно обеспечивается вторым аргументом map(). Это, кстати, справедливо и для других методов массива, таких как some(), every(), reduce(), reduceRight(). Я думаю, что JSHint & JSLint может проверить, что такая функция всегда используется как обратный вызов метода массива с предоставленным контекстом –

 Смежные вопросы

  • Нет связанных вопросов^_^