Ответы пользователя по тегу JavaScript
  • Как обратиться к аргументам конструктора класса?

    rockon404
    @rockon404
    Frontend Developer
    Обратиться к аргументам конструктора из методов класса нельзя, но можно сделать их в конструкторе полями класса:
    class Counter {
      constructor(value) {
        this.value = value || 0;  // определяем поле класса value со значением аргумента value
      }                           // либо 0 если аргумент не будет передан
      
      getVaue() {
        return this.value;
      }
    
      increment() {
        return ++this.value;
      }
    
      decrement() {
        return --this.value;
      }
    }


    Связанный список рекомендую попробовать написать своими силами. Если не хотите сами, то смотрите под спойлером.
    spoiler
    class Node {
      constructor(data) {
        this.data = data;
        this.next = null;
      }
    }
    
    class LinkedList {
      constructor() {
        this.head = null;
        this.length = 0;
        
        Array.prototype.forEach.call(arguments, data => this.add(data));
      }
    
      add(data) {
        const nodeToAdd = new Node(data);
        let nodeToCheck = this.head;
    
        if(!nodeToCheck) {
          this.head = nodeToAdd;
          this.length++;
          return nodeToAdd;
        }
    
        while(nodeToCheck.next) {
          nodeToCheck = nodeToCheck.next;
        }
        
        nodeToCheck.next = nodeToAdd;
        this.length++;
    
        return nodeToAdd;
      }
    
      get(num) {
        const nodeToCheck = this.head;
        let count = 0;
      
        if(num > this.length) {
          return "Doesn't Exist!"
        }
    
        while(count < num) {
          nodeToCheck = nodeToCheck.next;
          count++;
        }
    
        return nodeToCheck;
      }
    
      remove(num) {
        let nodeToCheck = this.head;
        let length = this.length;
        let count = 0;
        let prevNode = null;
         
         if(num > length) {
           return "Doesn't Exist!"
         }
       
         if(num === 0) {
           this.head = nodeToCheck.next;
           this.length--;
           return this.head;
         }
         
         while(count < num) {
           prevNode = nodeToCheck;
           nodeToCheck = nodeToCheck.next;
           count++;
         }
         
         prevNode.next = nodeToCheck.next;
         nodeToCheck = null;
         this.length--;
          
         return this.head;
      }
    }
    Ответ написан
  • Как задать стиль к символам внутри элемента?

    rockon404
    @rockon404
    Frontend Developer
    Можно так.
    Eще вариант с обработкой строки за один проход.
    Ответ написан
    1 комментарий
  • Как проверить скорость выполнения кода?

    rockon404
    @rockon404
    Frontend Developer
    Если интересует конкретный узел, можно использовать performance.now:
    var t0 = performance.now();
    doSomething();
    var t1 = performance.now();
    console.log("Call to doSomething took " + (t1 - t0) + " milliseconds.");

    Для асинхронных задач:
    var t0 = performance.now();
    var t1;
    doSomething().then(result => {
      t1 = performance.now();
      console.log("Call to doSomething took " + (t1 - t0) + " milliseconds.");
    });
    Ответ написан
    1 комментарий
  • Что значит эта строка кода?

    rockon404
    @rockon404
    Frontend Developer
    Опционально добавляется регулярное выражение в query string запроса, доступное по ключу description2__regex.
    Если вопрос только по синтаксису, то испльзуются шаблонные строки.
    Ответ написан
    2 комментария
  • Async await изнутри - как устроено?

    rockon404
    @rockon404
    Frontend Developer
    async/await лишь удобная обертка над промисами. Подробней о async/await можете почитать тут.
    1000 выводится раньше потому, что функция, благодаря использованию ключевого слова await, дожидается ответа от Promise возвращаемого функцией sleep и только после этого продолжает выполнение.
    В V8 async/await так же как и Promise реализованы на JavaScript. С реализацией можно ознакомиться тут.
    Как можно видеть реализована она на генераторах.

    Аналог вашего примера без использования async/await:
    const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
    
    (() => {
        setTimeout(() => console.log('1000'), 1000);
        sleep(5000).then(() => {
          console.log('5');
        });
    })();

    Так же async function всегда возвращает Promise, даже если вы ничего не возвращаете.
    Ответ написан
    2 комментария
  • Почему не работает массив javascript?

    rockon404
    @rockon404
    Frontend Developer
    Передавайте имена файлов строками:
    var variants = {
      '66': {'images_names':['4984534-1_1.jpg', '4984534-2_1.jpg'], 'v_id':[66]},
      '208': {'images_names':['4984534-3_1.jpg', '4984534-4_1.jpg'], 'v_id':[208]},
     };
    Ответ написан
    1 комментарий
  • Почему use strict не работает в setTimeout?

    rockon404
    @rockon404
    Frontend Developer
    Потому что setTimeout вызывает колбек в контексте window.
    Что-то вроде:
    func.apply(window);

    Стоит добавить, что при выполнении скрипта воркером this в колбеке setTimeout будет ссылаться на WorkerGlobalScope.
    Ответ написан
    6 комментариев
  • Почему не могу использовать await в if блоке?

    rockon404
    @rockon404 Куратор тега React
    Frontend Developer
    Дело не в условном операторе, а в том, что у вас колбек у map не асинхронная функция и в ней нельзя использовать ключевое слово await. Исправить можно так:
    export const renderNotes = (user , users) => dispatch => {
      Object.keys(users).forEach(async element => {
        if (user === users[element].login) {
          const elements = await fire.database().ref('users/' + element + '/notes/'); 
    
          return dispatch({
            type: RENDER_NOTES,
            payload: elements,
          });
        }
      })
    };


    В случае когда надо лишь пройтись по элементам массива, использовать метод map неправильно, для таких случаев есть метод forEach.

    map следует использовать тогда, когда на основе исходного массива, надо получить новый массив элементов, преобразованных по определенному алгоритму:
    const srcArray = [ 0.134555, 0.294587, 0.570858];
    
    const mappedArray = srcArray.map(el => (el * 100).toFixed(1) + '%');
    
    console.log(mappedArray);
    
    // => ["13.5%", "29.5%", "57.1%"]
    Ответ написан
    Комментировать
  • Почему в этой операции javascript выводится 16?

    rockon404
    @rockon404
    Frontend Developer
    Тут надо понимать, что в локальной области видимости функций plus1 и square x это значение преданного аргумента, а не глобальной переменной x.
    var x = 2, y = 3;
    function plus1(x) {
    return x + 1;  // тут x это значение которое вы передали при вызове аргументом
    }
    plus1(y)
    var square = function(x) {
    return x * x;  // тут тоже
    };
    square(plus1(y))


    Разберем выражение:
    square(plus1(y))

    У вас y = 3.

    Получается:
    square(plus1(3));

    На шаге plus1(3):
    function plus1(3) {
    return 3 + 1;
    }

    На выходе из первой функции получаем 4

    Получается:
    square(4);

    на этом шаге поисходит следущее:
    function(4) {
    return 4 * 4;
    };


    На выходе получаем 16
    Ответ написан
    2 комментария
  • Как получить название переменной в массиве?

    rockon404
    @rockon404
    Frontend Developer
    Никак. В массиве их нет. Там внутри значения x и y на момент присваивания:
    {
      0: 10,
      1: 3,
      length: 2,
      __proto__: Array(0)
    }


    Вам для вашей задачи лучше складывать данные в объект:
    var x = 10;
    var y = 3;
    var obj = { x: x, y: y };
    
    var keys = Object.keys(obj);
    
    console.log(keys);
    // => [ 'x', 'y']
    Ответ написан
    Комментировать
  • Как контролировать число одновременных вызовов асинхронных функций в очереди?

    rockon404
    @rockon404
    Frontend Developer
    function Parallel(settings) {
      this.parallelJobs = settings.parallelJobs;
      this.results;
      this.tasks = [];
      this.onDone;
      this.index = 0;
      this.activeJobs = 0;
    };
    
    Parallel.prototype.start = function() {
      this.results = Array(this.tasks.length);
    
      for (var i = 0; i < Math.min(this.parallelJobs, this.tasks.length); i++) {
        this.next();
      }
    }
    
    Parallel.prototype.next = function(result) {
      var index = this.index;
      this.activeJobs++;
    
    
      this.tasks[this.index](function(result) {
        this.onResult(result, index);
      }.bind(this));
    
      this.index++;
    }
    
    Parallel.prototype.onResult = function(result, index) {
      this.results[index] = result;
      this.activeJobs--;
    
      if(this.tasks[this.index]) {
        this.next();
      } else if (this.activeJobs === 0) {
        this.onDone(this.results);
      }
    }
    
    Parallel.prototype.job = function (step) {
      this.tasks.push(step);
      return this;
    };
    
    Parallel.prototype.done = function (onDone) {
      this.onDone = onDone;
      this.start();
    };
    
    
    
    function asyncRequest1(result) {  
         setTimeout(result, 2000, 'data');
    }
    
    function asyncRequest2(result) {  
         setTimeout(result, 2000, 'data 2');
    }
    
    function asyncRequest3(result) {  
         setTimeout(result, 2000, 'data3');
    }
    
    function asynRequest4(result) {  
         setTimeout(result, 2000, 'data4');
    }
    
    
    
    var runner = new Parallel({
      parallelJobs: 2
    });
    
    runner.job(asyncRequest1)
          .job(asyncRequest2)
          .job(asyncRequest3)
          .job(asyncRequest4)
          .done(function (results) {
             console.log(results); 
          });
    Ответ написан
    3 комментария
  • В чем отличия между .className('') и .classList.add('')?

    rockon404
    @rockon404
    Frontend Developer
    Ответ написан
    Комментировать
  • Как правильно получить данные из объекта?

    rockon404
    @rockon404
    Frontend Developer
    const { data } = response.getuserworkersinfo;
    
    const targetUser = Object.values(data).find(({ user }) => user === 'ole.5');
    
    const { rate } = targetUser;


    Демо: https://jsfiddle.net/rockon404/s4gnjffz/
    Ответ написан
    Комментировать
  • С this или без?

    rockon404
    @rockon404 Куратор тега React
    Frontend Developer
    Потому что в первом случае вы обращаетесь к аргументу функции, а во втором к полю класса. Все по канонам JavaScript.
    Ответ написан
    Комментировать
  • Как правиль загрузить api в react?

    rockon404
    @rockon404 Куратор тега React
    Frontend Developer
    Для асинхронных запросов следует использовать redux middleware, например redux-thunk:
    import { fetchInitialDataApi } from './api';
    
    const FETCH_DATA_REQUEST = 'FETCH_DATA_REQUEST';
    const FETCH_DATA_SUCCESS = 'FETCH_DATA_SUCCESS';
    const FETCH_DATA_ERROR = 'FETCH_DATA_ERROR';
    
    const fetchDataRequest = () => ({ type:  FETCH_DATA_REQUEST });
    
    const fetchDataSuccess = data => ({
      type:  FETCH_DATA_SUCCES,
      payload: data,
    });
    
    const fetchDataError = error => ({
      type:  FETCH_DATA_ERROR,
      payload: error,
    });
    
    const fetchData => async dispatch => {
      try {
        dispatch(fetchDataRequest());
        const { data } = await fetchDataApi();
        dispatch(fetchDataSuccess(data));
      } catch error {
        dispatch(fetchDataError(error));
      }
    };
    
    const initialState = {
      data: {},
      isLoading: false,
      isError: false,
      error: null,
    };
    
    export default function(state = initialState, action) {
      const { type, payload } = action;
    
      switch (type) {
        case FETCH_DATA_REQUEST:
          return {
            ...state,
            isLoading: true,
            isError: false,
            error: null,
          };
        case FETCH__DATA_SUCCESS:
          return {
            ...state,
            data: payload,
            isLoading: false,
          };
        case FETCH_DATA_ERROR:
          return {
            ...state,
            isLoading: false,
            isError: true,
            error: payload,
          };
      default:
        return state;
      }
    }
    Ответ написан
    4 комментария
  • Как правильно дождаться результата асинхронных функций в цепочке вызовов?

    rockon404
    @rockon404
    Frontend Developer
    Можно так:
    class Foo {
      constructor() {
        this.queue = [];
      }
    
      tick(cb) {
        this.queue.push(cb);
        return this;
      }
    
      then(cb) {
        return this.queue.reduce((acc, fn) =>
          acc.then(fn), Promise.resolve()).then(cb);
      }
    }


    Вариант в прототипном стиле:
    function Foo() {
      this.queue = [];
    }
    
    Foo.prototype.tick = function(cb) {
      this.queue.push(cb);
      return this;
    }
    
    Foo.prototype.then = function(cb) {
      return this.queue.reduce(function(acc, fn) {
        return acc.then(fn);
      }, Promise.resolve()).then(cb);
    }


    Пример использования:
    const foo = new Foo();
    
    const task1 = () =>
      new Promise(resolve => {
        setTimeout(() => {
          console.log('task1');
          resolve('Done!');
        }, 1000);
      });
    
    const task2 = arg =>
      new Promise(resolve => {
        setTimeout(() => {
          console.log('task2');
          resolve(arg);
        }, 1000);
      });
    
    foo.tick(task1)
       .tick(task2)
       .then(console.log);
    
    /* result:
    
        task1
        task2
        Done!
    
    */
    Ответ написан
    Комментировать
  • Как правильно использовать react component?

    rockon404
    @rockon404 Куратор тега React
    Frontend Developer
    1. Функция map превращает в колбеке элемент вашего массива данных в JSX код описывающий элемент и на выходе выдает массив таких элементов. Это лучший и общепринятый способ рендерить списки в react.
    Банальный пример:
    const employees =  ['Bill', 'Matt', 'Sarah'];
    
    return (
      <ul>
        {employees.map((employee, i) => (
          <li key={i}>employee</li>
        )}
      <ul>
    );

    Результат:
    <ul>
      <li>Bill</li>
      <li>Matt</li>
      <li>Sarah</li>
    </ul>


    2. "Element" как видите строка. Тут разработчики просто пушат в массив строку, но в идеале тут должна вызываться функция иницирующая запрос к серверу.
    Вот более приближенный к жизни пример:
    class Example extends Component {
      state = {
        elements: [],
        page: 1,
        limit: 20,
        total: 0,
        isLoading: false,
        isError: false,
      };
      
      componentDidMount() {
        this.loadThumbnails();
      }
     
      loadThumbnails = () => {
        const { page, limit } = this.state;
        
        this.setState({
          isLoading: true,
          isError: false,
        }, () => {
          axios.get(
            `api/somePath?limit=${limit}&page=${page + 1}`
          ).then(response => {
            const { data: { elements, total } } = response;
          
            this.setState(prevState => ({
              elements: [
                ...prevState.elements,
                ...elements
              ],
              page: page + 1,
              isLoading: false,
              total,
            }));
          }).catch(error => {
            this.setState({
              isLoading: false,
              isError: true,
            });
          });
        });
      };
      
      render() {
        const {
          elements,
          page,
          limit,
          total,
          isLoading,
        } = this.state;
    
        const hasMore = page * limit < total;
    
        return(
          <MasonryInfiniteScroller
            hasMore={hasMore}
            loadMore={this.loadThumbnails}
          >
            {elements.map(element => (
              <img
                key={element.id}
                src={element.thumbnail}
                style={{
                  width: element.width + 'px',
                  height: element.height + 'px',
                }}
              />
            )}
            {isLoading && <div>...Loading</div>}
            {isError && (
              <div>
                Can't load data. Please, check your internet connection.
                <button onClick={this.loadThumbnails}>
                  Try again
                </button>
              </div>
            )}
          </MasonryInfiniteScroller>
        ); 
      }
    }


    Тут как только вы пролистнете список
    Ответ написан
    1 комментарий
  • Как посчитать количество определенных объектов в LocalStorage?

    rockon404
    @rockon404
    Frontend Developer
    А почему не пишите массивом по одному ключу?
    Работать с массивом было бы гораздо удобней:
    var cartItems = JSON.parse(localStorage.getItem('cart'));
    var itemsQuantity = cartItems.length;
    Ответ написан
    3 комментария
  • Как избежать дублирования кода скрипта?

    rockon404
    @rockon404
    Frontend Developer
    Вам бы код научиться читать:
    $('.input-name').inputfit({ maxSize: 60 });
    $('.input-date').inputfit({ maxSize: 30 });


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