Является ли jQuery.extend защищенным от циклических ссылок? - PullRequest
1 голос
/ 02 декабря 2011

Безопасно ли jQuery.extend от circular reference?

Как можно избежать циклической ссылки в Javascript (при клонировании или рекурсивной проверке)? Недостаточно просто проверить наличие текущей цели в списке ее свойств, поскольку это может относиться к какому-либо внешнему объекту.

Один из вариантов - сохранить еще один список всех objects, выбранных до сих пор. но увеличит ли это потребление памяти и попросит ли остановить скрипт?

и я не хочу перемещать операцию клонирования в рабочем потоке.

1 Ответ

0 голосов
/ 14 октября 2018

Старый вопрос, но я искал это сегодня - ответ: нет.

https://api.jquery.com/jquery.extend/

В глубоком смысле Объект и Массив расширяются, но объектоболочки для примитивных типов, таких как String, Boolean и Number, не являются. Глубокое расширение циклической структуры данных приведет к ошибке .

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

Документы lodash не очень понятны, но _.cloneDeep поддерживает клонирование циклических ссылок.

https://lodash.com/docs/4.17.10#cloneDeep

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

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

public static DeepClone(source: any, stack: any[] = null): any
{
    if (!source)
    {
        return source;
    }

    var result;

    result = Array.isArray(source) ? [] : {};

    for (var k in source)
    {
        var v = source[k];
        if (typeof v === "object") 
        {
            stack = stack || [];

            // Just ignore circular references? Or, to be clever, maintain a 
            // dictionary of object references from the original graph linked to
            // the new objects in the cloned graph, to preserve the full graph.
            if (stack.indexOf(source) >= 0)
            {
                return null;
            }

            stack.push(source);

            result[k] = this.DeepClone(v, stack);

            stack.pop();
        }
        else
        {
            result[k] = v;
        }
    }

    return result;
}
...