Как предотвратить появление предупреждения «Свойство MyProp1 никогда не определялось в MyObject»?

У меня есть HTML-код, содержащий строку JSON. В обратном вызове on DOM ready у меня есть что-то вроде этого:

MyObject = JSON.parse($('#TheJsonString').html());

Позже в моем коде я пишу что-то такое:

var SomeVar = MyObject.MyProp1;

И затем, когда я запускаю код через компилятор закрытия Google, я получаю предупреждение

Свойство MyProp1 никогда не определялось в MyObject.

Как должен быть написан код, чтобы он не выдавал предупреждение?


person frenchie    schedule 05.03.2012    source источник


Ответы (5)


Самый простой способ удалить предупреждение — определить структуру JSON. Это можно сделать с помощью тега @type:

/** @type {{MyProp1:string}} */

Где MyProp1 — имя свойства, а string — тип.

Компилятор Google Closure переименует переменную. Если вы этого не хотите, вам нужно использовать кавычки + скобки вместо точечной записи:

MyObject['MyProp1']

Пример: вставьте следующее в компилятор закрытия:

// ==ClosureCompiler==
// @compilation_level ADVANCED_OPTIMIZATIONS
// ==/ClosureCompiler==

var MyObject;
function x() { // Magic happens at the next line
    /** @type {{MyProp1:string}}*/
    MyObject = JSON.parse(prompt(''));
}
function afterX() {
    var SomeVar = MyObject.MyProp1;
    alert(SomeVar);
}
x();
afterX();

Вывод:

var a;a=JSON.parse(prompt(""));alert(a.a);
person Rob W    schedule 05.03.2012
comment
Хорошо, спасибо, теперь это работает! В целом, лучше ли использовать точечную нотацию или скобочную нотацию или это просто вопрос стиля/предпочтения? Кроме того, я планирую использовать компилятор Google, а затем переобфусцировать скомпилированный код в jscrambler. Я знаю, что это не помешает обратному инжинирингу, но я просто хочу выиграть время. Будет ли работать двойная обфускация? - person frenchie; 05.03.2012
comment
@frenchie Как правило, запись скобок / точек является вопросом предпочтения. Однако в компиляторе Closure необходимо использовать скобки, чтобы сохранить имена. Однако в скомпилированном выводе используется точечная нотация. И да, двойная обфускация действительно усложнит обратный инжиниринг. Убедитесь, что вы проверяете производительность кода до/после обфускации. - person Rob W; 05.03.2012

Чтобы подавить это предупреждение для конкретной функции, вы можете использовать аннотацию @suppress:

/**
 * @suppress {missingProperties}
 */
function useJsonObject() { ... }

Чтобы отключить это предупреждение глобально, используйте флаг компилятора jscomp_off, чтобы отключить missingProperties класс предупреждений.

person bzlm    schedule 03.11.2013

Попробуйте получить доступ к свойству таким образом:

var SomeVar = MyObject['MyProp1'];
person lennel    schedule 05.03.2012

Вместо того, чтобы помещать содержимое JSON в объект #TheJsonString в виде HTML, вы должны поместить его на свою страницу в виде фактического javascript. Если сервер генерирует контент на странице, то нет причин, по которым серверу нужно генерировать HTML, который вы затем анализируете. Сервер может просто создать переменную javascript внутри тега script и поместить в нее фактическую структуру данных javascript.

JSON.parse() очень полезен для анализа ответов ajax, но на самом деле он не нужен, когда сервер может просто поместить готовый javascript прямо на сгенерированную страницу.

person jfriend00    schedule 05.03.2012
comment
Я помещаю строки json в литерал, поэтому в браузере они находятся внутри div. Asp.net - person frenchie; 05.03.2012
comment
@frenchie - я знаю, что вы помещаете их в div. Я спрашиваю, почему вы это делаете, когда вы можете просто поместить их прямо в переменную javascript. Нет причин помещать их в строковую форму на вашей странице. Это также решит проблему закрытия Google, потому что они будут определены в реальном javascript. - person jfriend00; 05.03.2012
comment
На самом деле есть 12 строк json, и литералы вводятся из кода мастер-страницы. Я не хочу, чтобы в моем файле .master был уродливый оператор eval сервера. И это все равно не решит проблему с компилятором, поскольку у меня нет операторов json; они оцениваются во время выполнения. - person frenchie; 05.03.2012
comment
@frenchie - я понятия не имею, что уродливого в том, что сервер генерирует структуры данных javascript на странице, которую он обслуживает. Это делается все время. Оператор eval не требуется. Вы используете неортодоксальный метод размещения данных на своей странице. Ваша жизнь была бы намного проще, если бы вы использовали лучший способ размещения данных на странице, но, похоже, вы боретесь с этим понятием, и мы действительно не знаем, почему. - person jfriend00; 05.03.2012
comment
Но я использую компилятор Google, где копирую и вставляю свой javascript и хочу удалить предупреждения (к вашему сведению, 837 предупреждений). Операторы json доступны только во время выполнения, поэтому, даже если я помещу операторы json как eval в файл aspx, у меня все равно появится предупреждение в компиляторе Google, потому что у меня их нет, когда я компилирую код! Чем больше я об этом думаю, тем больше я думаю, что решение находится в прототипном наследовании, где мне нужно создать объект и выполнить синтаксический анализ json или что-то в этом роде. - person frenchie; 05.03.2012

<!DOCTYPE html>
<html>
<head></head>
<body>
<div id="TheJsonString">
    {"bindings": "hr", "method":"asd"}
</div>
<script type="text/javascript" src="jquery-1.7.1.min.js"></script>
<script type="text/javascript">
    var MyObject = JSON.parse($('#TheJsonString').html());

    var SomeVar = MyObject.bindings;

    console.log(SomeVar);
</script>
</body>
</html>

Я тестировал это так, но он работает нормально без каких-либо предупреждений.

person Hengfeng Li    schedule 05.03.2012
comment
Проблема в том, что у меня нет строк json, когда я вставляю свой код в компилятор Google: json генерируется во время выполнения и отличается для каждого пользователя. Чем больше я об этом думаю, тем больше я думаю, что решение находится в прототипном наследовании, где мне нужно создать объект и выполнить синтаксический анализ json или что-то в этом роде. - person frenchie; 05.03.2012