Translate

Поиск по этому блогу

четверг, 3 мая 2018 г.

ES6 для начинающих (3).


Часть 1 статьи можно прочитать здесь.

Часть 2 статьи.



Темы, которые я расскажу в этой статье:
  1. Array map
  2. Array filter
  3. Array reduce
  4. Template literals
  5. Imports and exports
  6. Destructuring objects and arrays
  7. Extend and super


Array Map

Оператор Map используется для выполнения конкретной операции над всеми элементами массива и возвращает массив с модифицированными элементами.

Это очень легко реализовать. Давайте посмотрим пример.

let arr = [1,2,3,4,5];
let modifiedArr = arr.map(function(element, index, arr) {
  return element * 10;
});
console.log(modifiedArr);
Output:
[10, 20, 30, 40, 50]



Как видите, map принимает функцию с тремя параметрами.
  1. Первый параметр - это сам элемент.
  2. Второй параметр - это индекс элемента.
  3. Третий параметр - это весь массив.


А также обратите внимание, что в конце мы должны вернуть некоторое значение. Которое будет измененным значением этого элемента. Если вы ничего не вернули, то конкретный элемент будет неопределенным.

Еще одна вещь, которую я хотел бы добавить, - второй и третий параметр, является необязательным. Обязателен только первый параметр.

let modifiedArr = arr.map(function(element) {
  return element * 10;
});



Как вы видите, map принимает функцию с одним параметром.

Хорошо. Давайте попробуем написать map со стрелочными функциями.

let modifiedArr = arr.map((element, index) => {
  console.log("index "+index);
  return element * 10;
});
console.log(modifiedArr);
Output:
index 0
index 1
index 2
index 3
index 4
[10, 20, 30, 40, 50]



Думаю, мне не нужно много объяснять. Это просто.

Последний пример.

let modifiedArr = arr.map(element => element * 10);
console.log(modifiedArr);



Если вы знаете, стрелочные функции хорошо, это легко понять. Но если нет, то я попытаюсь объяснить.

Здесь есть две вещи.
  1. Если у вас есть функция с единственным параметром, вам не нужны круглые скобки - (). В нашем случае элементом является параметром.
  2. И если у вас есть единственная строка как тело функции, вам не нужны фигурные скобки - {}, а также JS будет неявно возвращать значение после выполнения функции. Вам не нужно использовать ключевое слово return.


Array Filter

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

Давайте посмотрим пример.

let arr = [1, 2, 3, 4, 5, 6]
let modifiedArr = arr.filter(function(element, index, array) {
  return element % 2 == 0
});
console.log(modifiedArr);
Output:
[2, 4, 6]



Как видно из приведенного выше примера, filter, подобно map, принимает три параметра.

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

Хорошо .. Давайте попробуем это в стрелочной функции.

let modifiedAarr = arr.filter((element, index) => element%2 == 0)



Надеюсь, вы поняли. И не забывайте об этом, только первый параметр является обязательным. Другие два параметра являются необязательными.

Array Reduce

Array Reduce используется для агрегирования всех элементов массива и возврата одного значения. Давайте посмотрим пример

let arr = [1,2,3,4,5,6]
let total= arr.reduce(function(sum, element, index, array) {
  return sum + element;
},0);
console.log("total is "+total);
Output:
total is 21



В отличие от filter и map, сокращение принимает функцию с четырьмя параметрами, а также дополнительный элемент. В нашем случае это 0.

Давайте посмотрим, как это работает.

Первый параметр - это элемент агрегатора. Он имеет сумму элементов в любой заданной точке. И это начальное значение определяется как дополнительный элемент. В нашем случае это 0.

Затем второй, третий и четвертый параметры такие же, как у filter и map.

Как и в функциях filter и map, вы должны вернуть конечный результат.

Давайте посмотрим другой пример.

let arr = [1,2,3,4,5,6];
let totalSum = arr.reduce(function(sum, element, index, array) {
  console.log(sum+"+"+element+"="+sum+element);
  return sum + element;
}, 10);
console.log("Total sum is "+ totalSum);
Output:
10 + 1 = 11
11 + 2 = 13
13 + 3 = 16
16 + 4 = 20
20 + 5 = 25
25 + 6 = 31
Total sum is 31



Надеюсь, это понятный пример. Обратите внимание, что я сначала установил начальное значение суммы sum, элемента агрегатора на 10.

Давайте напишем тот же код со стрелочными функциями.

let totalSum = arr.reduce((sum, element) => element+sum, 0)



Надеюсь, вы поняли. Это легко.

В отличие от filter и map, первые два параметра являются обязательными. Другие два являются необязательными.

Template Literals

Если вы знаете другие языки программирования, такие как ruby, python, то Template Literals для вас не новы.

Это новый синтаксис, который упрощает добавление выражений.

Template Literals используются для выполнения любых выражений JS.

Давайте посмотрим пример

let name = "Jon Snow";
let msg = `My name is ${name}`;
console.log(msg);
Output:
My name is Jon Snow



всё очень просто.

Вы также можете использовать многострочные строки- multi-line strings.

let msg = `My name
is ${name}`;
console.log(msg);
Output:
My name
is Jon Snow



Давайте посмотрим другой пример

let name = "Srebalaji";
let languages = () => {return "Ruby, Js, Java, Python"}
let msg = `My name is ${name}
My age is ${20+3}
And I code in ${languages()}`
Output:
My name is Srebalaji
My age is 23
And I code in Ruby, Js, Java, Python



Надеюсь, вы поняли. Идем дальше. Вы можете добавить любое выражение легко, а также многострочные строки (multi-line strings).

Imports and Exports

Импорт и экспорт модулей в ES6 - одна из полезных функций, которые вы увидите в современных библиотеках интерфейсов.

Я очень рекомендую поиграть с этой функцией в этом Plunk. Окружающая среда уже настроена в этом Plunk.

Хорошо .. Так импорт и экспорт работают в ES6.

Экспорт используется в модулях для явного экспорта некоторых переменных или функций или классов. То есть, если вы экспортируете переменную, ее можно использовать в других модулях.

Импорт используется для импорта переменных, функций, классов из других модулей.

Если вы не устали. то давайте посмотрим пример.

app.js
export let name = "Jon"
export let age = 23
index.js
import {name, age} from './app'
console.log(name);
console.log(age);
index.html

Output:
Jon
23



В приведенном выше примере мы определили две переменные name и age переменных и экспортировали их.

В другом файле мы импортировали переменные и получили доступ к их значениям.

Это очень просто.

Пойдем глубже.

app.js
export default const name = "Jon"
index.js
import name from './app.js'
console.log(name);
Output:
Jon



В приведенном выше коде вы видите, что мы использовали новое ключевое слово default - по умолчанию. Значения по умолчанию в основном используются, если вам нужно экспортировать одно значение, функцию или объект из модуля. И в модуле может быть только одно значение по умолчанию - default value.

Еще одна вещь о значениях по умолчанию. Поскольку в модуле будет только одно значение по умолчанию, вы можете использовать любое имя для ссылки на него во время импорта.

Пример:

import n from './app.js'
console.log(n);
Output:
Jon



Как вы можете видеть, мы указали значение по умолчанию - n здесь.

Пойдем глубже.

app.js
let a = 10;
let b = 2;
let sum = () => a+b;
export {a,b}
export default sum
index.js
import * as variables from './app'
import addition from './app' // default value
console.log(variables.a);
console.log(variables.b);
console.log(addition());
Output:
10
2
12



В приведенном выше примере вы можете видеть, что мы экспортировали две переменные и функцию. И мы импортировали все переменные, используя *.

При импорте есть две вещи.
  1. Если вы используете * для импорта значений, вы должны использовать псевдонимы - alias, которые будут ссылаться на импортированные значения. В нашем примере мы использовали переменные - variables как псевдоним.
  2. Использование * для импорта значений не импортирует значение по умолчанию. Вы должны импортировать их отдельно.


import addition, * as variables from './app'



Если вам нужно импортировать значение по умолчанию и другие значения в одной строке, вы можете использовать приведенный выше синтаксис.

Надеюсь, вы поняли. :)

Destructuring objects and arrays

Деструктуризация является одной из полезных функций в ES6. И это очень просто использовать.

Приведем пример.

let person = {firstName: "Jon", lastName: "Snow", age: 23}
const {firstName, lastName, age} = person
console.log(firstName);
console.log(lastName);
console.log(age);
Output:
Jon
Snow
23



В приведенном выше коде вы можете видеть, что у нас есть объект person с несколькими ключами.

И мы создали три переменные firstName, lastName, age (то же самое, что и ключи объектов.) из самого объекта.

Чтобы выразить это простыми словами, мы создали три переменные извлечением ключей из объекта.

Давайте посмотрим другой пример

let person = {firstName: "Jon", lastName: "Snow", age: 23}
const {firstName} = person
console.log(firstName);
Output:
Jon



В приведенном выше примере вы можете видеть, что мы извлекли из объекта только требуемые значения.

let person = {firstName: "Jon", lastName: "Snow", age: 23}
const {firstName: name, age} = person
console.log(name);
console.log(age);
Output:
Jon
23



В приведенном выше примере вы можете видеть, что мы определили новое имя переменной и присвоили значение firstName.

Надеюсь, вы поняли. Это просто.

Давайте посмотрим, как деструктурировать массив - destructure array.

let arr [1, 2, 3, 4]
const [a, b, c, d] = arr;
console.log(a);
console.log(b);
console.log(c);
console.log(d);
Output:
1
2
3
4



Надеюсь, вы уловили это из кода выше. Это просто.

Мы присваиваем каждому элементу массива переменную.

Давайте посмотрим другой пример.

let arr = [1,2,3,4,5,6]
let [a,b,,d,e] = arr
console.log(a);
console.log(b);
console.log(d);
console.log(e);
Output:
1
2
4
5



В приведенном выше коде вы можете видеть, что мы пропустили третий элемент массива. Помимо этого все так же, как в предыдущем примере.

Давайте посмотрим другой пример.

let person = {firstName: "Jon", lastName: "Snow", age: 23}
let displayName = ({firstName, lastName:last}) => {
  console.log(`${firstName} - ${last}`);
}
displayName(person);
Output:
Jon - Snow



Надеюсь, вы поняли. идем дальше.

Extend and Super

Если у вас есть опыт кодирования в OОП (объектно-ориентированном программировании), то >Extend - расширение и Super - супер не новы для вас.

Extend используется для создания подкласса из основного класса. Подкласс наследует все свойства основного класса и также может изменять свойства основного класса.

class Person{
 constructor(firstName, lastName, age) {
   this.firstName = firstName;
   this.lastName = lastName;
   this.age = age;
 }
 displayName() {
  return `${this.firstName} - ${this.lastName}`;
 }
}
class Employee extends Person {
 constructor(firstName, lastName, age, salary) {
  super(firstName, lastName, age);
  this.salary = salary;
 }
 displaySalary() {
  return `${this.salary}`;
 }
 displayName() {
  return super.displayName();
 }
 displayAge() {
  return this.age;
 }
}
let manager = new Employee("Jon", "Snow", 23, 100);
console.log(manager.displaySalary());
console.log(manager.displayName());
console.log(manager.displayAge());
Output:
100
Jon Snow
23



В приведенном выше коде вы можете видеть, что мы определили класс Person с конструктором и простой метод.

И тогда мы определили еще один класс Employee, который является подклассом, унаследованным от Person. Для этого мы использовали расширения - Extend. Надеюсь, что это ясно.

И затем мы использовали ключевое слово super, чтобы вызвать конструктор родительского класса. И мы также вызвали метод, объявленный в родительском классе, используя super.
Примечание: вы можете использовать this в подклассе только после вызова super. Если вы используете this перед вызовом super в подклассе, вы получите RefrenceError.

Итак, мы достигли трех вещей в приведенном выше коде
  1. Мы использовали расширения Extend для создания подкласса из родительского класса.
  2. Мы использовали super для вызова конструктора родительского класса.
  3. Мы использовали super для вызова метода, определенного в родительском классе.
Надеюсь, у вас это получилось :)

Здесь можно немного поиграть и потренировать свои знания


Часть 1 статьи здесь.

Часть 2 статьи здесь.






Автор: Srebalaji Thirumalai.
Перевод: Kolesnikov Yaroslav



                                                                                                                                                             

среда, 2 мая 2018 г.

ES6 для начинающих (2)


Первую часть этой статьи вы можете найти здесь.Там есть некоторые интересные функции. :)



Темы, которые я расскажу в этом посте
  1. Promises - Промисы (обещания)
  2. Async / Await


Promises

Promises - Обещания являются одной из полезных функций в ES6. Они используются для выполнения асинхронных операций, таких как запрос API, обработка файлов, загрузка изображений и т. д.

Итак, что такое Async? (держитесь, если вы уже знаете)

Асинхронные операции - это операции, требующие некоторого времени для завершения.

Например, скажем, вы определяете функцию, которая делает запрос API на сервер. Эта функция не возвращает результат немедленно. Для получения ответа от сервера требуется несколько секунд.

Поэтому, если вы вызываете эту функцию и присваиваете ее значение для некоторой переменной, она будет undefined не определено. Поскольку Javascript не знает, что функция обрабатывает некоторые операции async.

Итак, как мы справляемся с этим?

До этого поговорим немного о истории.

Перед обещаниями - promise программисты использовали обратные вызовы - callbacks. Обратные вызовы являются нормальными функциями в Javascript, который выполняется, когда операция async завершена.

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

Таким образом, в приведенном выше случае Javascript не останавливает выполнение, пока мы не получим ответ от API. И мы определили функцию callback, которая будет выполнена после получения ответа. Думаю, это понятно.

Итак, что такое обещания - promises





Обещания promises- это объекты, которые помогают выполнять асинхронные операции.

Технически это объекты, которые представляют собой завершение операции async. (Если вы что-то не получите, то остаетесь на некоторое время.)

Прежде чем объяснять, как определить обещание promises, я объясню жизненный цикл обещания.

У нас есть три состояния в promises.
  1. Pending Ожидание: в этом состоянии обещание (promises) просто выполняет операцию async. Например, он делает некоторый запрос API на сервер или загружает некоторые изображения из cdn. Из этого состояния (promises) обещания можно перейти либо к Fulfilled - исполнению, либо к Rejected - отказу.
  2. Fulfilled : Если (promises) обещание достигло этого состояния, значит, операция async завершена, и у нас есть выходные данные - output. Например, у нас есть ответ от API.
  3. Rejected : Если (promises) обещание достигло этого состояния, это означает, что асинхронная операция не увенчалась успехом, и у нас есть ошибка, из-за которой операция завершилась неудачей.


Хорошо ... Давайте посмотрим на некий код.

const apiCall = new Promise(function(resolve, reject) {
 // async operation is defined here...
});



Promise определяется созданием конструктора с использованием ключевого слова - new. Тогда конструктор будет иметь функцию (мы называем ее executor function - функцией-исполнителем).

Асинхронная операция определяется внутри функции-исполнителя.

Обратите внимание, что функция-исполнитель имеет два параметра, которые resolve - разрешают или reject - отклоняют.

Первое решение параметра - фактически функция. Он вызывается внутри функции-исполнителя и представляет, что операция async успешна, и мы получаем результат. Функция Resolve помогает обещать перейти от pending -ожидаемого к fulfilled - исполненному состоянию. Надеюсь, вы поняли. :)

Подобно решению, reject также является функцией. Он также вызывается внутри функции-исполнителя, и он показывает, что операция async не выполняется, и мы получили ошибку. Отклонение помогает обещанию перейти от ожидания - pending к отклонению - reject. :)

const apiCall = new Promise(function(resolve, reject) {
 if ( API request to get some data ) {
  resolve("The request is successful and the response is "+ response);
 }
 else {
  reject("The request is not successful. The error is "+error);
 }
});



В приведенном выше коде вы можете видеть, что мы выполнили некоторую асинхронную операцию внутри функции-исполнителя. Затем вызывается функция resolve разрешения, если мы получаем ответ от сервера. И если есть некоторая ошибка, то функция reject error вызывается с сообщением об ошибке.

Мы сделали определение promises - обещания. Давайте посмотрим, как выполнить promises - обещание и обработать результат.

// calling the promise.
apiCall



Это оно. мы сделали. :) :)

Просто шучу. Это еще не конец.

В приведенном выше коде функция вызывается и выполняется обещание (т. Е. Выполняется executor function исполнительская функция). Затем вызывается функция resolve - разрешения или reject -отклонения на основе вывода - output.

Но вы можете видеть, что мы не обрабатывали результат, полученный из promise- обещания.

Например, если мы получим ответ от API, мы должны обработать ответ. Или, если мы получим ошибку, нам нужно правильно ее обработать.

Итак, как мы справляемся с этим?

Мы используем обработчики - handlers для получения результата от обещания.

Обработчики (handlers)- это просто функции, которые выполняются, когда происходит какое-то событие, например, нажатие кнопки, перемещение курсора и т. д.

Таким образом, мы можем использовать обработчики для обработки при вызове функции resolve - разрешения или reject - отклонения функции.

Просто. :)

Давайте посмотрим, такой код:

// calling the promise with some handlers.
apiCall.then(function(x) {console.log(x); })



В приведенном выше коде мы приложили обработчик (handler) к (then) обещанию (promise). Затем - then обработчик получает параметр функции. Тогда сам параметр функции имеет параметр x.

Так что происходит.

Обработчик then выполняет function parameter, когда функция resolve вызывается внутри обещания (promise).

Я попытаюсь объяснить это снова.

Обработчик then ищет случай, когда вызывается функция разрешения. Поэтому, когда функция разрешенияresolve вызывается, then обработчик выполняет свой параметр функции.

apiCall.then(function(x) {console.log(x); })
// Output
The request is successful and the response is {name: "Jon Snow"}



Аналогично, есть еще один catch захват обработчика.

Обработчик catch ищет функцию отклонения - reject .

Функция catch выполняет свой функциональный параметр при вызове функции reject.

apiCall.then(function(x) {console.log(x); }).catch(function(x) {console.log(x); })
// Assuming the request is not successful ( reject function is called in the promise. )
Output:
The request is not successful



Думаю, вы поняли.

Вышеприведенный код недостаточно читабельен. Так давайте попробуем:

apiCall
.then(function(x) {
 console.log(x); 
})
.catch(function(x) {
 console.log(x);
}) 



Теперь это можно прочитать. Большинство программистов пишут это так.

Хорошо. Поэтому я думаю, что вы прошли долгий путь.

Давайте резюмировать..
  1. Promise определяется с помощью нового ключевого слова с параметром функции. Тогда сама функция имеет два параметра функции, которые разрешают - resolve и отклоняют - reject.
  2. Функция resolve будет вызвана, когда операция выполнена успешно.
  3. Функция reject - когда операция даст сбой.
  4. Обработчик then ищет функцию resolve разрешения.
  5. Обработчик catch ищет функцию reject отклонения.
  6. Удостоверьтесь в удобочитаемости кода :) :)
Вот рабочий пример - jsfiddle.net. Пожалуйста, попрактикуйтесь, если вы новичок в этом.


Надеюсь,что вы поймете пример. Тогда вперед.

Async / Await

Если вы понимаете Promise, то Async / Await довольно легко. И если вы не поняли Promise, Async / Await может помочь вам понять это. Может быть, вы также сможете получить ясный выход из Promise - обещаний. :)

Async

Ключевое слово Async позволяет любой функции возвращать только обещания.

Например, рассмотрите приведенный ниже код

async function hello() {
 return "Hello Promise..!"
}



Function hello вернет Promise - обещание.

Вышеприведенный код эквивалентен приведенному ниже коду.

function hello() {
 return new Promise(function(resolve, reject) {
 // executor function body.
 });
}



Так проще?

Другой пример:

async function hello(a, b) {
 if (a < b) {
  return "Greater";
 }
 else {
  return new Error("Not Greater");
 }
}
hello(14, 10)
.then(function(x) {
 console.log("Good..! " + x); 
})
.catch(function(x) {
 console.log("Oops..! " + x); 
})
Output:
Oops..! Not Greater. 
// if you call hello(4, 10) you get "Good..! Greater"



В приведенном выше коде мы определили функцию async и вернули некоторое значение или вернули некоторую ошибку.

Если вы возвращаете некоторое значение в async-функции, это эквивалентно вызову функции resolve разрешения.

Если вы возвращаете некоторую ошибку, вызывая error constructor using ‘new’ (конструктор ошибок с помощью «new»), то это эквивалентно функции reject - отклонения.

Не забывайте, что функция async вернет обещание. Поэтому, конечно, вы можете вызвать функцию resolve - разрешения и отклонения - reject внутри функции async.

Посмотрим, как это работает.

async function Max(a, b) {
 if (a > b) {
  return Promise.resolve("Success");
 }
 else {
  return Promise.reject("Error");
 }
}
Max(4, 10)
.then(function(x) {
 console.log("Good " + x); 
})
.catch(function(x) {
 console.log("Oops " + x); 
});
Output:
Oops Error
// If we pass Max(14, 10) then we should get "Good Success" :)



Await

Как следует из названия, это заставляет Javascript ждать завершения операции. Предположим, вы делаете запрос API с ключевым словом await. Это заставляет Javascript ждать, пока вы не получите ответ от конечной точки. И затем он возобновляет выполнение.

Хорошо .. Пойдем глубже

Ожидание await может использоваться только внутри асинхронной функции. Он не работает вне асинхронной функции
Давайте посмотрим пример:

async function hello() {
 let response = await fetch('https://api.github.com/');
 // above line fetches the response from the given API endpoint.
 return response;
}
hello()
.then(function(x) {
 console.log(x); 
});
...
...
Output:
Response from the API.



В приведенном выше коде вы можете видеть, что мы использовали await ожидание при получении ответа от API.

Операция выборки (fetch) может занять несколько секунд, чтобы получить ответ так, что выполнение будет остановлено и возобновлено позже.

Обратите внимание, что ожидание операции останавливает выполнение внутри функции hello. Остающийся код вне функции hello не будет затронут. Выполнение продолжается вне функции. И когда мы получаем ответ, выполняется параметр функции .then внутри обработчика .

Надеюсь, вы поняли.

Давайте посмотрим пример

jsfiddle.net



В приведенном выше примере вы можете видеть, что мы использовали await функцию для getResponse. И getResponse вернет результат или ошибку через 5 секунд. Таким образом, до этого времени выполнение приостанавливается, а затем возвращается ответ.

Давайте посмотрим пример в реальном времени.

jsfiddle.net



В приведенном выше примере вы можете видеть, что мы использовали несколько ожиданий - awaits. Поэтому для каждого ожидания выполнение останавливается до получения ответа, а затем возобновляется.

Попробуйте использовать тот же пример с некорректным URL-адресом. Вы можете видеть, что ошибка поднята.

Обработка ошибок очень проста в асинхронной async функции. Если ошибка возникает внутри функции async или когда ошибка возникает из других функций, которые вызываются внутри async, используя await, вызывается функция reject - отклонения. Просто.

Надеюсь тебе понравилось. Я рассмотрю гораздо более интересные темы, такие как карта массива, фильтр массивов, сокращение и т. д. В следующей части.




Автор: Srebalaji Thirumalai.
Перевод: Kolesnikov Yaroslav




                                                                                                                                                             

вторник, 1 мая 2018 г.

ES6 для начинающих. (1)

В этом посте я расскажу о некоторых новых функциях в ES6. Это будет полезно, если вы новичок в ES6 или изучаете front-end frameworks.




Темы, которые я расскажу в этом посте
  1. Let и Const.
  2. Стрелочные функции.
  3. Параметры по умолчанию.
  4. Цикл for.
  5. Spread атрибуты - Spread attributes.
  6. Maps.
  7. Sets.
  8. Статические методы.
  9. Геттеры и Сеттеры - Getters and Setters.


Let

Let аналогичен var, но let имеет область видимости. let доступен только на уровне блока, где он определен.


if (true) {
 let a = 40;
 console.log(a); //40
}
console.log(a); //



В приведенном выше примере переменная 'a' определяется внутри оператора If и поэтому недоступна вне функции.

Другой пример:

let a = 50;
let b = 100;
if (true) {
 let a = 60;
 var c = 10;
 console.log(a/c); // 6
 console.log(b/c); // 10
}
console.log(c); // 10
console.log(a); // 50



Const

Константа используется для назначения постоянной переменной переменной. И значение её не может быть изменено. Это фиксированная переменная.


const a = 50;
a = 60; // shows error. You cannot change the value of const.
const b = "Constant variable";
b = "Assigning new value"; // покажет ошибку.



Рассмотрим другой пример.
const LANGUAGES = ['Js', 'Ruby', 'Python', 'Go'];
LANGUAGES = "Javascript"; // покажет ошибку
LANGUAGES.push('Java'); // сработает.
console.log(LANGUAGES); // ['Js', 'Ruby', 'Python', 'Go', 'Java']


Это может казатся немного запутанным.

Рассмотрим это таким образом. Всякий раз, когда вы определяете константную (постоянную) переменную, Javascript ссылается на адрес значения переменной. В нашем примере переменная 'LANGUAGES' фактически ссылается на память, выделенную для массива. Поэтому вы не можете изменить эту переменную, чтобы позже ссылаться на другую ячейку памяти. Всюду по программе она ссылается только на массив.

Стрелочные функции - Arrow Function

Функции в ES6 немного изменились. Я имею в виду синтаксис.


// Old Syntax
function oldOne() {
 console.log("Hello World..!");
}
// New Syntax
var newOne = () => {
 console.log("Hello World..!");
}



Новый синтаксис может немного запутать. Но я попытаюсь объяснить синтаксис.

Есть две части синтаксиса.

Первая часть просто объявляет переменную и присваивает ей функцию (). Она просто говорит, что переменная на самом деле является функцией.

Затем вторая часть объявляет часть тела функции. Часть стрелки с фигурными скобками определяет часть тела.

Другой пример с параметрами.

let NewOneWithParameters = (a, b) => {
 console.log(a+b); // 30
}
NewOneWithParameters(10, 20);



Я не думаю, что мне нужно давать объяснение этому. Это просто.

Более подробно об этих функциях я рассказываю в посте ES6: Стрелочные функции (XI).

Параметры по умолчанию - Default Parameters

Если вы знакомы с другими языками программирования, такими как Ruby, Python, то параметры по умолчанию для вас не новы.

Параметры по умолчанию - это параметры, которые задаются по умолчанию при объявлении функции. Но это значение могут быть изменены при вызове функции.

Пример:

let Func = (a, b = 10) => {
 return a + b; 
}
Func(20); // 20 + 10 = 30



В приведенном выше примере мы передаем только один параметр. Функция использует параметр по умолчанию и выполняет функцию.

Рассмотрим другой пример:

Func(20, 50); // 20 + 50 = 70



В приведенном выше примере функция принимает два параметра, а второй параметр заменяет параметр по умолчанию.

Рассмотрим другой пример:

let NotWorkingFunction = (a = 10, b) => {
 return a + b;
}
NotWorkingFunction(20); // NAN. Not gonna work.



Когда вы вызываете функцию с параметрами, они назначаются в порядке. Первое значение присваивается первому параметру, а второе значение присваивается второму параметру и т. д.

В приведенном выше примере значение 20 присваивается параметру «a», а «b» не имеет значения. Таким образом, мы не получаем никакой информации.

Но,

NotWorkingFunction(20, 30); // 50;



Работает отлично.

Цикл for - For of loop

Цикл for очень похож на цикл for in в легкой модификации. Цикл for проходит через список элементов (например, типа Array) и возвращает элементы (а не их индекс) один за другим.


let arr = [2,3,4,1];
for (let value of arr) {
 console.log(value);
}
Output:
2
3
4
1



Обратите внимание, что переменная 'value' выводит каждый элемент в массиве, а не индекс.

Другой пример

let string = "Javascript";
for (let char of string) {
 console.log(char);
}
Output:
J
a
v
a
s
c
r
i
p
t



Да. Он также работает для строки.

Spread атрибуты - Spread attributes

Атрибуты спреда помогают распространять выражение, как следует из названия. Простыми словами он преобразует список элементов в массив и наоборот.

Пример без атрибутов распространения - Spread attributes:

let SumElements = (arr) => {
 console.log(arr); // [10, 20, 40, 60, 90]
let sum = 0;
 for (let element of arr) {
 sum += element;
 }
 console.log(sum); // 220. 
}
SumElements([10, 20, 40, 60, 90]);



Вышеприведенный пример прост. Мы объявляем функцию принимающую массив как параметр и возвращать его сумму. Это просто.

Теперь рассмотрим тот же пример с атрибутами распространения

let SumElements = (...arr) => {
 console.log(arr); // [10, 20, 40, 60, 90]
let sum = 0;
 for (let element of arr) {
 sum += element;
 }
 console.log(sum); // 220. 
}
SumElements(10, 20, 40, 60, 90); // Note we are not passing array here. Instead we are passing the elements as arguments.



В приведенном выше примере атрибут spread преобразует список элементов (например, параметры) в массив.

Другой пример:

Math.max(10, 20, 60, 100, 50, 200); // returns 200.



Math.max - простой метод, который возвращает максимальный элемент из данного списка. Он не принимает массив.


let arr = [10, 20, 60];
Math.max(arr); // Shows error. Doesn't accept an array.



Так что давайте использовать нашего спасителя.

let arr = [10, 20, 60];
Math.max(...arr); // 60



В приведенном выше примере атрибут spread преобразует массив в список элементов.

Maps

Map содержит пары ключ-значение. Он похож на массив, но мы можем определить наш собственный индекс. И индексы уникальны в map.

Пример:

var NewMap = new Map();
NewMap.set('name', 'John'); 
NewMap.set('id', 2345796);
NewMap.set('interest', ['js', 'ruby', 'python']);
NewMap.get('name'); // John
NewMap.get('id'); // 2345796
NewMap.get('interest'); // ['js', 'ruby', 'python']



Я думаю, что приведенный выше пример является самоочевидным.

Другие интересные особенности map - все его индексы уникальны. И мы можем использовать любое значение в качестве ключа или значения.

Пример:

var map = new Map();
map.set('name', 'John');
map.set('name', 'Andy');
map.set(1, 'number one');
map.set(NaN, 'No value');
map.get('name'); // Andy. Note John is replaced by Andy.
map.get(1); // number one
map.get(NaN); // No value



Другие полезные методы, используемые в Map:


var map = new Map();
map.set('name', 'John');
map.set('id', 10);
map.size; // 2. Returns the size of the map.
map.keys(); // outputs only the keys. 
map.values(); // outputs only the values.
for (let key of map.keys()) {
 console.log(key);
}
Output:
name
id



В приведенном выше примере map.keys () возвращает ключи map, но возвращает его в объекте Iterator. Это означает, что он не может отображаться так, как есть. Он должен отображаться только путем итерации.

Другой пример:

var map = new Map();
for (let element of map) {
 console.log(element);
}
Output:
['name', 'John']
['id', 10]



Вышеприведенный пример является самоочевидным. Цикл for..of выводит пару ключ-значение в массиве.

Мы можем немного его оптимизировать.

var map = new Map();
for (let [key, value] of map) {
 console.log(key+" - "+value);
}
Output:
name - John
id - 10



Наборы - Sets.

Наборы используются для хранения уникальных значений любого типа. Просто..!

Пример:

var sets = new Set();
sets.add('a');
sets.add('b');
sets.add('a'); // We are adding duplicate value.
for (let element of sets) {
 console.log(element);
}
Output:
a
b



Обратите внимание, что не отображаются повторяющиеся значения. Отображаются уникальные значения.

А также обратите внимание, что наборы являются итерируемыми объектами. Нам нужно перебирать элементы для отображения.

Другие полезные методы:

var sets = New Set([1,5,6,8,9]);
sets.size; // returns 5. Size of the set.
sets.has(1); // returns true. 
sets.has(10); // returns false.



В приведенном выше примере размер не требует пояснений. Существует еще один метод has, который возвращает логическое значение, основанное на том, присутствует ли данный элемент в наборе или нет.

Статические методы - Static methods

Большинство из вас уже слышали о статических методах. Статические методы вводятся в ES6. И это довольно легко определить и использовать.

Пример:

class Example {
 static Callme() {
 console.log("Static method");
 }
}
Example.Callme();
Output:
Static method



Обратите внимание, что я не использовал ключевое слово function внутри класса.

И я могу вызвать функцию без создания какого-либо экземпляра для класса.

Геттеры и сеттеры - Getters and Setters

Getters и seters и одна из полезных функций, введенных в ES6. Это пригодится, если вы используете классы в JS.

Пример без геттеров и сеттеров:

class People {
constructor(name) {
 this.name = name;
 }
 getName() {
 return this.name;
 }
 setName(name) {
 this.name = name;
 }
}
let person = new People("Jon Snow");
console.log(person.getName());
person.setName("Dany");
console.log(person.getName());
Output:
Jon Snow
Dany



Я думаю, что приведенный выше пример не требует пояснений. У нас есть две функции в классе Люди, которые помогают установить и получить имя человека.

Пример с геттерами и сеттерами

class People {
constructor(name) {
 this.name = name;
 }
 get Name() {
 return this.name;
 }
 set Name(name) {
 this.name = name;
 }
}
let person = new People("Jon Snow");
console.log(person.Name);
person.Name = "Dany";
console.log(person.Name);



В приведенном выше примере вы можете увидеть, что внутри класса People есть две функции «get» и «set». Свойство «get» используется для получения значения переменной, а свойство «set» используется для установки значения переменной.

И вы можете видеть, что функция getName вызывается без скобок. И функция setName вызывается без скобок, и это точно так же, как присвоение значения переменной.

Спасибо за ваше время. Надеюсь, вам понравилась статья. :) :) promises and async/await

Надеюсь тебе понравилось. Я рассмотрю гораздо более интересные темы, такие как promises and async/await и т. д. В следующей части.




Автор: Srebalaji Thirumalai.
Перевод: Kolesnikov Yaroslav




                                                                                                                                                             

четверг, 26 апреля 2018 г.

Вопросы для собеседования на вакансию js-разработчика.

Идеальное руководство для прохождения интервью JavaScript- разработчика.

Интервью с JavaScript (JS) непросты. Я принимаю это, вы принимаете его, и каждый делает это. Количество возможностей вопросов, которые можно задать в интервью для JavaScript, велико. Как можно пройти интервью JS? Когда начать? Эта статья - попытка проинструктировать всех начинающих разработчиков JavaScript, чтобы углубить их знания JS, зная основные концепции. Это первые шаги, которые нужно предпринять, по крайней мере, для интервью JS. Если я кандидат, я хорошо готовлю эти концепции. Если я интервьюер, я предполагаю, что вы знаете, что бы продолжить дальше.

Если вы не знаете автора,то он является разработчиком полного стека с опытом работы с Python, Go & JavaScript. Недавно он написал книгу- "Building RESTful Web services with Go"!

Это руководство является отправной точкой, но не является толчком для разработчика JS. Это его / ее обязанность готовиться к гораздо более жестким интервью. Им также необходимо иметь в виду, что вопросы собеседования также могут быть связаны с доменом и технологиями, которые они работали (например: React JS, WebPack, Node JS и т. Д.).

Здесь мы представляем основные элементы JS, которые вы должны хорошо разбираться, чтобы назвать себя хорошим разработчиком JavaScript.

Прекрасный разработчик JS может быть отличным разработчиком React, но обратное не гарантируется. К сожалению, JS имеет плохую репутацию для производства бесчисленных сценаристов с отсутствием дисциплины (частично верно). JavaScript позволяет разработчикам делать что-либо, без полного понимания. Это тоже забавно. Немногие великие программисты на JavaScript, такие как Джон Ресиг (создатель, jQuery), Брендан Эйч (создатель, JS), и Ларс Бак (команда Google Chrome) понимали язык от и до. Успешный программист JS всегда читает простой JS-код из библиотек. Многие говорят, что очень сложно найти хорошего разработчика JavaScript.

«Виртуальные машины - странный зверь. Идеального решения нет, вместо этого вы оптимизируете «идеальное место». Там много мастерства. Это долгая игра, вы не можете сгореть »- Ларс Бак, Google


Чтобы показать вам сложность интервью JS, с первого взгляда попытайтесь выяснить исход этого заявления JS.

console.log(2.0 == “2” == new Boolean(true) == “1”)

9 человек из 10 говорят, что это печатает false. Но он печатает true. Почему? См. здесь.



JavaScript- язык жесткий. Мы не можем сделать многого, если интервьюер слишком умный, чтобы задавать такие вопросы, как выше. Но что мы можем сделать? Глубоко изучите эти одиннадцать основных элементов, чтобы превратить JS-интервью, в благоприятное для вас.

1) Хорошо понимать функции JS

Функции - это сливки JavaScript. Это граждане первого класса. Без глубокого знания функций JS, ваши знания сильно ограничены. Функция JS больше чем, просто функция. В отличие от других языков, функция может быть назначена переменной, переданной как аргумент другой функции и также может быть возвращена из другой. Следовательно, это гражданин первого класса в JS.

Я не собираюсь объяснять, что здесь является функцией, но знаете ли вы, что малые вещи тоже могут вас удивить? Как это!


console.log(square(5));
/* ... */
function square(n) { return n * n; }



Этот фрагмент кода выведет 25. True! См. Второй фрагмент кода


console.log(square(5));
 
var square = function(n) { 
  return n * n; 
}



На первый взгляд, у вас может возникнуть соблазн сказать, что это тоже печатает 25. False! Но вместо этого вы получите ошибку уже при обработке кода.

TypeError: square is not a function

В JavaScript, если вы определяете функцию как переменную, имя переменной будет поднято (hoisted), и вы не сможете получить доступ, пока выполнение JS не встретит её объявления . Вы не удивлены?

Оставим это. Возможно, вы часто видели этот синтаксис где-то в некотором коде.


var simpleLibrary = function() {
   var simpleLibrary = {
        a,
        b,
        add: function(a, b) {
            return a + b;
        },
        subtract: function(a, b) {
            return a - b;   
        }
   }
  return simpleLibrary;
}();



Почему люди делают такие странные вещи? Это функциональная переменная, которая имеет инкапсулированные переменные и функции, которые не загрязняют глобальную область. Библиотеки от jQuery до Lodash используют эту технику, чтобы предоставить вам переменные типа $ и т. Д.

То, что я здесь представил, - «учиться хорошо». Мы используем много тонких ловушек. Прочитайте хорошо написанную запись Mozilla о функциях. Functions

2) Понимание bind, apply и call

Эти функции вы можете увидеть во всех известных библиотеках. Они позволяют делать что-то названное currying, используя их мы можем скомпоновать функциональность в разные функции. Хороший разработчик JavaScript может рассказать вам о них в любое время дня и ночи.

В принципе, это прототип методов функций для изменения их поведения для достижения чего-то. Согласно Чаду, разработчику JS, использование похоже на это:

Используйте .bind (), когда вы хотите, чтобы эта функция позже вызывалась с определенным контекстом, полезным в событиях. Используйте .call () или .apply (), когда вы хотите немедленно вызвать функцию, с изменением контекста.


Бережный вызов (saving call)

Давайте посмотрим, что означает это утверждение! Предположим, ваш учитель математики попросил вас создать библиотеку и отправить ее. Вы написали абстрактную библиотеку, которая находит область и окружность круга.


var mathLib = {
    pi: 3.14,
    area: function(r) {
        return this.pi * r * r;
    },
    circumference: function(r) {
        return 2 * this.pi * r;
    }
};



Вы отправили библиотеку профессору. Теперь пришло время представить код, который вызывает эту математическую библиотеку.


mathLib.area(2);
12.56



Представляя образцы второго кода, вы нашли в рекомендациях, что профессор попросил вас использовать постоянный pi с точностью до пяти десятичных знаков. О Боже! Вы только что использовали 3.14, а не 3.14159. Теперь у вас нет возможности отправить библиотеку по истечении крайнего срока. Функция вызова - Call JS спасет вас. Просто вызвать.call() своему коду таким образом:


mathLib.area.call({pi: 3.14159}, 2);



и функция принимает ваше новое значение pi на лету. Выведет:


12.56636



Это сделает вашего профессора счастливым! Если вы заметили, функция вызова - Call принимает два аргумента:
  • Context - контекст.
  • Function arguments - аргументы функции.


Контекст - это объект, который заменяет это ключевое слово внутри функции области. Позже аргументы передаются как аргументы функции. Для Ex:


var cylinder = {
    pi: 3.14,
    volume: function(r, h) {
        return this.pi * r * r * h;
    }
};



Вызов Call выглядит следующим образом:


cylinder.volume.call({pi: 3.14159}, 2, 6);
75.39815999999999



Вы увидели, что эти аргументы функции передаются в качестве последующих аргументов после объекта контекста.

Apply точно также, только вместо аргументов передает список:


cylinder.volume.apply({pi: 3.14159}, [2, 6]);
75.39815999999999



Если вы знаете call, вы знаете apply и наоборот. Теперь, что такое bind?

Bind придает новое значение данной функции. В случае с Bind функция не запускается мгновенно, как например Call или Apply.


var newVolume = cylinder.volume.bind({pi: 3.14159}); // This is not instant call
// After some long time, somewhere in the wild 
newVolume(2,6); // Now pi is 3.14159



Какая польза от Bind? Это позволяет нам вводить контекст в функцию, которая возвращает новую функцию с обновленным контекстом. Это означает, что эта переменная будет использоваться пользователем. Это очень полезно при работе с событиями JavaScript.

Вы должны знать эти три функции для создания функциональности в JavaScript.


3) Хорошо понимать области видимости JavaScript (И скрытые области также)

Область видимости (scope) JavaScript - это ящик пандоры. Сотни сложных вопросов интервью могут быть сформулированы из этой единой концепции. Существует три вида областей видимости (scope):

  • Global scope - глобальная
  • Local Scope/Function scope - локальная (функциональная).
  • Block scope(Introduced in ES6)- блочная. Представленная в ES6


Глобальная область - это то, что мы обычно делаем:


x = 10;
function Foo() {
  console.log(x); // Prints 10
}
Foo()



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


pi = 3.14;
function circumference(radius) {    
     pi = 3.14159;
     console.log(2 * pi * radius); // Prints "12.56636" not "12.56"
}
circumference(2);



Стандарт ES16 ввел новую область блока, которая ограничивает область переменной для данного блока внутри скобок.


var a = 10;

function Foo() {
  if (true) {
    let a = 4;
  }

  alert(a); // alerts '10' because the 'let' keyword
}
Foo();



Функции и условия рассматриваются как блоки. Вышеприведенный пример должен предупредить 4, поскольку выполняются условные операторы. Но ES6 уничтожает область блоков переменных, и область охвата перешла в глобальную.

Теперь наступает просто магия области видимости (scope). Это может быть достигнуто с помощью закрытий (closures). Закрытие (closures) JavaScript - это функция, которая возвращает другую функцию.

Если кто-то задаст вам этот вопрос. Напишите пример, который принимает строку и сразу возвращает символ. Если задана новая строка, она должна заменить старую. Это просто называется генератором.


function generator(input) {
      var index = 0;
      return {
           next: function() {
                   if (index < input.length) {
                        index += 1;
                        return input[index - 1];
                   }
                   return "";
           } 
      }
}



Исполнение идет таким образом!


var mygenerator = generator("boomerang");
mygenerator.next(); // returns "b"
mygenerator.next() // returns "o"
mygenerator = generator("toon");
mygenerator.next(); // returns "t"



Здесь область видимости (scope) играет важную роль. Закрытие - это функция, которая возвращает другую функцию и обертывает данные. Вышеуказанный генератор строк представляет замыкание. Значение индекса сохраняется между несколькими вызовами функций. Внутренняя функция может обращаться к переменным, определенным в родительской функции. Это разная область. Если вы определили еще одну функцию в функции второго уровня, которая может получить доступ ко всем родительским переменным.

Область видимости (scope) JavaScript может доставить вам массу проблем! Стоит полностью понимать это.


4) Понимайте это ключевое слово well (глобальное, функциональное и предметное пространство - global, function and object scopes)

В JavaScript мы всегда составляем код с функциями и объектами. Если вы используете браузер, то в глобальном контексте он ссылается на объект окна (window object). Я имею в виду, что это будет оцениваться как true, если вы сейчас откроете консоль браузера и введите это.


this === window;



Когда изменяется контекст и область видимости (scope) программных изменений, this в этом конкретном пункте изменяется соответствующим образом. Теперь см. this в локальном контексте:

function Foo(){
  console.log(this.a);
}
var food = {a: "Magical this"};
Foo.call(food); // food is this



Теперь у вас возникнет соблазн предсказать этот результат.


function Foo(){
    console.log(this); // prints {}?
}



Нет, не будет. Потому что здесь this ссылается на глобальный объект. Помните, каков бы ни был родительский охват, он будет унаследован дочерним элементом. Таким образом, здесь будет выведен объект окна (window object). Три метода, которые мы обсуждали, фактически используются для установки this объекта.

Теперь идет последний тип this - this в области объекта. Вот так:


var person = {
    name: "Stranger",
    age: 24,
    get identity() {
        return {who: this.name, howOld: this.age};
    }
}



Я просто использовал синтаксис getter, который является функцией, которую можно вызвать как переменную.


person.identity; // returns {who: "Stranger", howOld: 24}



Здесь this фактически относится к самому объекту. И this, как мы уже говорили ранее, ведет себя по-разному в разных местах. Это следует очень хорошо знать.

5) Хорошо понимать объекты (Object.freeze, Object.seal)

Многие из нас знают такие объекты.


var marks = {physics: 98, maths:95, chemistry: 91};



Это пример объекта, в котором хранятся пары Key- ключи, Value - значения. Объекты JavaScripts имеют особое свойство хранить что-либо как значение. Это означает, что мы можем сохранить список, другой объект, функцию и т. д. В качестве значения. Почему бы и нет?

Вы можете создать объект таким образом:


var marks = {};
var marks = new Object();



Вы можете легко преобразовать заданный объект в строку JSON, а также преобразовать его обратно с помощью методов строкового и синтаксического анализа объектов JSON соответственно.


// returns "{"physics":98,"maths":95,"chemistry":91}"
JSON.stringify(marks);
// Get object from string
JSON.parse('{"physics":98,"maths":95,"chemistry":91}');



Итак, какие еще мелочи об объектах, которые вы должны знать? Простую итерацию объекта, используя Object.keys.


var highScore = 0; 
for (i of Object.keys(marks)) {
   if (marks[i] > highScore)
      highScore = marks[i];
}



Object.values возвращает список значений объекта.

Другими важными функциями для объекта являются:
  • Object.prototype(object)
  • Object.freeze(function)
  • Object.seal(function)


Object.prototype предоставляет более важные функции, которые имеют множество приложений. Некоторые из них:

Object.prototype.hasOwnProperty полезен, чтобы узнать, существует ли данное свойство / ключ в объекте.


marks.hasOwnProperty("physics"); // returns true
marks.hasOwnProperty("greek"); // returns false



Object.prototype.instanceof оценивает, является ли данный объект типом определенного прототипа (мы увидим их в следующем разделе, это функции).


function Car(make, model, year) {
  this.make = make;
  this.model = model;
  this.year = year;
}
var newCar = new Car('Honda', 'City', 2007);
console.log(newCar instanceof Car); // returns true



Теперь идут две другие функции.Object.freeze позволяет нам заморозить объект, чтобы существующие свойства не могли быть изменены.


var marks = {physics: 98, maths:95, chemistry: 91};
finalizedMarks = Object.freeze(marks);
finalizedMarks["physics"] = 86; // throws error in strict mode
console.log(marks); // {physics: 98, maths: 95, chemistry: 91}



Здесь мы пытаемся изменить значение свойства physics после замораживания объекта. Но JavaScript не позволит этого сделать. Мы можем определить, заблокирован ли данный объект или нет.


Object.isFrozen(finalizedMarks); // returns true



Object.seal немного отличается от freeze замораживания. Он позволяет изменять свойства, но не позволяет добавлять или удалять новые свойства или свойства.


var marks = {physics: 98, maths:95, chemistry: 91};
Object.seal(marks);
delete marks.chemistry; // returns false as operation failed
marks.physics = 95; // Works!
marks.greek = 86; // Will not add a new property



Мы также можем проверить, закрыт ли данный объект, используя этот


Object.isSealed(marks); // returns true



Существует множество других важных функций / методов, доступных для функции Global Object. Найдите их здесь. Object

6) Хорошо понимать прототипное наследование - Prototypical Inheritance

В традиционном JavaScript существует концепция скрытого наследования. Это использование технологии прототипирования. Все новые class syntax , которые вы видите в ES5, ES6 - это просто синтаксическое представление для базового прототипироания, лежащего в основе ООП. Создание класса в JavaScript, выполняется с помощью функции.


var animalGroups = {
  MAMMAL: 1,
  REPTILE: 2,
  AMPHIBIAN: 3,
  INVERTEBRATE: 4
};
function Animal(name, type) {
  this.name = name;
  this.type = type;
}
var dog = new Animal("dog", animalGroups.MAMMAL);
var crocodile = new Animal("crocodile", animalGroups.REPTILE);



Здесь мы создаем объекты для класса (используя новое ключевое слово). Мы можем добавить методы для данного класса (функции), подобные этому. Прикрепить метод класса, подобный this.


Animal.prototype.shout = function() {
    console.log(this.name + 'is ' + this.sound + 'ing...');
}



Здесь можно усомниться в правильности. В классе нет свойства звука - sound property. Да! вряд ли определяется sound property. Но таким образом это предназначено для передачи дочерними классами, которые наследуют класс далее.

В JavaScript наследование достигается таким образом.

function Dog(name, type) {
   Animal.call(this, name, type);
   this.sound = "bow";
}



Я определил еще одну специальную функцию под названием Dog. Здесь, чтобы наследовать класс Animal, нам нужно выполнить функцию вызова call (мы обсуждали ее ранее) с передачей this и других аргументов. Мы можем создать экземпляр German Shepard.


var pet = Dog("germanShepard", animalGroups.MAMMAL);
console.log(pet); // returns Dog {name: "germanShepard", type: 1, sound: "bow"}



Мы не назначаем имя и тип дочерней функции, мы вызываем супер функцию Animal и устанавливаем соответствующие свойства. Домашнее животное имеет свойства (имя, тип) родителя. Но как насчет методов. Наследуются ли они тоже? Давайте посмотрим!


pet.shout(); // Throws error



Как же так? Почему это произошло? Это происходит потому, что мы не сказали JavaScript, чтобы наследовать методы родительского класса. Как это исправить?


// Link prototype chains
Dog.prototype = Object.create(Animal.prototype);
var pet = new Dog("germanShepard", animalGroups.MAMMAL);
// Now shout method is available
pet.shout(); // germanShepard is bowing...



Теперь method доступен. Мы можем проверить, что является классом данного объекта в JavaScript, используя функцию object.constructor. Давайте посмотрим, что предсавляет класс нашего питомца - pet.


pet.constructor; // returns Animal



Это расплывчато. Animal - родительский класс. Но какой именно тип pet ? Это Dog type. Это происходит из-за конструктора Dog class.


Dog.prototype.constructor = Dog;



Эти четыре вещи, которые вы должны помнить о прототипическом наследовании.
  • Свойства класса связаны c this.
  • Методы класса связаны с прототипом объекта Object.prototype
  • Чтобы наследовать свойства, используйте функцию вызова call, передающую this объекта.
  • Чтобы наследовать методы, используйте Object.create для связывания прототипов родительского и дочернего
  • Всегда устанавливайте конструктор дочерних классов для получения правильного идентификатора его объектов.


Примечание. Это происходит под капотом даже с новым синтаксисом класса. Знание этих данных ценно для вашего знания JS.


В JS функция вызова - call и прототип объекта - Object.prototype обеспечивают наследование


7) Хорошо понимать обратные вызовы (callbacks) и обещания (promises)

Обратные вызовы (Callbacks)- это функции, выполняемые после выполнения операции ввода-вывода. Время, затрачиваемое на операцию ввода-вывода, может блокировать код, который не позволяет выполнять дальнейшее выполнение в Python / Ruby. Но в JavaScript из-за разрешенного асинхронного выполнения мы можем обеспечить обратные вызовы для асинхронных функций. Примером может служить вызов AJAX (XMLHttpRequest) из браузера на сервер, события, генерируемые мышью. клавиатуры и т. д. Пример


function reqListener () {
  console.log(this.responseText);
}

var req = new XMLHttpRequest();
req.addEventListener("load", reqListener);
req.open("GET", "http://www.example.org/example.txt");
req.send();



Здесь reqListener - это обратный вызов, который будет выполняться, когда запрос GET успешно возвращается.

Обещания (promises) - это аккуратные обертки для обратных вызовов, которые позволяют нам запускать асинхронный код элегантно. Я много обсуждал здесь обещания. Это также важный элемент, который должен быть известен всем в JS. Writing neat asynchronous Node JS code with Promises

8) Хорошо понимать регулярные выражения

У регулярных выражений много приложений. Обработка текста, соблюдение правил ввода данных и т. д. Разработчик JavaScript должен знать, как выполнять базовое Regex и решать проблемы. Regex - универсальная концепция. Мы здесь видим, как мы можем это сделать из JS.

Мы можем создать новое регулярное выражение, используя это


var re = /ar/;
var re = new RegExp('ar'); // This too works



Вышеприведенное регулярное выражение является выражением, которое соответствует заданному набору строк. Как только регулярное выражение определено, мы можем попытаться подобрать и увидеть соответствующую строку. мы можем сопоставить строки с помощью функции exec (exec function).


re.exec("car"); // returns ["ar", index: 1, input: "car"]
re.exec("cab"); // returns null



Существует несколько специальных классов символов, которые позволяют нам писать сложные регулярные выражения.

В RegEx существует много типов элементов. Некоторые из них:

  • Символы Ex:\ w - буквенно-цифровые, \ d - десятичные, \ D - не десятичные
  • Классы символов Ex: [x-y] в диапазоне от x до y, [^ x] не x
  • Квантификаторы Ex: +,?, * (Жадные и ленивые)
  • Границы Ex: ^ (начало ввода), $ (конец ввода)


Используя приведенные выше вещи, давайте проиллюстрируем несколько примеров.


/* Character class */
var re1 = /[AEIOU]/;
re1.exec("Oval"); // returns ["O", index: 0, input: "Oval"]
re1.exec("2456"); // null
var re2 = /[1-9]/;
re2.exec('mp4'); // returns ["4", index: 2, input: "mp4"]
/* Characters */
var re4 = /\d\D\w/;
re4.exec('1232W2sdf'); // returns ["2W2", index: 3, input: "1232W2sdf"]
re4.exec('W3q'); // returns null
/* Boundaries */
var re5 = /^\d\D\w/;
re5.exec('2W34'); // returns ["2W3", index: 0, input: "2W34"]
re5.exec('W34567'); // returns null
var re6 = /^[0-9]{5}-[0-9]{5}-[0-9]{5}$/;
re6.exec('23451-45242-99078'); // returns ["23451-45242-99078", index: 0, input: "23451-45242-99078"]
re6.exec('23451-abcd-efgh-ijkl'); // returns null
/* Quantifiers */
var re7 = /\d+\D+$/;
re7.exec('2abcd'); // returns ["2abcd", index: 0, input: "2abcd"]
re7.exec('23'); // returns null
re7.exec('2abcd3'); // returns null
var re8 = /<([\w]+).*>(.*?)<\/\1>/;
re8.exec('

Hello JS developer

'); //returns ["

Hello JS developer

", "p", "Hello JS developer", index: 0, input: "

Hello JS developer

"]


Для получения дополнительной информации о регулярном выражении, пройдите по ссылке Quick-Start: Regex Cheat Sheet.

Наряду с exec существуют и другие функции, а именно match, search и, replace доступны для поиска строки в другой с использованием регулярных выражений. Но эти функции должны использоваться в строковых выражениях.


"2345-678r9".match(/[a-z A-Z]/); // returns ["r", index: 8, input: "2345-678r9"]
"2345-678r9".replace(/[a-z A-Z]/, ""); // returns 2345-6789



Regex - важная тема, которую разработчики должны легко понимать для решения сложных задач.

9) Хорошо понимать Map, Reduce и Filter

Функциональное программирование - это тема обсуждения в эти дни. Многие языки программирования включают в себя функциональные концепции, такие как lambdas, в их новые версии (пример: Java> 7). В JavaScript поддержка конструкций функционального программирования существует в течение длительного времени. Есть три основные функции, которые нам нужно глубоко изучить. Математические функции принимают некоторый входной (input) и обратный вывод (return output). Чистая функция всегда возвращает тот же вывод output) для данного ввода (input). Функции, которые мы обсуждаем сейчас, также являются чистыми.

map

Функция map доступна в массиве JavaScript. Используя эту функцию, мы можем получить новый массив, применив функцию преобразования для каждого элемента в массиве. Общий синтаксис для работы map массива JS:


arr.map((elem){
    process(elem)
    return processedValue
}) // returns new array with each element processed



Предположим, есть несколько нежелательных символов, введенных в серийные ключи, с которыми мы работаем в последнее время. Нам нужно их удалить. Вместо удаления символа путем итерации и поиска мы можем использовать map для выполнения той же операции и получения массива результатов.


var data = ["2345-34r", "2e345-211", "543-67i4", "346-598"];
var re = /[a-z A-Z]/;
var cleanedData = data.map((elem) => {return elem.replace(re, "")});
console.log(cleanedData); // ["2345-34", "2345-211", "543-674", "346-598"]



Примечание. Мы использовали стрелочный синтаксис (arrow syntax) для определения функции в JavaScript ES6


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

Другими словами мы хотим выполнить определенные действия с каждым элементом массива.

reduce

Функция reduce урезает данный список до конечного результата. Мы также можем сделать то же самое, итерации массива и сохранение промежуточного результата в переменной. Но здесь это более чистый способ уменьшить массив до значения. Общий синтаксис для операции reduce JS:


arr.reduce((accumulator,
           currentValue,
           currentIndex) => {
           process(accumulator, currentValue)
           return intermediateValue/finalValue
}, initialAccumulatorValue) // returns reduced value



accumulator сохраняет промежуточное и конечное значение. CurrentIndex, currentValue - это индекс и значение элемента из массива соответственно. initialAccumulatorValue передает это значение в аргумент аккумулятора.

Одним из практических приложений для reduce может быть сглаживание массива массивов. Сглаживание (Flattening) преобразует внутренние массивы в один массив. Для Ex:


var arr = [[1, 2], [3, 4], [5, 6]];
var flattenedArray = [1, 2, 3, 4, 5, 6];



Мы можем добиться этого путем обычной итерации. Но, используя сокращение, это более читабельный и простой код. Магия!


var flattenedArray = arr.reduce((accumulator, currentValue) => {
    return accumulator.concat(currentValue);
}, []); // returns [1, 2, 3, 4, 5, 6]



filter

Это третий тип концепции функционального программирования. Он близок к map, поскольку он также обрабатывает каждый элемент в массиве и, наконец, возвращает другой массив (не возвращающий значение, как в сокращении). Длина фильтрованного массива может быть меньше или равна исходному массиву. Поскольку условие фильтрации, которое мы передаем, может исключать несколько / нулевых входов в выходном массиве. Общий синтаксис для работы filter JS:


arr.filter((elem) => {
   return true/false
})



Здесь elem - это элемент данных массива, и true / false следует возвращать из функции, чтобы указать включение / исключение фильтрованного элемента. Общим примером является фильтрация массива слов, который начинается и заканчивается заданными условиями. Предположим, мы должны отфильтровать массив слов, начинающийся с t и заканчивающийся на r.


var words = ["tiger", "toast", "boat", "tumor", "track", "bridge"]
var newData = words.filter((elem) => {
   return elem.startsWith('t') && elem.endsWith('r') ? true:false;
}); // returns ["tiger", "tumor"]



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

10) Понимать шаблоны обработки ошибок

Это самый малозанятый фрагмент JavaScript для многих разработчиков. Я вижу, что очень немногие разработчики говорят об обработке ошибок. Хороший подход к разработке всегда тщательно переносить JS-код вокруг блоков try / catch.

Николас К. Закас (Nicholas C. Zakas), инженер UI в Yahoo, сказал в 2008 году: "Всегда предполагайте, что ваш код не удастся. Невозможно правильно обработать события! Запишите их на сервер. Брось свои ошибки."

В JavaScript всякий раз, когда мы кодируем, мы всегда можем потерпеть неудачу. Для Ex:


$("button").click(function(){
    $.ajax({url: "user.json", success: function(result){
        updateUI(result["posts"]);
    }});
});



Здесь мы попадаем в ловушку, говоря, что результаты всегда будут объектом JSON. Иногда сервер может сбой, и вместо результата возвращается null. В этом случае null ["posts"] выдаст ошибку. Правильное обращение может быть таким!


$("button").click(function(){
    $.ajax({url: "user.json", success: function(result){
    
      try {     
        updateUI(result["posts"]);
       }
      catch(e) {
        // Custom functions
        logError();
        flashInfoMessage();      
      }
    }});
});



Функция logError предназначена для сообщения об ошибке на сервере. Вторая функция flashInfoMessage- это функция, которая отображает удобное для пользователя сообщение типа «Сервис недоступен в настоящее время» и т. д.

Николас говорит, что каждый раз, когда вы чувствуете, что-то неожиданное произойдет, вы будете ловить ошибки. Различают фатальные и нефатальные ошибки. Вышеприведенная ошибка связана с тем, что сервер backend упал, что является фатальным. Таким образом вы должны сообщить клиенту, что по какой-то причине служба отключена. В некоторых случаях это может быть не смертельным, но лучше уведомлять об этом. Чтобы создать такой код, сначала выведите ошибку, поймайте ее с событием ошибки на уровне объекта window, затем сделайте вызов API для регистрации этого сообщения на сервер.


reportErrorToServer = function (error) {
  $.ajax({type: "POST", 
          url: "http://api.xyz.com/report",
          data: error,
          success: function (result) {}
  });
}
// Window error event
window.addEventListener('error', function (e) {
  reportErrorToServer({message: e.message})
})}
function mainLogic() {
  // Somewhere you feel like fishy
  throw new Error("user feeds are having fewer fields than expected...");
}



Этот код в основном выполняет три функции:

  1. Слушайте ошибки на уровне окна (window).
  2. Всякий раз, когда возникает ошибка, делает вызов API (API call).
  3. Записывает ошибку на сервер.


Вы также можете использовать новую функцию Boolean (ES5, ES6), чтобы проверить, действительна ли переменная, а не null (или) не определена, прежде чем продолжить.


if (Boolean(someVariable)) {
// use variable now
} else {
    throw new Error("Custom message")
}



Всегда думайте, как обращаться с ошибками. Все может закончиться неудачей!

Другие вещи, чтобы знать (Hoisting, Event Bubbling)

Все вышеперечисленные концепции являются основными для разработчика JavaScript. Есть немного внутренних деталей, чтобы знать, что они могут быть действительно полезными. Вот как работает JavaScript-движок в браузере. Что такое Подъем -Hoisting и Событие Bubbling?

Hoisting

Подъем - это процесс выталкивания объявленных переменных в начало программы во время ее запуска. Для Ex:


doSomething(foo); // used before
var foo; // declared later



Когда вы делаете что-то выше на языке сценариев, таком как Python, он выдает ошибку. Вы должны сначала определить что-то (переменную, функцию), а уже потом использовать это. Несмотря на то, что JS является языком сценариев, у него есть механизм подъема. В этом механизме, во время работы программы, во время работы с программой Java VM делает две вещи:

  1. Сначала сканируйте программу, соберите все объявления переменных и функций и назначьте для нее пространства памяти.
  2. Запустите программу сейчас, заполнив их любыми значения переменных если нет, заполните undefined


В приведенном выше фрагменте кода console.log печатает "undefined". Это потому, что в первом проходе собрана переменная foo. VM ищет любое значение, определенное для переменной foo. Этот подъем может привести ко многим ситуациям кода JavaScript, где код может вызывать ошибки в некоторых местах и использовать неопределенное значения по умолчанию, в другом. Вы должны знать подъем hosting , чтобы очистить ваш код от двусмысленности! Несколько примеров! Hoisting

Event Bubbling

Теперь рассмотрим событие (Event Bubbling)! По словам Аруна П, старшего инженера-программиста:

«Event Bubbling - это два способа распространения событий в API DOM HTML, когда событие происходит в элементе внутри другого элемента, и оба элемента зарегистрировали обработчик для этого события. Режим распространения событий определяет, в каком порядке элементы получают событие ».


При барботировании событие сначала захватывается и обрабатывается самим внутренним элементом, а затем распространяется на внешние элементы. С захватом процесс идет обратным образом. Обычно мы прикрепляем событие к обработчику, используя функцию addEventListener.


addEventListener("click", handler, useCapture=false)



Третий аргумент useCapture - это ключ. Значение по умолчанию неверно. Таким образом, это будет пузырящая модель, в которой событие сначала обрабатывается самым внутренним элементом, и оно распространяется наружу, пока не достигнет родительского элемента. Если этот аргумент верен, он захватывает модель.

Для Ex: Bubbling Model


<div onClick="divHandler()">
    <ul onClick="ulHandler">
        <li id="foo"></li>
    </ul>
</div>
<script>
function handler() {
 // do something here
}
function divHandler(){}
function ulHandler(){}
document.getElementById("foo").addEventListener("click", handler)
</script>



Когда мы нажимаем элемент списка, порядок выполнения обработчиков подобен порядковому номеру (по умолчанию).

handler() => ulHandler() => divHandler()



На диаграмме обработчики последовательно запускаются наружу. Аналогично, модель захвата пытается инициировать события от родителя до щелчка элемента. Теперь измените эту строку в приведенном выше коде.


document.getElementById("foo").addEventListener("click", handler, true)



Порядок выполнения обработчиков будет следующим:

divHandler => ulHandler() => handler()



Вы должны понимать, что пузырь событий (event bubbling) (независимо от направления движения к родительскому элементу или к ребенку) должным образом реализует пользовательские интерфейсы (UI), чтобы избежать нежелательного поведения.

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








Рекомендации:

Inheritance in JavaScript

Object.prototype.constructor

Using XMLHttpRequest

Regular Expressions

What is event bubbling and capturing?

123-Essential-JavaScript-Interview-Question




Автор: Naren Arya, перевел Ярослав Колесников.                                                                                                                                                              

воскресенье, 22 апреля 2018 г.

FireFox: SNB Social Neworks Buttons.

Самый простой способ поделиться статьей, или страницей в соц.сетях, если у вас браузер Mozilla Firefox, это посто воспользоваться готовым расширением (Userscript)
Работаю с этим расширением уже более полугода никаких проблем не выявил. Написал его для SMM - менеджеров нашей компании, и теперь готов представить его в открытый доступ для совместного, безвозмездного использования.




Расширение может быть легко дополнено "кнопками" других социальных сетей. Буду очень благодарен вам за отзывы и рекомендации.
Итак, приступим!

Требования к "железу"

  1. Браузер Mozilla Firefox версии 57.0 и выше. Хотя, я думаю, что будет работать с любой версией, где можно запустить код.
  2. Операционная система Windows (32-bit or 64-bit). С другими не проверял.

Установка

  1. Идем на страницу Greasemonkey
  2. и нажимаем "Добавить".



  3. После этого на панели инструментов справа появится значок - голова обезьянки. Щелкаем по ней и выбираем пункт New User Script.




  4. Скачиваем расширение с сайта gitHub, или с моего диска Google Drive. Открываем файл snb-firefox-social-networks-buttons.js и копируем оттуда все - Ctrl + A -> Ctrl + C
  5. О том. как клонировать репозиторий с gitHub вы можете вспомнить пройдя по ссылке. Я рассказывал об этом в своем посте "Клонирование репозитория GitHub на компьютер"

  6. Откроется новое окно. Удаляем оттуда все полностью и на это место вставляем код расширения из файла snb-firefox-social-networks-buttons.js все. Для удобства выделения всего текста (кода), вы можете пользоваться сочетанием клавиш Ctrl + A- выделить все, а для копирования Ctrl + С и для вставки кода - Ctrl + V




  7. Нажимаем на иконку справа вверху - "Сохранить", или нажимаем Ctrl + S и на этом установка расширения считается законченной.
  8. При первом запуске, возможно потребуется дать разрешение на всплывающие окна для сайтов. на которых вы будете использовать расширение. Это сообщение появится при попытке использования расширения в виде полоски вверху окна браузера.

Для отключения блокировки всплывающих окон Mozilla Firefox

  1. Нажать на сэндвич-меню -> , справа на панели браузера
  2. Выбрать пункт "Настройки" ->
  3. Слева, на панели, выбираем раздел "Приватность и защита"
  4. Прокручиваем вниз и находим раздел "Блокировать всплывающие окна". Снимаем галочку напротив, как на фото ниже.




Включить, или отключить расширение очень легко. Достаточно нажать на значок "Обезьянки" на панели браузера, сверху и выбрать режим "Enabled" -> Включено или "Disabled" -> Выключено.



Теперь, когда вы зайдете на страницу где нет кнопок социальных сетей, вы всегда сможете быстро поделиться ею со своими читателями, просто нажав:
Shift + G - для Google Plus,
Shift + F - для Facebook,
Shift + T - для Twitter.



Если вас интересует такое же расширение для Google Chrome, то я про него написал в посте Extension Social Networks Button (SNB)

                                                                                                                                                             


Хотите освоить самые современные методы написания React приложений? Надоели простые проекты? Нужны курсы, книги, руководства, индивидуальные занятия по React и не только? Хотите стать разработчиком полного цикла, освоить стек MERN, или вы только начинаете свой путь в программировании, и не знаете с чего начать, то пишите через форму связи, подписывайтесь на мой канал в Телеге, вступайте в группу на Facebook.Пишите мне - kolesnikovy70 почта gmail.com