Доброго времени суток, друзья!
Представляю Вашему вниманию перевод статьи Kent Dodds «5 JavaScript Features I Couldn't Code Without».
Это мой первый перевод, так что буду рад любым замечаниям.
const address = {
city: 'Salt Lake City',
state: 'UT',
zip: 84115,
coords: {
lat: 40.776608,
long: -111.920485,
},
}
// допустим, вы хотите сделать это:
const city = address.city
const state = address.state
const zip = address.zip
// используя деструктуризацию, вы можете сделать так:
const {city, state, zip} = address
// без деструктуризации:
function UserName(props) {
return (
<div>
</div>
)
}
// с использованием деструктуризации:
function UserName() {
return (
<div>
</div>
)
}
// с использованием вложенной деструктуризации:
function UserName({name: {first, last}}) {
return (
<div>
</div>
)
}
const info = {
title: 'Once Upon a Time',
protagonist: {
name: 'Emma Swan',
enemies: [
{name: 'Regina Mills', title: 'Evil Queen'},
{name: 'Cora Mills', title: 'Queen of Hearts'},
{name: 'Peter Pan', title: `The boy who wouldn't grow up`},
{name: 'Zelena', title: 'The Wicked Witch'},
],
},
}
// при правильном форматировании вложенная деструктуризация довольно проста,
// хотя не все разделяют мое мнение на этот счет
const {
title,
protagonist: {
name: name,
enemies: [, , , {title: enemyTitle, name: enemyName}],
},
} = info
console.log(`${enemyTitle} (${enemyName}) is an enemy to ${name} in "$5 JavaScript Features I Couldn't Code Without"`)
// a.js
// экспорт
function add(a, b) {
return a + b
}
const foo = 'bar'
const theAnswer = 42
const theQuestion = 'who knows'
// синтаксис модулей позволяет экспортировать их во время создания, но
// мне нравится размещать все "экспорты" в одном месте
export default add
export {foo, theAnswer, theQuestion}
// b.js
// импорт
// 1. импортируем модуль
import './a'
// 2. импортируем по умолчанию
import add from './a'
// 3. импортируем `theAnswer` и `theQuestion` из './a'
import {theAnswer, theQuestion} from './a'
// 4. импортируем `theAnswer` и переименовываем его в `fortyTwo`
import {theAnswer as fourtyTwo} from './a'
// 5. импортируем `add` (по умолчанию) и `theQuestion`
import {default as add, theQuestion} from './a'
// 6. импортируем `add` и `theQuestion` без указания импорта по умолчанию
import add, {theQuestion} from './a'
// 7. импортируем все в единое "пространство имен" под названием `allTheThings`
import * as allTheThings from './a'
const bench = {type: 'Piano', adjustable: false}
const {legs = 4} = bench
// `The bench has ${legs} legs`
// -> The bench has 4 legs
// bench - скамья, leg - ножка
const bench = {type: 'Piano', adjustable: false}
const {legs: legCount = 4} = bench
// `The bench has ${legCount} legs`
// -> The bench has 4 legs
function getDisplayName(firstName = 'Unknown', lastName = 'Unknown') {
return `${firstName} ${lastName}`
}
// getDisplayName()
// -> Unknown Unknown
// getDisplayName('Andrew')
// -> Andrew Unknown
// getDisplayName(undefined, 'Yang')
// -> Unknown Yang
// getDisplayName('Andrew', 'Yang')
// -> Andrew Yang
function getCandy(
kind = requiredParam('kind'),
size = requiredParam('size'),
upperKind = kind.toUpperCase(),
callback = function noop() {},
) {
const result = {kind, size, upperKind}
callback(result)
return result
}
function requiredParam(argName) {
throw new Error(`${requiredParam} is required`)
}
// getCandy('twix', 'king')
// -> {kind: 'twix', size: 'king', upperKind: 'TWIX'}
// getCandy('twix')
// -> ошибка: 'size is required'
const divide = (a, b) => a / b
const getFive = () => 5
const identity = i => i
const asArray = (...args) => args
// обычно, я не именую стрелочные функции с несколькими аргументами
// (в таких случаях я использую обычные функциональные выражения),
// но Вы можете их именовать, если хотите:
const tryInvoke = (obj, fn, ...args) => {
try {
return obj[fn](...args)
} catch (e) {
return undefined
}
}
// для того, чтобы вернуть объект, необходимо заключить его в круглые скобки
const getObject = favoriteCandy => ()
// многострочные JSX (расширение JS в React) также должны быть заключены в круглые скобки
const MyComponent = () => (
<div>
Hello world! I am a function and I return <strong>JSX!</strong>
</div>
)
test('Can fill out a form across multiple pages', async () => {
mockSubmitForm.mockResolvedValueOnce({success: true})
const testData = {food: 'test food', drink: 'test drink'}
const {findByLabelText, findByText} = render(<App />)
user.click(await findByText(/fill.*form/i))
user.type(await findByLabelText(/food/i), testData.food)
user.click(await findByText(/next/i))
user.type(await findByLabelText(/drink/i), testData.drink)
user.click(await findByText(/review/i))
expect(await findByLabelText(/food/i)).toHaveTextContent(testData.food)
expect(await findByLabelText(/drink/i)).toHaveTextContent(testData.drink)
user.click(await findByText(/confirm/i, {selector: 'button'}))
expect(mockSubmitForm).toHaveBeenCalledWith(testData)
expect(mockSubmitForm).toHaveBeenCalledTimes(1)
user.click(await findByText(/home/i))
expect(await findByText(/welcome home/i)).toBeInTheDocument()
})
async function getListItems(req, res) {
const listItems = await listItemsDB.query({ownerId: req.user.id})
res.json({listItems: await expandBookDataMultiple(listItems)})
}
React.useEffect(() => {
getUser().then(
user => setState({status: 'success', error: null, user}),
error => setState({status: 'error', error, user: null}),
)
}, [])
К сожалению, не доступен сервер mySQL