Блокировка видимости с помощью Let в JavaScript

    Let — это такое ключевое слово с помощью которые мы можем определить переменную с ограниченной областью видимости, и эту область видимости мы можем ограничить аж четырьмя способами. Люди знающие OCaml сразу найдут параллель между let… in в Ocaml и let в JavaScript.
    На хватит слов, давайте рассмотрим каждый способ применения let.



    Включаем поддержку Let


    Возможно у вас не получится сразу воспользоваться Let, но не огорчайтесь возможно Let заработает когда вы укажите type=«application/javascript;version=1.7» или вызовите version(170).

    Область видимости для одного блока


    С помощью let мы можем определить переменную видимой только в определенном блоке кода.
    Синтаксис такого определения выглядит так
    let(define vars){
    some expression
    }

    А чтобы было понятней давайте рассмотрим простой пример. Пусть Bob живет в России и хочет купить DreamPlug он знает что в СНГ эта штучка будет стоит 300$, он отправляется в Европу чтобы купить подешевле, покупает и возвращается в Россию, и хвастается друзьям что у него есть комп из розетки и когда его спрашивают про цену он отвечает 300$.
    Посмотреть данный пример
    //Bob в России
    dreamplug = new Object();
    dreamplug.price = 300;
    let(dreamplug.price = 150){
    //Bob приехал в Европу
    Bob.buy(dreamplug); // Bob покупает dream plug за 150$
    }
    //Bob вернулся в Россию
    Bob.onmessage = function(event){
    if(event.data == "Сколько стоил?")Bob.postmessage(price + "$",event.origin) //Когда Bob-а спрашивают он отвечает
    }
    //Данный пример заработает только если вы определите обьект Bob с методом buy
    //И да, я выражаю человеческие разговоры через JavaScript
    


    Область видимости для одного выражения



    Практически тоже самое что и для блока но применяется к одному выражению(кто бы мог подумать). И соответственно не надо ставить фигурных скобок.
    Для понятности рассмотрим пример с Bob-ом. Итак, наш Bob впал в детство и вспомнил то как он отвечал по признакам делимости у доски. Он отвечал по признаку делимости на два, кроме одного примера в котором надо было ответить по признаку делимости на 3.
    Посмотреть данный пример
    //Признак делимости на два
    pred = function(x)!(x%2) //Предикат признака делимости на два
    pred(3)
    //Здесь я пропустил еще пару ответов Bob-a у доски
    pred(2)
    let(pred = function(x)!(x%3))pred(4) //Предикат признака делимости на три
    


    Некоторые хабровчане (а именно те кто не знают что такое функциональный ЯП) наверняка заметили что тут мы определяли с помощью let не переменную, а функцию, но не забывайте что JS — функциональный ЯП, и функция является полноценным типом.

    Let внутри цикла for


    Мы также можем определит переменные с помощью let для цикла, единственным отличием от определения с помощью var будет то что переменная не будет в области видимости цикла и ничего кроме него.
    Итак, пусть Bob пошел в магазин за покупками.
    Посмотреть данный пример
    list = ["msp430","avr","pic","msp430 Launch pad"] //Bob не тупой и у него есть список поупок
    var i = 100; //Прсто Bob-у понравилось это число
    for(let i=0;i<list.length;i++){
      Bob.buy(list[i]); //Bob купил вещь из списка
    }
    Bob.say('Мне нравится число ' + i) //100!!!
    


    Let внутри блока



    Мы можем определить с помощью let переменную внутри определенного блока. Отличием от определения let для блока кода будет в том что здесь начав определять переменную она станет undefined и только когда мы присвоим ей значение он станет не undefined. То есть например. Если Bob-а спросят квадрат его любимого числа, делать так нельзя.
    Посмотреть данный пример
    let i=100
    {
    let i = i * i
    Bob.say(i) //NaN так как когда мы написали let i - мы определили i внутри блока i пока что undefined и при умножении undedined на undedined мы получили NaN
    }
    


    Но тем не менее можно делать вот так:
    Посмотреть данный пример
    let i=100
    {
    let m = i * i
    Bob.say(m) 
    }
    


    Буду рад услышать замечания относительно статьи и адекватности.
    Поделиться публикацией
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама
    Комментарии 28
    • 0
      Где ещё почитать про синтаксис javascript;version=1.7 и область его применимости в браузерах?

      В FF3.6 заработал, а где ещё такая странная запись будет работать и каковы перспективы для неё?

      Впрочем, там работает и

      , что тоже не обычно. С какой это версии JS пошло и почему так не пишут, а обычно f = function(x){return x*x;}?
      • 0
        [Съедены теги:]
        В FF3.6 заработал
        <script type="application/javascript;version=1.7">let(f = function(x)(x*x))alert(f(4));</script>
        , а где ещё такая странная запись будет работать и каковы перспективы для неё?

        Впрочем, там работает и
        <script>
        f = function(x)(x*x);
        alert(f(4))
        </script>
        , что тоже не обычно. С какой это версии JS пошло и почему так не пишут, а обычно f = function(x){return x*x;}?
        • 0
          Такая запись функций пошла с 1,7 версии.
          Не пишут так потому что 1)Не все знают 2)Internet Explorer
          Основные перспективы использования let — это node.js
          Почитать про JavaScript можно на MDC
          Где работает с уверенностью сказать не могу но насколько я знаю IE8+, Chrome,FireFox (версии не указал так как пользователи этих браузеров обычно обновляют его) поддерживают 1.7 версию.
          • +3
            Нет, кроме лисы ни один популярный браузер не поддерживает.
            • –1
              В node.js let, array comprehensions и closure expression у меня не заработали =( Есть способ запустить?
              • +2
                В V8 нет let и поэтому его нет в Node.js
                let is a Mozilla extension, not part of any standard
                Аналогично с E4X (хотя он в стандарте)
                There are currently no plans for implementing E4X in V8
                Comparison_of_layout_engines_(ECMAScript)
          • +8
            Javascript — это имплементация стандарта ECMAscript корпорацией Mozilla. Следовательно, в других браузерах (вообще ни в одном, базирующемся на Webkit, Presto, Trident) поддержки let нету. Я как-то заводил баг в багтрекере V8 — там мне сказали то же самое «извините, но новые фичи не включим, пока они не будут в ecmascript».
            Ответвление Javascript, поддерживаемое мозиллой добавляет еще такие фичи:
            — Короткие анонимные функции
            Было: function(x) {return x * x}
            Стало: function(x) x * x
            — Генераторы, итераторы (__iterator__, next()) и, следовательно, yield statement, как в пытоне
            function fib() { // js 1.7
              var i = 0, j = 1;
              while (true) {
                yield i;
                var t = i;
                i = j;
                j += t;
              }
            }
            
            handleResults( i for ( i in obj ) if ( i > 3 ) ); // js 1.8
            


            — Списочные выражения (тоже из пытона)
            var ten_squares = [i * i for each (i in range(0, 10))];
            var evens = [i for each (i in range(0, 21)) if (i % 2 == 0)];
            

            — Destructing assignment
            var a = 1;
            var b = 3;
            [a, b] = [b, a];
            function f() {
              return [1, 2];
            }
            
            var c, d = f();
            
            • 0
              Ну тогда я пожалуй напишу компилятор данного подмножества JS в JS для V8, Preso,…
              • 0
                Было бы здорово, но как будет выглядеть тогда разработка? Будет что-то типа Coffeescript — пишешь код, компилируешь, вставляешь в js-файл и смотришь?
                • +1
                  Две версии.
                  1) Как Coffescript
                  2) JIT с подключением extend.js
              • 0
                Маленькая поправочка, Webkit, Presto, Trident — это движки, которые рендерят НТМЛ. За джаваскрипт отвечает JS движок.

                Еще я бы добавил к вашему списку такую вещь:
                Object.__noSuchMethod__ — вызывается, если метод не существует. Ну вот почему именно этой фичи нет в V8, когда она так мне нужна в node.js -_-

          • 0
            Ссылка на работающий пример в вашей статье смотрелась бы как нельзя кстати.
            • 0
              Спасибо за совет, работающие примеры добавил.
            • 0
              Последний пример, скорее всего, с ошибкой. В том же FF сравните:
              <script type="application/javascript;version=1.7">
              let f = 1
              	{alert(f);} //вывод 1
              	alert(f); //вывод 1
              </script>
              

              и
              <script type="application/javascript;version=1.7">
              let(f = 1)
              	{alert(f);} //вывод 1
              	alert(f); //ошибка "f is not defined"
              </script>
              
              • 0
                Поясните пожалуйста в чем ошибка. Так как пробовал все из веб консоли FF 4.0 Beta 10 и все работало как я расписал.
                • 0
                  Ограничение видимости работает именно во 2-м моём примере, когда после let — скобки. В первом случае оператор let, скорее всего, просто игнорируется. Ещё пример:
                  <script type="application/javascript;version=1.7">
                  let(f = 1)
                  	alert(window.f); //undefined - правильно
                  	alert(f); //ошибка "f is not defined" - тоже правильно
                  </script>

                  Поэтому Ваш пример
                  let i=100
                  {

                  не сработает по ограничению видимости.
                  • 0
                    Т.е работать, конечно, будет, но i==100 останется и после фигурных скобок после блока.
                    • 0
                      Оно так и задумано.
                      • 0
                        А какое тогда отличие от просто
                        i=100
                        {

                        ? Даже область видимости переменной i в этом случае — windows.
                        • 0
                          Вот именно что отличий нет, в том примере внешняя область видимости для кода в блоке не важна. Важно то что когда мы определяем внутри let i = i *i то сначала i становится undefined во внутренней области.
                          а в let m = i * i мы определяем m а затем присваиваем m значения в результате умножения i*i из внешней области видимости.
                  • –1
                    Потому что в JavaScript областью видимости управляет только функция.
                    Последний пример должен выглядеть так:

                    let i=100;
                    (function(){
                    let i = i * i;
                    Bob.say(i);
                    })();
                  • 0
                    так можно писать с тех пор как вышел FF 2.0.
                    Подробнее
                    • 0
                      если правильно понял, то в первом примере вместо
                      Bob.postmessage("300$",event.origin)

                      должно быть
                      Bob.postmessage(price+"$",event.origin)
                      • +1
                        Да вы правильно поняли, спасибо, ошибку исправил.
                      • +1
                        а поямните первый пример
                        в эту функцию вы прайс не передаете?
                        Bob.buy('dream plug');
                        т.е. эта фунция работает с глобальным объектом прайс
                        то есть получается что let на время переопределяет глобальную переменную?
                        • 0
                          К сожалению тесты показали что не переопределяет, следовательно у меня ошибка в примере, сейчас я её исправлю.
                        • 0
                          Устарело. Теперь es6

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