02. Строки

Контрольные вопросы

  1. Испытательный стенд Какое значение получит переменная x. Ответ объясните.

    
    var s = "Где начало того конца, которым оканчивается начало?";
    var x = 0;
    for(var i=0; i<s.length; i++) 
      if (s.charAt(i) == " ") x++;
    
    Ответ

    Ответ: 6. К значению переменной x в цикле добавляется единица всякий раз, когда обнаруживается пробел в строке.

  2. Испытательный стенд Напишите функцию, которая удаляет подстроку из текущей строки (без проверки на правильность значений аргументов).

    
    // Возвращает строку, в которой удалена подстрока 
    // с позиции begin (включая) до позиции end (исключая).
    // Если end отсутствует, удаляется конец строки, начиная 
    // с позиции begin.
    function delSubStr(str, begin, end) 
    {
      ...
    }
    var s1 = "Кукарача";
    s1 = delSubStr(s1,2,6); // s1 == "Куча"
    var s2 = "Кукарача";
    s2 = delSubStr(s2, 4);  // s2 == "Кука"
    
    Ответ
    
    // Возвращает строку, в которой удалена подстрока 
    // с позиции begin (включая) до позиции end (исключая).
    // Если end отсутствует, удаляется конец строки, начиная 
    // с позиции begin.
    function delSubStr(str, begin, end) 
    {
      end = end || str.length; 
      return str.substring(0,begin)+str.substring(end); 
    }
    var s1 = "Кукарача";
    s1 = delSubStr(s1, 2,6);  // s1 == "Куча"
    var s2 = "Кукарача";
    s2 = delSubStr(s2, 4);    // s2 == "Кука"
    

    Или

    
    function delSubStr(str, begin, end) 
    {
      return str.substring(0,begin)+str.substring(end || str.length); 
    }
    

    Как работает проверка end || str.length? Немного не так, как вы, вероятно, думаете. Алгоритм такой:

    • Вычисляется первый операнд операции ||. Если его логическое значение есть true, возвращается он сам и вычисление второго операнда не производится.
    • Если логическое значение первого операнда false, возвращается второй операнд.

    Пример 1

    
    var x = 4;
    var y = x-2 || x*x;  //  у равно 2 
    

    Пример 2

    
    var x = 2;
    var y = x-2 || x*x;  //  у равно 4
    

    Посмотрим на выражение:

    
    end = end || str.length; 
    

    Если end отсутствует в вызове функции, его значение равно undefined.

    
    delSubStr(s1,2,6);  // Здесь end равно 6
    delSubStr(s2, 4);   // Здесь end равно undefined
    

    Поясняю почему. Значение undefined имеют переменные, которые существуют (объявлены), но которым не присвоено значение.

    Кажется, что раз в вызове функции не задан аргумент end, то этой переменной нет, значит, при обращении к этой переменной должна выдаваться синтаксическая ошибка, а не undefined.

    Например, синтаксическая ошибка обеспечена таким кодом:

    
    function f()
    {
       return y; // Переменной y нет -- синтаксическая ошибка
    }
    var x = f();
    

    Но формальные аргументиы, то есть параметры, присутствующие в описании функции (в нашем случае str, begin, end), существуют всегда. Они неявно объявляются, как локальные переменные функции. При вызове функции этим локальным переменным присваиваются фактические аргументы вызова. Если аргумент вызова не задан (end), локальной переменной ничего не присваивается, значит, она имеет значение undefined.

    Теперь давайте посмотрим, как вычисляется логическое значение числового значения. Здесь все просто: 0 — есть false, остальное — true. Логическое значение undefined — всегда false.

    
    end = end || str.length; 
    

    Если end не нуль и не undefined, он сохранит своё значение. Если end нуль или undefined, он получит значение str.length (для пустой строки это будет 0, для непустых строк — целое положительное число).

    Проверьте, что и вызов delSubStr("", 0) будет работать правильно.

    * * *

    Заодно, приведу алгоритм вычисления выражения:

    
    a && b 
    

    Алгоритм такой:

    • Вычисляем первый операнд операции &&. Если его логическое значение есть false (false, null, 0, "", undefined), возвращается он сам и вычисление второго операнда не производится.
    • Если логическое значение первого операнда есть true, возвращается второй операнд.

    Пример 1

    
    var x = 2;
    var y = x-2 && x*x;  //  у равно 0 
    

    Пример 2

    
    var x = 4;
    var y = x-2 && x*x;  //  у равно 16
    

    Пример 2

    Два следующих выражения дают эквивалентные результаты:

    
    (a == b) && f();
    if(a == b) f();
    
  3. Испытательный стенд Какое значение получит переменная x. Ответ объясните.

    
    var x = 25 + "1".concat(".",3)-.3+7;
    
    Ответ

    Ответ: 258. Операции + и - имеют один приоритет и выполняются слева направо.

    
    "1".concat(".",3) // Строка "1.3"
    25 + "1.3"        // Строка "251.3"
    "251.3"-.3        // Число 251
    251+7             // Число 258
    
  4. Испытательный стенд Какое значение получит переменная x в каждом случае? Объясните ответы.

    1. "1 плюс 2 плюс 45".match(/плюс/)
    2. "1 плюс 2 плюс 45".match(/плюс/g)
    3. "1 плюс 2 плюс 45".match(/минус/g)
    4. var x = "1 плюс 2 плюс 45".match(/\d\d/)
    5. var x = "23+78=101".match(/\d\d/);
    6. var x = "23+78=101".match(/\d\d/g);
    7. var x = "0123456789".match(/\d\d/g);
    Ответ
    1. var x = "1 плюс 2 плюс 45".match(/плюс/); // Массив ["плюс"]
    2. var x = "1 плюс 2 плюс 45".match(/плюс/g); // Массив ["плюс","плюс"]
    3. var x = "1 плюс 2 плюс 45".match(/минус/g); // null
    4. var x = "1 плюс 2 плюс 45".match(/\d\d/); // Массив ["45"]
    5. var x = "23+78=101".match(/\d\d/); // Массив ["23"]
    6. var x = "23+78=101".match(/\d\d/g); // Массив ["23","78","10"]
    7. var x = "0123456789".match(/\d\d/g); // Массив ["01","23","45","67","89"]
  5. Испытательный стенд Какое значение получит переменная x. Ответ объясните.

    
    var y = "0 плюс 2 плюс 45789";
    function f(d)
    {
      d = d-0;
      if (d && d < 5) d++;
      else if (d >= 5) d--;
      else d = "ноль";
      return d;
    }
    var x = y.replace(/\d/g, f);
    
    Ответ

    Ответ: строка "ноль плюс 3 плюс 54678".

  6. Испытательный стенд Какое значение получит переменная x. Ответ объясните.

    
    var x = "01234567".replace(/\d/g, function (d) { if(d-0) d--; return d});
    
    Ответ

    Ответ: строка "00123456".

  7. Испытательный стенд Какое значение получит переменная x. Ответ объясните.

    
    var x = "01234567".replace(/\d/g, function (d) { if(d) d--; return d});
    
    Ответ

    Ответ: строка "-10123456".

    Пояснение: строка "0" преобразуется в true, а число 0 в false в логическом контексте.

  8. Испытательный стенд Какое значение получит выражение? Ответ объясните.

    
    ((function (x,y){ return x.concat(y)})("1","2")/3+" попугая").search(/\d/)
    
    Ответ

    Ответ: число 0.

    Пояснение:

    
    function (x,y){ return x.concat(y)} // Функциональный литерал
    (function (x,y){ return x.concat(y)})("1","2") // Вычисление: строка "12" 
    "12"/3  // Равно числу 4
    4+" попугая" // Равно строке "4 попугая"
    "4 попугая".search(/\d/) // Равно числу 0 -- номер позиции цифры