Javascript именованные параметры функции

Обзор ECMAScript 6, следующей версии JavaScript

В текущей версии JavaScript присутствует функциональная область видимости. Это означает, что все переменные, объявленные c помощью ключевого слова var , будут видны в любом месте функции (даже если они объявлены внутри блока):

function f(a) < if (a < 0) < var i = 3; >console.log(i); // 3 > f(-1) 

В новой версии появится ключевое слово let , которое позволит объявлять переменные с блочной областью видимости:

function f(a) < if (a < 0) < let i = 3; >console.log(i); // ReferenceError: i is not defined > f(-1) 

Значения параметров по умолчанию

В функциях добавилась возможность объявлять у параметров значения по умолчанию:

function setLevel(newLevel = 0) < . >setLevel(); // newLevel = 0 setLevel(5); // newLevel = 5 setLevel(undefined); // newLevel = 0 

Именованные параметры функций

В функциях также появилась возможность указывать именованные параметры:

Именованные параметры можно комбинировать с обычным (позиционными параметрами):

function foo(positional, < named1, named2 >) < . >foo(123, < named1: 'abc', named2: 'def' >) foo(123, < named2: 'def', named1: 'abc' >) 

Destructuring assignment

ECMAScript 6 позволит деструктуризировать при присваивании:

let < first: f, last: l >= < first: 'Jane', last: 'Doe' >; console.log(f); // 'Jane' console.log(l); // 'Doe' 

Кстати, в примере из предыдущего пункта (Именованные параметры) вы видели пример деструктуризации параметров функции.

Деструктуризация по умолчанию является refutable (не имею понятия, как это переводить). Т.е. если в объекте-источнике присваивания соответствующего поля нету, то выбрасывается ошибка:

Если же вы не хотите, чтобы ошибка генерировалась, то переменную можно объявить как irrefutable с помощью суффикса ?:

let < first: f, last?: l >= < first: 'Jane' >; // ok console.log(l); // undefined 

Либо можно дать переменной значение по умолчанию:

let < first: f, last: l = 'Unknown' >= < first: 'Jane' >; // ok console.log(l); // 'Unknown' 

Значение по умолчанию также срабатывает, если соответствующее поле в объекте-источнике является undefined :

Наконец, если вы хотите, чтобы все переменные были irrefutable, то можно поставить суффикс ? в конце всего шаблона присваивания:

let < foo: f >? = anything; // всегда ok 

В последнем примере переменная f будет инициализирована значением undefined , если anything будет равно undefined , null или не иметь поля foo .

С помощью деструктуризации можно одной строчкой кода поменять значение двух переменных (без всяких tmp ):

Классы

В ECMAScript 6 появятся классы:

// Supertype class Person < constructor(name) < this.name = name; >describe() < return "Person called " + this.name; >> // Subtype class Employee extends Person < constructor(name, title) < super.constructor(name); this.title = title; >describe() < return super.describe() + " (" + this.title + ")"; >> 

Теперь можно использовать эти классы:

let jane = new Employee("Jane", "CTO"); jane instanceof Person; // true jane instanceof Employee; // true jane.describe(); // 'Person called Jane (CTO)' 

Всего того же можно было добиться с помощью прототипов:

// Supertype function Person(name) < this.name = name; >Person.prototype.describe = function () < return "Person called " + this.name; >; // Subtype function Employee(name, title) < Person.call(this, name); this.title = title; >Employee.prototype = Object.create(Person.prototype); Employee.prototype.constructor = Employee; Employee.prototype.describe = function () < return Person.prototype.describe.call(this) + " (" + this.title + ")"; >; 

Как видите, классы в ECMAScript 6 — это просто синтаксический сахар над конструкторами и функциями.

Классы могут иметь статические методы:

Приватных полей и методов не будет (по крайней мере, в ECMAScript 6). Однако некоторое сокрытие данных все же появится. Через модули.

Модули

В JavaScript наконец-то появятся модули:

module Math < export function sum(x, y) < return x + y; >export var pi = 3.141593; // Не видна снаружи function internal() < . >> 
import Math.; alert("2π 2π bar.js").y; // file system 

Все глобальные переменные в модули являются глобальными только в этом модуле.

Возможны циклические зависимости между модулями.

Цикл for-of

Как вы знаете, цикл for-in в JavaScript итерирует по всем полям объекта (включая наследованных). Т.е. итерироваться по значениям массива можно, но опасно:

let arr = [ "blue", "green" ]; arr.notAnIndex = 123; Array.prototype.protoProp = 456; for(var x in arr) < console.log(x); // Напечатает blue, green, notAnIndex, protoProp >

В ECMAScript 6 появится цикл for-of , который решит данную проблему:

Также, возможно, в язык добавится оператор yield , с помощью которого можно легко и красиво писать кастомные итераторы.

Arrow-функции

В ECMAScript 6 появятся arrow functions:

let squares = [ 1, 2, 3 ].map(x => x * x); 

Код выше эквивалентен этому:

let squares = [ 1, 2, 3 ].map(function (x) < return x * x >); 

Arrow-функции немножко отличаются от обычных функций. В первую очередь тем, что в arrow-функциях this привязан к вышестоящему контексту. Т.е.

let jane = < name: "Jane", sayHello: function (friends) < friends.forEach(friend =>< console.log(this.name + " says hello to " + friend) >); > > jane.sayHello([ 'Mark', 'John' ]); 
Jane says hello to Mark Jane says hello to John 
 says hello to Mark says hello to John 

Проблема в том, что this из анонимной функции function(friend) < . >) перекрывает this из окружающего контекста. Для того, чтобы этого избежать, можно использовать старый прием с var self = this или использовать функцию bind :

Т.е. по сути своей arrow functions — опять же синтаксический сахар над существующими анонимными функциями:

  • Нельзя использовать arrow-функции как конструкторы ( new (() =><>) кинет ошибку)
  • Arrow-функции не могут обратиться к переменной arguments (да и незачем)

В остальном arrow-функции не отличаются от обычных функций. Они поддерживают значения по умолчанию, переменное количество параметров, операторы typeof и instanceof :

typeof () => <>; // 'function' () => <> instanceof Function; // true 

Заключение

Я описал далеко не всё, что появится в новом стандарте ECMAScript 6. И очень возможно, что что-то из того, о чем я написал выше, может измениться или вообще не появиться в стандарте. Тем не менее, все, что я описал, — это не слухи. Это вещи, реально обсуждаемые комитетом TC39. И к концу этого (2013) года стандарт должен быть утвержден.

Ссылки

Большая часть информации взята из блога доктора Axel’а Rauschmayer’a, послушать которого и повидать вживую мне посчастливилось на конференции CodeFest в Новосибирске.

PS. Спасибо 2GIS за организацию конференции!

Источник

3 чудо-приема JavaScript для ускорения разработки

3 чудо-приема JavaScript для ускорения разработки

За последнее время, благодаря поддержке сообщества, JavaScript стал в технологической индустрии языком, девиз которого “Напиши одни раз — выполняй где угодно”. С его помощью вы можете разрабатывать почти все, что пожелаете: мобильные, настольные и веб-приложения. На JavaScript также создаются нейронные сети и программируются дроны. Что и говорить — этот язык способен на многое. А у профессионального разработчика JavaScript всегда найдется в запасе несколько особо крутых приемов, накопленных за многие годы работы.

Далее я поделюсь тремя своими любимыми и очень эффективными приемами JavaScript, которые сэкономят время разработки.

1. Создание асинхронного контекста

Обработка асинхронных событий в JavaScript — довольно сложный аспект программирования, особенно для новичков, поскольку он непосредственно связан с промисами. Проще говоря, сам разработчик управляет выполнением кода. До выхода ES6 (2015) приходилось использовать множество методов then и catch , объединенных в цепочки, и асинхронный код обрабатывался следующим образом:

promise 
.then(function () < . >)
.catch(function () < . >)
.then(function () < . >)
.catch(function () < . >)

В ES6 было представлено новое и эффективное ключевое слово await . Оно позволяет просто подождать завершения любой асинхронной задачи, после чего продолжить выполнение. Все бы хорошо, но есть одно большое “но”: место await в функции async , и его нельзя задействовать в глобальной области видимости. Поэтому мы воспользуемся IIFE для имитации асинхронного контекста глобального уровня, что позволит применять await везде, где необходимо:

let data

(async () => // Это асинхронный контекст для await

const res = await fetch("https ://google.com/mcdkncjs")
data = await res.json()

>)();

console.log(data)

Благодаря IIFE вы можете создавать асинхронный контекст для обработки различных асинхронных задач.

2. Именованные параметры функции

Как правило, при определении функции у вас есть параметры, которые поочередно передаются при вызове и разделяются запятой (,). Это прекрасно работает при наличии небольшого их числа, отличной IDE или текстового редактора с технологией IntelliSense. В противном случае усложняется процесс написания функции и приходится запоминать все параметры по порядку, что довольно утомительно.

createUser(name, surname, 1542, 21, true)

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

// Объявляем функцию, используя деструктурированные параметры. 
function createUser( name,
surname,
id,
age,
isForeigner
>) < . >

// После этого передаем объект параметров
createUser( name,
surname,
id: 1542,
age: 21,
isForeigner: true
>)

С деструктурированными параметрами вызов функций становится более явным и простым.

3. Функциональная обертка для блоков Try/Catch

С ростом популярности async/await сократились случаи применения catch , вследствие чего разработчики стали задействовать блоки try/catch для обработки ошибок в асинхронных функциях. Однако новый блок означает новый уровень индентации (стиль отступов) и новый уровень сложности.

try var quote = await getQuote(); 
console.log(quote);
catch (error) console.error(error);
>

Блок try/catch для обработки ошибок в асинхронных функциях полностью нивелирует преимущество индентации await перед then .

Поэтому было бы лучше, имей мы функцию, которая возвращала бы ошибку или результат в случае успеха без индентации. Именно этой реализацией мы сейчас и займемся. Для этого оборачиваем блок try/catch функцией, а затем используем ее для перехвата ошибок без индентации.

Функция обработки ошибок будет асинхронной, поскольку внутри мы намерены задействовать await и принять в качестве аргумента другую асинхронную функцию. Далее в зависимости от успешного ее выполнения вернется результат или ошибка.

const handled = async (asyncFunc) => < 
try <
const res = await asyncFunc();
return [null, res];
> catch (error) <
return [error, null]
>
>

Обертывание try/catch внутри функции позволяет работать с ней ее без индентации.

С помощью функции handled можно обрабатывать ошибки на том же уровне индентации, что и await . Нужно лишь обернуть асинхронную функцию посредством handled и провести деструктуризацию и ответа, и ошибки.

const [error, res] = await handled(asyncFunc)

handled возвращает и ошибку, и ответ, но в зависимости от успеха один из них — null .

Отлично! Теперь вы знаете 3 замечательных приема JavaScript, которые являются неотъемлемой частью моей ежедневной работы. Рекомендую вам также взять их на заметку. Благодарю за внимание!

Источник

Читайте также:  Bootstrap css cdn https
Оцените статью