Русский
Русский
English
Статистика
Реклама

Инструмент

Фичи JavaScript. Часть 1

19.06.2020 08:12:45 | Автор: admin


Доброго времени суток, друзья!

В этой статье я хочу поделиться с Вами некоторыми находками, сделанными мной в процессе изучения JavaScript. Возможно, Вы найдете для себя что-то интересное. Данная часть серии будет посвящена, преимущественно, работе с DOM.

Настоятельно рекомендую применить к body следующие стили:

body {    margin: 0;    min-height: 100vh;    overflow: hidden;}

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

const clear = () => document.body.innerHTML = ''clear()

1. Активный элемент


Свойство activeElement позволяет получить элемент, находящийся в фокусе.

const input = document.createElement('input')input.setAttribute('type', 'text')input.setAttribute('placeholder', 'Введите свое имя')input.className = 'username'document.body.append(input)input.focus()console.log(document.activeElement)// <input type="text" placeholder="Введите свое имя" class="username">

2. Редактирование страницы


Свойство designMode позволяет редактировать страницу, открытую в браузере.

document.designMode = 'on'



3. Стили элемента


Метод getComputedStyle() позволяет получить стили элемента. Для получения определенного свойства следует использовать getPropertyValue().

// напишем вспомогательную функцию для получения определенного свойства элемента// мы будем использовать ее в нескольких примерахconst getStyle = (element, property) => getComputedStyle(element).getPropertyValue(property)// возьмем инпут из первого примера// и определим его ширину и высотуconst inputWidth = getStyle(input, 'width')const inputHeight = getStyle(input, 'height')console.log(`Ширина: ${inputWidth}\nВысота: ${inputHeight}`)// Ширина: 156.8px// Высота: 16px// позиционируем элемент, используя полученные данные// предположим, что мы собираемся анимировать элемент// поэтому не хотим использовать transform: translate(-50%, -50%)// допустим также, что мы не знаем размеров элемента// поэтому не можем использовать calc(50% - ширина/высота элемента)input.setAttribute('style',    `position: absolute; top: calc(50% - ${inputHeight.replace('px', '') / 2}px); left: calc(50% - ${inputWidth.replace('px', '') / 2}px);`)

4. Определение браузера


Объект Navidator, в числе прочего, позволяет получить информацию о браузере пользователя.

let browserconst agent = navigator.userAgentif (agent.indexOf('Google')) {    browser = 'Google Chrome'} else if (agent.indexOf('Safari')) {    browser = 'Apple Safari'} else if (agent.indexOf('Opera')) {    browser = 'Opera'} else if (agent.indexOf('Firefox')) {    browser = 'Mozilla Firefox'} else if (agent.indexOf('MSIE')) {    browser = 'Microsoft Interner Explorer'}console.log(browser) // Google Chrome// вероятно, в данном случае надо было использовать switchif (browser === 'Google Chrome' || browser === 'Mozilla Firefox') {    console.log('ok') // ok} else if (browser === 'Opera' || browser === 'Apple Safari') {    console.log('50/50')} else if (browser === 'Microsoft Interner Explorer') {    console.log('!ok')}

5. Получение координат


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

const success = position => {    // деструктурируем объект    const {        latitude,        longitude,        altitude,        speed    } = position.coords    console.log(`${latitude.toFixed(2)}\n${longitude.toFixed(2)}\n${altitude}\n${speed}`)    // об этом ниже    getCityAndWeather(latitude, longitude)}navigator.geolocation.getCurrentPosition(success)/*    56.90    60.63    null    null*/// вот как мы можем использовать полученные данные// определим город пользователя и погодуconst getCityAndWeather = (latitude, longitude) => {    // прокси для преодоления CORS    const proxy = 'https://cors-anywhere.herokuapp.com/'    // данный сервис был куплен Facebook и станет платным в 2021 году    const api = `${proxy}https://api.darksky.net/forecast/fd9d9c6418c23d94745b836767721ad1/${latitude}, ${longitude}`    fetch(api)        .then(response => response.json())        .then(data => {            console.log(data) // много всего            // получаем город            const city = data.timezone            // получаем температуру            const { temperature, summary } = data.currently            // переводим фаренгейт в цельсий            const celsius = Math.floor((temperature - 32) * (5 / 9)).toFixed()            // выводим результат            console.log(                `${city}\n${celsius}C\n${summary}`            )            /*                Asia/Yekaterinburg                15C                Overcast            */        })}

6. Получение элементов


Как нам получить все элементы DOM? Использовать рекурсию.

const template = `<div>    <p> Lorem ispum        <span>dolor sit amet</span>    </p></div><a href="#">link</a>`document.body.innerHTML = templateconst getElements = element => {    for (const i of element.children) {        console.log(i.tagName)        // 0 -> ! -> false -> ! -> true        if (!!i.children.length) {            console.log('дочерний элемент')            getElements(i)        }    }}getElements(document.body)/*    DIV    дочерний элемент    P      дочерний элемент    SPAN    A*/

7. Разбор URL


Как нам получить отдельные части URL? Это можно сделать двумя способами.

// с помощью регуляркиconst regex = /(\w+):\/\/([\w.]+)\/(\S*)/const url = 'https://example.com/index.html'const result = url.match(regex)// полный адрес (абсолютный путь), протокол, хост, страницаconsole.log(result[0], result[1], result[2], result[3])// https://example.com/index.html https example.com index.html// с помощью конструктора URLconst url2 = new URL('https://example.com/search?query=fetch&page=2#awesome-page')console.log(url2) // много всегоconst {    origin,    protocol,    host,    pathname} = url2console.log(    `${origin} ${protocol} ${host} ${pathname}`)// https://example.com https: example.com /search// рекомендую почитать про свойство searchParams// searchParams.get(), searchParams.append(), searchParams.has(), searchParams.delete() и т.д.

8. Позиционирование одного элемента относительно другого


const toCenter = (element, parent) => {    element.style.position = 'relative'    element.style.left = (parent.clientWidth - element.offsetWidth) / 2 + 'px'    element.style.top = (parent.clientHeight - element.offsetHeight) / 2 + 'px'}const div = document.createElement('div')div.setAttribute('style', 'width: 150px; height: 150px; background: red;')document.body.append(div)const div2 = document.createElement('div')div2.setAttribute('style', 'width: 100px; height: 100px; background: green;')div.append(div2)const div3 = document.createElement('div')div3.setAttribute('style', 'width: 50px; height: 50px; background: blue;')div2.append(div3)toCenter(div, document.body)toCenter(div2, div)toCenter(div3, div2)


9. Ширина и высота документа


Как нам получить полную ширину и высоту документа?

const pageWidth = Math.max(    document.body.scrollWidth, document.documentElement.scrollWidth,    document.body.offsetWidth, document.documentElement.offsetWidth,    document.body.clientWidth, document.documentElement.clientWidth)const pageHeight = Math.max(    document.body.scrollHeight, document.documentElement.scrollHeight,    document.body.offsetHeight, document.documentElement.offsetHeight,    document.body.clientHeight, document.documentElement.clientHeight)// один из вариантов использования// определяем центр страницыconst pageCenter = [pageWidth / 2, pageHeight / 2]console.log(pageCenter)// создаем элемент для позиционированияconst p = document.createElement('p')p.textContent = 'Lorem ipsum dolor sit amet'document.body.append(p)p.style.position = 'absolute'// получаем ширину и высоту элемента, используя getStyleconst elementWidth = getStyle(p, 'width').replace('px', '')const elementHeight = getStyle(p, 'height').replace('px', '')// определяем центр элементаconst elementCenter = [elementWidth / 2, elementHeight / 2]console.log(elementCenter)// позиционируем элементp.style.top = pageCenter[1] - elementCenter[1] + 'px'p.style.left = pageCenter[0] - elementCenter[0] + 'px'

10. Координаты элемента в контексте документа


Метод getBoundingClientRect() возвращает размер элемента и его позицию относительно области просмотра.

// возьмем p из предыдущего примераconsole.log(p.getBoundingClientRect()) // много всегоconsole.log(    `Отступ сверху => ${p.getBoundingClientRect().top.toFixed()}\nОтступ слева => ${p.getBoundingClientRect().left.toFixed()}`)/*    Отступ сверху => 352    Отступ слева => 288*/// создадим два элемента// и определим, в какой части страницы находится каждый из нихconst div = document.createElement('div')div.setAttribute('style', 'width: 100px; height: 100px; background: #222; position: absolute; top: calc(50% - 50px); left: calc(25% - 50px);')document.body.append(div)const div2 = document.createElement('div')div2.setAttribute('style', 'width: 100px; height: 100px; background: #222; position: absolute; top: calc(50% - 50px); left: calc(75% - 50px);')document.body.append(div2)document.querySelectorAll('div').forEach(div => div.addEventListener('click', event => {    const x = event.target.getBoundingClientRect().x    const width = event.target.getBoundingClientRect().width    // расчеты приблизительные    x + width < innerWidth / 2    ? console.log('Элемент находится в левой части страницы.')    : console.log('Элемент находится в правой части страницы.')}))div.click() // Элемент находится в левой части страницы.div2.click() // Элемент находится в правой части страницы.// определим расстояние между нимиconst distanceBetweenDivs = (div, div2) =>console.log((div2.getBoundingClientRect().x - div.getBoundingClientRect().x + div.getBoundingClientRect().width).toFixed())distanceBetweenDivs(div, div2) // 477

11. Координаты курсора


Как нам получить координаты курсора? Очень просто.

// document.addEventListener('click', ev => console.log(`X => ${ev.clientX}\nY => ${ev.clientY}`))/*    X => 348    Y => 304*/// вот как мы можем это использовать// создаем холст и получаем его контекстconst canvas = document.createElement('canvas')document.body.append(canvas)const $ = canvas.getContext('2d')// размер холста - область просмотраcanvas.width = innerWidthcanvas.height = innerHeight// создаем вспомогательную функцию для получения случайного целого числа в заданном диапазонеconst randomInt = (min, max) => Math.floor(min + Math.random() * (max + 1 - min))// создаем вспомогательную функцию для получения случайного цветаconst randomColor = () => `#${((Math.random()*0xfff)<<0).toString(16)}`// давайте порисуем// рисование фигур осуществляется по клику// центр фигуры - место клика// форма фигуры - круг или квадратlet i = 0canvas.addEventListener('click', ev => {    $.beginPath()    // если i - четное число, то рисуем круг    // если нечетное - квадрат    if (i % 2 === 0) {        // $.arc(x, y, радиус, угол)        $.arc(ev.clientX, ev.clientY, randomInt(10, 30), 0, 2 * Math.PI)        $.fillStyle = randomColor()        $.fill()    } else {        let randomSize = randomInt(20, 60)        $.fillStyle = randomColor()        // $.fillRect(x, y, ширина, высота)        $.fillRect(ev.clientX - randomSize / 2, ev.clientY - randomSize / 2, randomSize, randomSize)    }    $.closePath()    i++})

Напоследок реализуем функцию рисования определенного количества фигур.

const manyShapes = number => {    // очищаем холст    $.clearRect(0, 0, canvas.width, canvas.height)    for (let i = 0; i < number; i++) {        let randomX = randomInt(0, innerWidth)        let randomY = randomInt(0, innerHeight)        if (i % 2 === 0) {            $.beginPath()            $.arc(randomX, randomY, randomInt(10, 30), 0, 2 * Math.PI)            $.fillStyle = randomColor()            $.fill()        } else {            let randomSize = randomInt(20, 60)            $.beginPath()            $.rect(randomX, randomY, randomSize, randomSize)            $.fillStyle = randomColor()            $.fill()        }    }}manyShapes(100)



Благодарю за потраченное время. Надеюсь, оно было потрачено не зря.

Продолжение следует
Подробнее..

Фичи JavaScript. Часть 2

27.06.2020 10:22:34 | Автор: admin


Доброго времени суток, друзья!

В этой статье я продолжаю делиться с Вами некоторыми находками, сделанными мной в процессе изучения JavaScript. Данная часть посвящена, преимущественно, новым и продвинутым фичам.

См. Фичи JavaScript. Часть 1.

1. Частое обращение к одним и тем же элементам


Порой при написании кода приходится снова и снова обращаться к одним и тем же элементам. При работе с DOM, например, такими элементами являются document и document.body. Казалось бы, что тут такого? 8 и 13 символов, соответственно, да еще и emmet помогает. Однако, когда кода действительно много, автозавершение начинает предлагать неправильные варианты. Либо, когда работаешь не с html, а, например, с php без правильного синтаксического анализатора, многие привычные вещи приходится набирать вручную. Задумавшись о том, как решить указанную проблему, я вспомнил о canvas. Помните, с чего начинается работа с холстом? Правильно, с его определения и инициализации двумерного контекста рисования:

const C = document.querySelector('canvas')const $ = C.getContext('2d')

Также я подумал об объекте jQuery ($).

Так вот, могу предложить три варианта (один из вариантов я подглядел у разработчиков Facebook при изучении протокола Open Graph):

    // внутри функцииfunction foo() {    const D = document    const B = document.body    const div = D.createElement('div')    B.append(div)    const p = D.createElement('p')    p.textContent = 'Lorem ipsum dolor sit amet...'    div.append(p)    console.log(div)    B.removeChild(div)}foo()// снаружи функцииfunction bar(D, B) {    const div = D.createElement('div')    B.append(div)    const p = D.createElement('p')    p.textContent = 'Lorem ipsum dolor sit amet...'    div.append(p)    console.log(div)    B.removeChild(div)}bar(document, document.body)// IIFE;((D, B) => {    const div = D.createElement('div')    B.append(div)    const p = D.createElement('p')    p.textContent = 'Lorem ipsum dolor sit amet...'    div.append(p)    console.log(div)    B.removeChild(div)})(document, document.body)

Это была разминка, переходим к тренировке.

2. Генератор


Генератор это особая функция, которая работает как фабрика итераторов. Объект является итератором, если он умеет обращаться к элементам коллекции по одному за раз, при этом отслеживая свое текущее положение внутри этой последовательности. Генераторы позволяют определить алгоритм перебора элементов коллекции с помощью единственной функции, поддерживающей собственное состояние.

// пример 1function* takeItem(arr) {    for (let i = 0; i < arr.length; i++) {        yield arr[i]    }}const arr = ['foo', 'bar', 'baz', 'qux']const generator = takeItem(arr)const timer = setInterval(() => {        const item = generator.next()        item.done            ? clearInterval(timer)            : console.log(item.value)    }, 1000)// пример 2async function* range(start, end) {    for (let i = start; i <= end; i++) {        yield Promise.resolve(i)    }};(async () => {    const generator = range(1, 4)    for await (const item of generator) {        console.log(item)    }})()

3. Async/await + fetch


Async/await является альтернативой промисов, позволяя обеспечить синхронность выполнения асинхронных функций. В свою очередь, fetch является альтернативой XMLHttpRequest, представляя собой интерфейс для получения ресурсов (в том числе, по сети).

const url = 'https://jsonplaceholder.typicode.com/users';(async () => {    try {        const response = await fetch(url)        const data = await response.json()        console.table(data)    } catch (er) {        console.error(er)    } finally {        console.info('потрачено')    }})()

4. For await


Выражение for await...of создает цикл, проходящий через асинхронные итерируемые объекты, а также синхронные итерируемые сущности. Он вызывает пользовательский итерационный хук с инструкциями, которые должны быть выполнены для значения каждого отдельного свойства объекта.

const delayedPromise = (id, ms) => new Promise(resolve => {    const timer = setTimeout(() => {        resolve(id)        clearTimeout(timer)    }, ms)})const promises = [    delayedPromise(1, 1000),    delayedPromise(2, 2000),    delayedPromise(3, 3000)]// старый стильasync function oldStyle() {    for (const promise of await Promise.all(promises)) {        console.log(promise)    }}oldStyle() // все промисы через 3 секунды// новый стильasync function newStyle() {    for await (const promise of promises) {        console.log(promise)    }}newStyle() // каждый промис в свой черед

5. Proxy


Прокси используются для объявления расширенной семантики JS объектов. Стандартная семантика реализована в движке JS, который обычно написан на низкоуровневом языке программирования, например C++. Прокси позволяют определить поведение объекта при помощи JS. Другими словами, они являются инструментом метапрограммирования.

const person = {    firstname: 'Harry',    lastname: 'Heman',    city: 'Mountain View',    company: 'Google'}const proxy = new Proxy(person, {    get(target, property) {        if (!(property in target)) {            return property                .split('_')                .map(p => target[p])                .sort()                .join(' ')        }        console.log(`получено свойство: ${property}`)        return target[property]    },    set(target, property, value) {        if (property in target) {            target[property] = value            console.log(`изменено свойство: ${property}`)        } else {            console.error('нет такого свойства')        }    },    has(target, property) {        // return property in target        return Object.entries(target)            .flat()            .includes(property)    },    deleteProperty(target, property) {        if (property in target) {            delete target[property]            console.log(`удалено свойство: ${property}`)        } else {            console.error('нет такого свойства')        }    }})console.log(proxy.company_city_firstname_lastname) // Google Harry Heman Mountain Viewproxy.firstname = 'John' // изменено свойство: firstnameproxy.surname = 'Smith' // нет такого свойстваconsole.log(proxy.city) // получено свойство: city Mountain Viewconsole.log('company' in proxy) // truedelete proxy.age // нет такого свойства// proxy + cookieconst getCookieObject = () => {    const cookies = document.cookie.split(';').reduce((cks, ck) => ({        [ck.substr(0, ck.indexOf('=')).trim()]: ck.substr(ck.indexOf('=') + 1),        ...cks    }), {})    const setCookie = (name, value) => document.cookie = `${name}=${value}`    const deleteCookie = name => document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:01 GTM;`    return new Proxy(cookies, {        set: (obj, prop, val) => (setCookie(prop, val), Reflect.set(obj, prop, val)),        deleteProperty: (obj, prop) => (deleteCookie(prop), Reflect.deleteProperty(obj, prop))    })}

6. Reduce


Метод reduce() применяет функцию reducer к каждому элементу массива, возвращая результирующее значение. Данный метод принимает четыре аргумента: начальное значение (или значение предыдущей функции обратного вызова), значение текущего элемента, текущий индекс и итерируемый массив (два последних являются необязательными). В простейшем случае это выглядит так:

const arr = [1, 2, 3]const total = arr.reduce((sum, cur) => sum + cur)console.log(total) // 6// forEachlet total2 = 0arr.forEach(num => total2 += num)console.log(total2) // 6

Однако возможности reduce() этим далеко не исчерпываются:

const devs = [    {        name: 'John',        sex: 'm',        age: 23    },    {        name: 'Jane',        sex: 'f',        age: 24    },    {        name: 'Alice',        sex: 'f',        age: 27    },    {        name: 'Bob',        sex: 'm',        age: 28    }]const men = devs.reduce((newArr, dev) => {    if (dev.sex === 'm') newArr.push(dev.name)    return newArr}, [])console.log(men) // ["John", "Bob"]// filter + mapconst olderThan25 = devs    .filter(dev => dev.age > 25)    .map(dev => dev.name)console.log(olderThan25) // ["Alice", "Bob"]

Сформируем список имен разработчиков одной строкой:

const devsNamesList = `<ul>${devs.reduce((html, dev) => html += `<li>${dev.name}</li>`, '')}</ul>`document.body.innerHTML = devsNamesList// mapconst devsNamesList2 = `<ul>${devs.map(dev => `<li>${dev.name}</li>`).join('')}</ul>`document.body.insertAdjacentHTML('beforeend', devsNamesList2)

Поговорим о группировке:

const groupBy = (arr, criteria) =>    arr.reduce((obj, item) => {        const key = typeof criteria === 'function'            ? criteria(item)            : item[criteria]        if (!obj.hasOwnProperty(key)) obj[key] = ''        obj[key] = item        return obj    }, {})const nums = [6.1, 4.2, 2.3]console.log(groupBy(nums, Math.floor)) // {2: 2.3, 4: 4.2, 6: 6.1}// forEachconst groupBy2 = (arr, criteria, obj = {}) => {    arr.forEach(item => {        const key = typeof criteria === 'function'            ? criteria(item)            : item[criteria]                if (!obj.hasOwnProperty(key)) obj[key] = ''        obj[key] = item        return obj    })    return obj}const words = ['one', 'three', 'five']console.log(groupBy2(words, 'length')) // {3: "one", 4: "five", 5: "three"}

Сделаем выборку:

const cash = {    A: 1000,    B: 2000}const devsWithCash = devs.reduce((arr, dev) => {    const key = dev.name.substr(0,1)        if (cash[key]) {        dev.cash = cash[key]        arr.push(`${dev.name} => ${dev.cash}`)    } else dev.cash = 0    return arr}, [])console.log(devsWithCash) // ["Alice => 1000", "Bob => 2000"]// map + filterconst devsWithCash2 = devs.map(dev => {    const key = dev.name.substr(0,1)    if (cash[key]) {        dev.cash = cash[key]    } else dev.cash = 0    return dev}).filter(dev => dev.cash !== 0)console.log(devsWithCash2)

И последний пример. Помните, как мы формировали список имен разработчиков из массива объектов одной строкой? Но что если у нас имеется такой массив:

const users = [    {        john: {            name: 'John'        }    },    {        jane: {            name: 'Jane'        }    },    {        alice: {            name: 'Alice'        }    },    {        bob: {            name: 'Bob'        }    }]

Как нам сделать тоже самое?

document.body.insertAdjacentHTML('afterbegin', `<ul>${users.reduce((html, el) => html + `<li>${Object.values(el)[0].name}</li>`, '')}</ul>`) // фух!

Давайте рассмотрим что-нибудь попроще.

7. Новые методы работы со строками


// trimStart() trimEnd() trim()const start = '   foo bar'const end = 'baz qux   'console.log(`${start.trimStart()} ${end.trimEnd()}`) // foo bar baz quxconsole.log((`${start} ${end}`).trim()) // тоже самоеconst startMiddleEnd = '   foo  bar   baz  ' // три пробела в начале, два - между foo и bar, три - между bar и baz и два - в конце// при помощи регулярного выражения заменяем два и более пробела одним// затем посредством trim() удаляем пробелы в начале и концеconst stringWithoutRedundantSpaces = startMiddleEnd.replace(/\s{2,}/g, ' ').trim()console.log(stringWithoutRedundantSpaces) // foo bar baz// padStart() padEnd()let str = 'google'str = str.padStart(14, 'https://') // первый аргумент - количество символовconsole.log(str) // https://googlestr = str.padEnd(18, '.com')console.log(str) // https://google.com

8. Новые методы работы с массивами


const arr = ['a', 'b', ['c', 'd'], ['e', ['f', 'g']]]console.log(arr.flat(2)) // ["a", "b", "c", "d", "e", "f", "g"]const arr2 = ['react vue', 'angular', 'deno node']console.log(arr2.map(i => i.split(' ')))/*    [Array(2), Array(1), Array(2)]        0: (2) ["react", "vue"]        1: ["angular"]        2: (2) ["deno", "node"]*/console.log(arr2.flatMap(i => i.split(' '))) // ["react", "vue", "angular", "deno", "node"]

9. Новые методы работы с объектами


const person = {    name: 'John',    age: 30}console.log(Object.getOwnPropertyDescriptor(person, 'name')) // {value: "John", writable: true, enumerable: true, configurable: true}const arr = Object.entries(person)console.log(arr) // [["name", "John"], ["age", 30]]console.log(Object.fromEntries(arr))for (const [key, value] of Object.entries(person)) {    console.log(`${key} => ${value}`) // name => John age => 30}console.log(Object.keys(person)) // ["name", "age"]console.log(Object.values(person)) // ["John", 30]

10. Приватные переменные в классах


class Person {    // значения по умолчанию    static type = 'человек'    static #area = 'Земля'    name = 'John'    #year = 1990    get age() {        return new Date().getFullYear() - this.#year    }    set year(age) {        if (age > 0) {            this.#year = new Date().getFullYear() - age        }    }    get year() {        return this.#year    }    static area() {        return Person.#area    }}const person = new Person()console.log(person) // Person{name: "John", #year: 1990}console.log(person.age) // 30// console.log(person.#year) // errorperson.year = 28console.log(person.year) // 1992console.log(Person.type) // человек// console.log(Person.#area) // errorconsole.log(Person.area()) // Земля

11. Еще парочка нововведений


// промисыconst p1 = Promise.resolve(1)const p2 = Promise.reject('error')const p3 = Promise.resolve(3);(async () => {const result = await Promise.all([p1, p2, p3])console.log(result)})() // Uncaught (in promise) error;(async () => {const result = await Promise.allSettled([p1, p2, p3])console.log(result)})()/*    [{}, {}, {}]        0: {status: "fulfilled", value: 1}        1: {status: "rejected", reason: "error"}        2: {status: "fulfilled", value: 3}*/// приведение к null (nullish coercion)const values = {    undefined: undefined,    null: null,    false: false,    zero: 0,    empty: ''}console.log(values.undefined || 'default undefined')console.log(values.undefined ?? 'default undefined')// default undefinedconsole.log(values.null || 'default null')console.log(values.null ?? 'default null')// default nullconsole.log(values.false || 'default false') // default falseconsole.log(values.false ?? 'default false') // falseconsole.log(values.zero || 'default zero') // default zeroconsole.log(values.zero ?? 'default zero') // 0console.log(values.empty || 'default empty') // default emptyconsole.log(values.empty ?? 'default empty') // ''// опциональная цепочка (optional chaining)const obj1 = {    foo: {        bar: {            baz: {                qux: 'veryDeepInside'            }        }    }}const obj2 = {    foo: {}}// старый стильfunction getValueOld(obj) {    if (obj.foo !== undefined &&    obj.foo.bar !== undefined &&    obj.foo.bar.baz !== undefined &&    obj.foo.bar.baz.qux !== undefined) {        return obj.foo.bar.baz.qux    }}console.log(getValueOld(obj1)) // veryDeepInsideconsole.log(getValueOld(obj2)) // нет ошибки// новый стильconst getValueNew = obj => obj?.foo?.bar?.baz?.quxconsole.log(getValueNew(obj1)) // veryDeepInsideconsole.log(getValueNew(obj2)) // нет ошибки

Благодарю за потраченное время. Надеюсь, оно было потрачено не зря.

Продолжение следует
Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru