JS

recursive, lexical scoping, setTimeout/setInterval

Agenda

  • lexical scoping
  • setTimeout
  • setInterval
  • Recursive function

Task

var userName = 'Vik';  

function sayHi(userName ) { 
    console.log(userName);
}

sayHi('Arni');

// ???

Task

function ask(question, yesCb, noCb) {

}

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

Task

Функция возвращает true, если параметр age больше 18.

В ином случае она запрашивает подтверждение через confirm и возвращает его результат:

lexical scoping

Все переменные внутри функции – это свойства специального внутреннего объекта LexicalEnvironment, который создаётся при её запуске.

function init() {
    let name = "Mozilla"; // name - локальная переменная, созданная в init

    function displayName() { // displayName() - внутренняя функция,
        alert(name); // displayName() использует переменную, объявленную в родительской функции    
    }

    displayName();    
}

init();

lexical scoping

  • Каждая функция при создании получает ссылку [[Scope]] на объект с переменными, в контексте которого была создана.
  • При запуске функции создаётся новый объект с переменными LexicalEnvironment. Он получает ссылку на внешний объект переменных из [[Scope]].
  • При поиске переменных он осуществляется сначала в текущем объекте переменных, а потом – по этой ссылке.

setTimeout/setInterval

Dellayed call of function

setTimeout(handler, dellay_in_ms);                // :)

setTimeout('alert("code")', dellay_in_ms);        // :(

setTimeout(function () {/*code*/}, dellay_in_ms); // :(

Interval works in same way but every period of time

SetTimeout context

// Be caerfully.

setTimeout(function () {
    console.log(this); // window
}, 0);

setTimeout event quie

// Ваш код
setTimeout(a, 0);

… 
// someLongCode
…

setTimeout(b, 0);
// Порядок выполнения

// someLongCode 

reflow() //browser native code
repaint()//browser native code

a()

reflow() //browser native code 
repaint() //browser native code 

b()

setTimeout - cancel

// SetTimeout/inteval return uniq id

var id = setTimeout(ahtung, 10000);

function somethingHappens() {
  clearTimeout(id);
} 

setInterval - cancel

// SetTimeout/inteval return uniq id

var id = setInterval(function() {console.log('hi')}, 10000);

function somethingHappens() {
  clearInterval(id);
} 

Task

Напишите функцию printNumbers(from, to), которая выводит число каждую секунду, начиная от from и заканчивая to.

Используя setInterval.

Recursive Function

Рекурсия – это приём программирования, полезный в ситуациях, когда задача может быть естественно разделена на несколько аналогичных, но более простых задач. Или когда задача может быть упрощена до несложных действий плюс простой вариант той же задачи. Или, как мы скоро увидим, для работы с определёнными структурами данных.

Recursive Function

function log(num){
    if(num > 5){
        return;
    }
    console.log(num);
    log(num + 1);
}

log(1);

Рассмотрим функцию. Нужно выйти когда num  === 5.

Recursive Function

for(let i = 1; i <= 5; i++){
    console.log(i);
}

Решение без рекурсии

Recursive Function

function randomUntilFive(result = 0, count = 0){
    if(result === 5){
        console.log(`The random result: ${result}`);
        console.log(`How many times random is executed: ${count}`);
        return;
    }
    result = Math.floor(Math.random() * (10 - 1 + 1) + 1);
    count++;
    randomUntilFive(result, count);
}

randomUntilFive();

Вариант с динамичными значениями.

Рандомно будут выбираться значения в диапазоне 1 до 10, пока не будет 5.

Task

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

function log(num) {}

log(2);
// 2
// 1

Другим отличным применением рекурсии является рекурсивный обход.

let company = {
  sales: [{
    name: 'John',
    salary: 1000
  }, {
    name: 'Alice',
    salary: 600
  }],

  development: {
    sites: [{
      name: 'Peter',
      salary: 2000
    }, {
      name: 'Alex',
      salary: 1800
    }],

    internals: [{
      name: 'Jack',
      salary: 1300
    }]
  }
};

Recursive Function

function sumSalaries(department) {
  if (Array.isArray(department)) { // случай (1)
    // сумма элементов массива
    return department.reduce((prev, currentObj) => prev + currentObj.salary, 0);
  } else { // случай (2)
    let sum = 0;
    for (let subdep of Object.values(department)) {
      sum += sumSalaries(subdep); // рекурсивно вызывается для подотделов, суммируя результаты
    }
    return sum;
  }
}

Recursive Function

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

js function part 3

By Oleg Rovenskyi

js function part 3

events, closure, context, this, call, apply, setTimeout/setInterval

  • 272