Выразительный JavaScript (Хавербеке) - страница 73

>      output += charFromElement(element);

>    }

>    output += "\n";

>  }

>  return output;

>};

Стена >wall – простой объект. Используется для занятия места и не имеет метода >act.

>function Wall() {}

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

>var world = new World(plan, {"#": Wall, "o": BouncingCritter});

>console.log(world.toString());

>// → ############################

>//   #      #    #      o      ##

>//   #                          #

>//   #          #####           #

>//   ##         #   #    ##     #

>//   ###           ##     #     #

>//   #           ###      #     #

>//   #   ####                   #

>//   #   ##       o             #

>//   # o  #         o       ### #

>//   #    #                     #

>//   ############################

this и его область видимости

В конструкторе >World есть вызов >forEach. Хочу отметить, что внутри функции, передаваемой в >forEach, мы уже не находимся непосредственно в области видимости конструктора. Каждый вызов функции получает своё пространство имён, поэтому >this внутри неё уже не ссылается на создаваемый объект, на который ссылается >this снаружи функции. И вообще, если функция вызывается не как метод, >this будет относиться к глобальному объекту.

Значит, мы не можем писать >this.grid для доступа к сетке изнутри цикла. Вместо этого внешняя функция создаёт локальную переменную >grid, через которую внутренняя функция получает доступ к сетке.

Это промах в дизайне JavaScript. К счастью, в следующей версии есть решение этой проблемы. А пока есть пути обхода. Обычно пишут >var self = this и после этого работают с переменной >self.

Другое решение – использовать метод >bind, который позволяет привязаться к конкретному объекту >this.

>var test = {

>  prop: 10,

>  addPropTo: function(array) {

>    return array.map(function(elt) {

>      return this.prop + elt;

>    }.bind(this));

>  }

>};

>console.log(test.addPropTo([5]));

>// → [15]

Функция, передаваемая в >map – результат привязки вызова, и посему её >this привязан к первому аргументу, переданному в >bind, то есть переменной >this внешней функции (в которой содержится объект >test).

Большинство стандартных методов высшего порядка у массивов, таких как >forEach и >map, принимают необязательный второй аргумент, который тоже можно использовать для передачи >this при вызовах итерационной функции. Вы могли бы написать предыдущий пример чуть проще:

>var test = {

>  prop: 10,

>  addPropTo: function(array) {

>    return array.map(function(elt) {