Ответы пользователя по тегу JavaScript
  • Как расшифровать этот скрипт?

    Посмотреть, где используется содержимое eval. Можете открыть WebStorm и нажать "find usages". Если совсем никак не найти - сделать его геттером и поставить внутри breakpoint (бабель тут может справедливо возмутиться и послать вас читать доку - билдим оригинальный код, находим этот кусок в сбилдженном под es3 коде и уже там меняем значение на аксессор)

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

    Еще можно поискать по "eval", "new Function" и других способах рантайм-запуска кода - в эти функции передается уже расшифрованный код.
    Ответ написан
    2 комментария
  • Как разрешить ввод только для определенного времени?

    Судя по документации там есть "validator" (ищите по этому слову). Вам подойдет такой регексп:

    var re = /((1[0-9]|2[0-1]):([0-5][0-9])|22:00)/;
    [
    "09:59", // false
    "10:00", // true
    "21:59", // true
    "22:00", // true
    "22:01"  // false
    ].map(a => !!a.match(re))


    Можно ещё написать функцию - её будет проще настраивать:

    var minTime = 10 * 60 + 0; // часы в минутах + минуты
    var maxTime = 22 * 60 + 0;
    
    validator = data => {
      var parts = data.split(':');
    
      if (parts != 2) return false;
    
      var hours = parseInt(parts[0], 10);
      var minut = parseInt(parts[1], 10);
    
      var time = hours * 60 + minut;
    
      return time >= minTime && time <= maxTime;
    }


    Я не проверял, но идею вы поняли.
    Ответ написан
    Комментировать
  • Что скажете о таком применении Object.defineProperty в javascript?

    В реальном коде может сесть производительность очень сильно. Решаю использованием TypeScript. Зачем придумывать костыль, если есть подходящий инструмент?
    Ответ написан
    Комментировать
  • Если куки отключены, то использовать localStorage?

    Если куки отключены, то, возможно, человек не хочет, чтобы его запоминали. Стоит полагаться на сессию - то есть пусть данные будут в памяти вкладки пока она открыта и очищаются, когда закрывается. Ему придется перелогиниваться, но это выбор пользователя.
    Ответ написан
    Комментировать
  • Как правильно писать на ООП?

    TLDR: Все зависит от ситуации. Набивайте свои шишки и наберетесь опыта.

    Самый главный вопрос - зачем вы вообще хотите использовать ООП, насколько сложный и "правильный", какие цели хотите достичь.

    Когда разрабатываете библиотеку, то есть несколько важных целей (независимо от парадигмы):
    1. Апи должнен быть простым, понятным и самодокументируемым
    2. Вы должны иметь возможность развивать библиотеку и не нарушать при этом уже используемый пользователями API

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

    Еще одна важная причина - это обучение. Вы хотите попробовать и набить своих шишек. Тогда пользуйтесь и вставляйте все самые стремные подходы, о которых только сможете прочитать.

    Не слушайте евангелистов ФП - сейчас в JS функциональностью модно прикрывать говнокод.

    Так же не слушайте тех, которые на каждом углу кричат "Composition over inheritance", "Banana monkey problem" другие страшные термины. В своем религиозном угаре они забывают, что все эти принципы рекомендации для определенных ситуаций. Да, иногда (в большинстве случаев на самом деле) композиция значительно лучше наследования, очень часто стыкаешься с ситуацией, что наследование применено не в тему и из-за этого усложнено развитие. Но иногда наследование - правильный путь и пока сами не набъете шишек - будет крайне сложно понять разницу. Помогает принцип is-a/has-a. И я видел код отличных программистов, где наследование было применено так, что значительно разгрузило API и упростило код. Не зацикливайтесь из-за религиозных фанатиков.

    Множество паттернов ООП придумано, чтобы изолировать функциональность и облегчить её тестирование, но каждый паттерн - лишь рекомендация.

    Получился класс, в котором есть эти 4 метода. Все эти методы я вызываю в конструкторе. То есть получается, я процедурный стиль просто запихнул в класс.
    Да, вы правы, но это не обязательно плохо, идеальный код никто и никогда не пишет. Но посмотрите какая проблема - у вас и парсятся входные данные и делается запрос и делается обработатка. Можно ли изменить парсинг входных данных, оставив другие шаги? Можно ли не отправлять запрос? Как вы будете тестировать эту функцию, если она обязательно выполняет запрос и нету никакого способа не дать ей отправить этот запрос?

    С другой стороны, будут ли довольны пользователи вашей библиотеки, если им придется инджектить все зависимости? Даже если вы сделаете вызов по-умолчанию, то чтобы изменить одну зависимость - придется изменять все. Я приведу пример, где использование наследования даст необходимую вам гибкость и API для пользователя не разбухнет, зато он сможет изменить каждый шаг. Вот:

    interface IPipeline {
    	ResultView Render (RawData rawData);
    }
    
    class Pipeline : IPipeline {
    	protected virtual ParsedRawData ParseRawData(RawData rawData) {
    		return new DataParser(rawData).GetParsedData();
    	}
    	
    	protected virtual ActualData GetActualData (ParsedRawData rawData) {
    		return new HttpRequest(rawData.src);
    	}
    	
    	protected virtual ResultState GetResultState (RawData rawData, ActualData actualData) {
    		return new StateCounter().Count(rawData, actualData);
    	}
    	
    	public virtual ResultView Render (RawData rawData) {
    		var parsed = ParseRawData(rawData);
    		
    		if (parsed.IsValid) {
    			var actual = GetActualData(rawData);
    			var state = GetResultState(rawData, response);
    			return new Renderer().Render(state);
    		} else {
    			throw new Exception("Raw data is invalid");
    		}
    	}
    }


    Для пользователя это выглядит довольно симпатично:
    new Pipeline().Render(rawData);

    Если же ему необходимо брать из другого источника данные - он легко это исправит:
    class MyPipeline : Pipeline {
    	protected virtual ActualData GetActualData (ParsedRawData rawData) {
    		return new LocalStorageRequest(rawData.src);
    	}
    }
    
    new MyPipeline().Render(rawData);


    Конечно, это же можно сделать при помощи композиции. Ну давайте поиграем на основе паттерна Билдер:

    interface IPipeline {
    	ResultView Render (RawData rawData);
    }
    
    class Pipeline : IPipeline {
    	private IRawDataParser rawDataParser;
    	private IActualDataReciever actualDataReciever
    	private IResultStateCounter resultStateCounter;
    	private IRenderer renderer;
    	
    	public GetRawDataParser () {
    		return rawDataParser ?? new RawDataParser();
    	}
    	public GetActualDataReciever () {
    		return rawDataParser ?? new ActualDataReciever();
    	}
    	public Pipeline GetActualDataReciever (actualDataReciever) {
    		actualDataReciever = actualDataReciever;
    		return this;
    	}
    	
    	// ...
    	private GetRenderer () {
    		return renderer ?? new Renderer();
    	}
    	
    	
    	public virtual ResultView Render (RawData rawData) {
    		
    		var parsed = GetRawDataParser().Parse(rawData);
    		
    		if (parsed.IsValid) {
    			var actual = GetActualDataReciever().Get(rawData);
    			// ...
    			return GetRenderer().Render(state);
    		} else {
    			throw new Exception("Raw data is invalid");
    		}
    	}
    }


    Использование по-умолчанию всё то же:
    new Pipeline().Render(rawData);

    А изменить пользователь их может так:
    new Pipeline()
    	.SetActualDataReciever(new MyDataReciever())
    	.Render(rawData);


    Тут впору уже и о DI Container'ах почитать.

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

    В качестве вывода повторю самое главное - просто тренируйтесь, пишите и набивайте шишки, читайте о паттернах и приемах, но помните, что это рекомендации, а не законы и старайтесь думать и анализировать, что пишете и читаете.
    Ответ написан
    Комментировать
  • Как правильно организовать структуру класса?

    Если что-то попроще, но при этом более-менее ООПшное, то можно как-то так:

    class Plugin {
    
    	constructor (rawUrl, rawName) {
    		this.url = new UrlParser(rawUrl);
    		this.name = new NameParser(rawName);
    	}
    
    	doSomething () {
    		// code
    	}
    }
    
    function userCode() {
        new Plugin("example.com", "FooBar").doSomething()
    }


    Если хотите побольше DI и всего такого, но при этом не потерять лёгкость использования, то можно так:

    class Plugin {
    
    	constructor (urlParser, nameParser) {
    		this.url = urlParser;
    		this.name = nameParser;
    	}
    	
    	doSomething () {
    		// code
    	}
    
    }
    
    Plugin.init = function (url, name) {
    	return new Plugin(
    		new UrlParser(url),
    		new NameParser(name)
    	);
    }
    
    function userCode() {
    	Plugin.init("example.com", "FooBar").doSomething()
    }


    UrlParser и NameParser - это классы, которые парсят всё необходимое, а потом внутри имеют свойства для обращения к ним.

    class UrlParser {
    
    	constructor (urlString) {
    		var result = this.matchUrlStrign(urlString)
    		
    		this.anchor = result[0];
    		this.path   = result[1];
    		// etc
    	}
    }


    Соответственно, в плагине используете как-то так:
    this.url.anchor
    Ответ написан
    3 комментария
  • Что делает этот участок кода (JS)?

    Вопрос далеко не простой. Если прогнать через jsbeautifier.org и убрать шум, то останется такой код:

    (function(){
    
    function ExitApi () {};
      
    ExitApi.prototype.exit = function() {
       console.log("Exit API: Close requested.")
    };
    
    ExitApi.prototype.delayCloseButton = function(e) {
       if (e < 5) e = 5;
    
       console.log("Exit API: Close Button will not appear for " + e + " seconds.")
    };
    
    var b = new ExitApi(),
       method = "ExitApi",
       _this = this;
    
    if (!method in _this && _this.execScript) {
      _this.execScript("var " + method);
    }
    
    if (!_this[method] || _this[method] === Object.prototype[method]) _this[method] = ExitApi;
    
    }).call(this);


    _this в данном случае скорее всего объект window или аналог.
    Если оставить только суть, то она приблизительно такова:

    (function(){
    
    function Foo () {};
      
    Foo.prototype.exit = function() {
       console.log("Exit API: Close requested.")
    };
    
    Foo.prototype.delayCloseButton = function(e) {
       if (e < 5) e = 5;
    
       console.log("Exit API: Close Button will not appear for " + e + " seconds.")
    };
    
    this.ExitApi = new Foo();
    
    }).call(this);


    То есть он создает инстанс, у которого есть два метода, которые исключительно пишут в консоль и не выполняют никакой задачи. Смысла в этом коде пока нет, выглядит словно старались запутать специально.
    Ответ написан
    4 комментария
  • Как при смене картинки фона сохранить анимацию?

    Увы, если вы хотите показывать две картинки, одна поверх другой - вам необходимо две html-ноды.
    Ответ написан
    Комментировать
  • Как побороть вагон if'ов?

    Если не нравится идея с циклом по какой-то причине (например, хочется явно указать список параметров) - можно создать анонимную функцию

    function saveParam (title) {
      var param = req.body.queryResult.parameters[title];
      if (param) {
        transportationData[title] = param;
      }
    }
    
    saveParam('places-count');
    saveParam('contact-person');
    saveParam('stowing-type');
    saveParam('cargo-type');
    Ответ написан
    2 комментария
  • Скрипт счетчика типа 0.00000,как сделать что бы при регистрации аккаунта?

    Тут есть примеры, с которых следует начать, чтобы найти решение:
    https://www.electrictoolbox.com/using-settimeout-j...

    Тут, в первом ответе, посовременнее и попроще:
    https://stackoverflow.com/questions/6893130/how-to...
    Ответ написан
    Комментировать
  • Как сделать выталкивающий сайдбар?

    display: flex для контейнера, flex-grow: 1 для правого блока и изменяете ширину у левого. Все очень просто. Рекомендую внимательно почитать про css flex =)
    html, body {
      width: 100%;
      height: 100%;
    }
    #container {
      display: flex;
      width: 100%;
      height: 100%;
    }
    #left {
      transition: width 0.3s ease-in-out;
      background: #fcc;
      width: 40px;
    }
    #left:hover {
      width:200px;
    }
    #right {
      background: #cfc;
      flex-grow: 1;
    }
    Ответ написан
    Комментировать
  • Плавное рисование линии в canvas?

    Смотрите, как сделано в Гимпе:
    b600e3f6abf9762bab4e3290dc5a68a5.png

    Событие mousemove может иметь разный отступ, вам главное построить линию и расположить по этой линии равномерно точки.

    Ну и вот как референс: libcanvas.github.io/archive/5iton
    Ответ написан
    Комментировать
  • Libcanvas сейчас актуален?

    Смотря что вы имеете ввиду под словом "актуален". Актуален как минимум тем, что до сих пор нету более мощного 2d canvas фреймворка)
    Ответ написан
  • Нетормозящий «визуализатор кода матрицы» на js?

    У вас прикольно получилось, но сильно уж быстро.
    Ответ написан
    Комментировать
  • Нетормозящий «визуализатор кода матрицы» на js?

    Самый простой и быстрый способ — это Canvas.
    Принцип простой — у нас нет всех букв как объектов.
    Каждый «тик» мы отрисовываем только новые буквы, после того как весь холст заливаем полупрозрачным фоном.
    Тогда весь экран у нас будет словно «угасать». И вся производительность будет упираться только в возможность компа залить весь холст одним цветом.
    Единственная проблема — остаются лёгкие следы, но это, имхо, даже хорошо — именно так ведь оно на лучевых мониторах и должно быть?
    Ответ написан
    2 комментария
  • Как избавиться от белого фона под анимацией в Libcanvas?

    Добрый день) Проблема скорее всего в том, что по-умолчанию очистка идёт через «boundingRectangle» фигуры.
    Попробуйте добавить в ваш класс такой код и скажите, исправился ли баг?
    clearPrevious: function (ctx) {
        ctx.clear( this.shape );
    }
    


    Как альтернатива — заменить boundingShape:
    get currentBoundingShape () {
      return this.shape;
    }
    


    По идее любой из этих способов должен помочь.

    С точки зрения производительности вместо projectiveImage, который реализуется через множество трансформаций — лучше использовать одну трансформацию. Например, как в топике "Canvas-трансформации доступным языком".

    А ещё лучше — загружать уже транформированные картинки (так и дизайнеру легче, имхо). Пример из Civilization3:
    Ответ написан
    2 комментария
  • Что означает код?

    Обратите внимание на Урл:
    http://marijnhaverbeke.nl/js1k

    Это фича нужна для соревнований очень маленького кода. В реальных приложениях, естественно, такую хрень использовать не стоит.
    Ответ написан
    Комментировать
  • Как подружить .toLowerCase() и null?

    var player = prompt('SoMe DaTa') || ''; 
    console.log( player.toLowerCase() ); 
    Ответ написан
    Комментировать