8 вещей, о которых я забыл в JavaScript
12 марта 2021 г. • ☕️ 5 мин.
С приходом ECMAScript 2015
(ES6
), JavaScript
стал развиваться очень стремительно, новые улучшения стали появляться каждый год. За счет большого количества новых фич, старые фичи/подходы часто остаются ненужными или используются в редких случаях.
Вспомним некоторые из них, которые были забыты, но когда-то использовались повсеместно.
Методы bind
, call
и apply
До появления стрелочных функций (arrow function
), эти методы имели очень широкое применение. Хоть стрелочные функции не являются прямой заменой этим методам, они очень сильно перекрывают сценарии использования.
До
const user = {
name: "John",
sayHi: function() {
console.log(`Hi, ${this.name}`)
},
}
setTimeout(user.sayHi.bind(user), 1000)
После
const user = {
name: "John",
sayHi: function() {
console.log(`Hi, ${this.name}`)
},
}
setTimeout(() => user.sayHi(), 1000)
Явная работа с прототипами и наследование на функциях
В JavaScript
ООП работает с помощью прототипов (prototype
). Для реализации ООП и наследования приходилось использовать функции и явно работать с прототипами.
function User(name) { this.name = name
}
User.prototype.sayHi = function() {
console.log(this.name)
}
const user = new User("John")
user.sayHi()
Также многие библиотеки имели отдельные реализации упрощающие работу с “классами” и наследованием.
util
- стандартная библиотека в Node.js
const util = require('util')
const EventEmitter = require('events')
function MyStream() {
EventEmitter.call(this)
}
util.inherits(MyStream, EventEmitter)
MyStream.prototype.write = function(data) {
this.emit('data', data)
}
const stream = new MyStream()
console.log(stream instanceof EventEmitter) // true
console.log(MyStream.super_ === EventEmitter) // true
React
когда-то имел свою реализацию классов.
const createReactClass = require('create-react-class')
const Greeting = createReactClass({ render: function() {
return <h1>Hello, {this.props.name}</h1>
}
});
Новый синтаксис class
добавил стандартную реализацию и абстрагировал многие детали.
class User {
constructor(name) {
this.name = name
}
sayHi() {
console.log(this.name)
}
}
var
vs let
и const
С появлением let
и const
использование var
кануло в небытие, как и проблемы связанные с ним.
var
for (var i = 0; i < 10; i++) { // ...
}
console.log(i) // 10
let
for (let i = 0; i < 10; i++) { // ...
}
console.log(i) // ReferenceError: i is not defined
jQuery
Хоть это и не часть JavaScript
, а библиотека, когда-то она имела огромную популярность, за счет того, что упрощала написание кода с удобным API
. ES6
же принес много “синтаксического сахара”, после чего jQuery
стал не нужен в большинстве ситуаций.
Пример jQuery
$(el).find(selector)
На чистом JavaScript
el.querySelectorAll(selector)
Существует даже веб-сайт, помогающий перейти с “синтаксиса” jQuery
на JavaScript
.
http://youmightnotneedjquery.com
Callbacks
Несмотря на то, что многие API
браузера и Node.js
до сих пор построены на callbacks
, чаще всего для них пишут обертки с использованием Promise
. Код, который мы пишем в программах, в основном использует Promise
и async/await
.
До
fs.readFile("./file.txt", (err, file) => {
if (err) throw err
})
После
async function main() {
const file = await fs.readFile("./file.txt")
}
Подробная статья про проблемы с callbacks
Код без модулей и проблемы с глобальными переменными
Раньше не было модулей, можно было только подключить файл через tag script
, а так же использовать анонимные самовызывающиеся функции (IFFE
) во избежание конфликтов названий глобальных переменных.
В скором это было решено использованием различнх менеджеров/сборщиков модулей, таких как webpack
. А с приходом ESM
появлась полноценная поддержка модульности в JavaScript
.
import { hi } from './hi.js'
hi('John')
Псевдомассив arguments
Сейчас мы используем rest parameter
синтаксис, позволяющий принять неопределенное количество аргументов, как массив.
function f(a, b, ...theArgs) {
// ...
}
До его появления, для этих целей использовали псевдомассив arguments
.
function f(a, b) {
console.log(arguments)
}
Конкатенация строк
До появления шаблонных строк (Template Literals
), очень часто использовалась простая конкатенация.
const name = "John"
const greeting = "Hello" + " " + name + "!"
В современном JavaScript
для этих целей обычно используются шаблонные строки.
const name = "John"
const greeting = `Hello ${name}!`
Удобно, не правда ли?
Так с эволюцией языка, появляются новые абстракции, чтобы упростить решение типичных задач, а старые, остаются для сохранения обратной совместимости и решения узкого круга задач.