Статьи

Подробнее об этом в JavaScript


В
thisJavaScript есть больше, чем я показывал в
прошлый раз . Время для более подробной информации о методах, замыканиях и глобальном объекте.

Это прямое продолжение этого в JavaScript против C # поста. Если вы еще не прочитали это, я предлагаю вам прочитать это, прежде чем продолжить здесь.

Подробнее о методах

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

// Repeated from old post
var mySelf = {};
mySelf["name"] = "Anders";
 
var getPayment = function (amount) {
  // Initialize to 0 if no cash property.
  this.cash = (this.cash || 0) + amount;
};
 
var showCash = function() { 
  document.write("Current " + this.name + " cash: " + this.cash + "<br/>"); 
};
 
mySelf.getPayment = getPayment;
mySelf.showCash = showCash;
mySelf.getPayment(10);
mySelf.showCash();
 
// New content
computerShop = { getPayment: getPayment, showCash: showCash, name: "Computers inc." };
computerShop.getPayment(100);
computerShop.showCash();

computerShopПовторно используют getPaymentи showCashфункцию в качестве методов. Теперь одна и та же функция используется в качестве метода двух разных объектов. Функция получит текущий объект как this, благодаря тому, thisчто связана с вызовом метода, а не привязана к объекту.

Глобальный объект

Что если функция вызывается напрямую — у нас есть ссылка на нее в getPaymentпеременной?

getPayment(42);
showCash();

Вывод в документ показывает, что значение действительно сохраняется между вызовами функции:

Current cash: 42

Чтобы иметь возможность сохранить значение, функции используют this. Даже если функции не были вызваны как метод, thisбыл действительным.

В JavaScript всегда есть this. Если ничего не указано, thisэто глобальный объект (так же, как и где хранятся глобальные переменные).

cash = 17;
showCash();

Это теперь покажет денежную стоимость как 17 вместо. Использование глобального объекта, конечно, не рекомендуется. Глобальные переменные — это запах кода на любом языке, поскольку это неизбежно при столкновении имен в больших программах. Способ определения модулей в JavaScript — использовать замыкания. Я не буду сейчас вдаваться в подробности о замыканиях для создания модулей, но покажу важное отличие в обработке замыканий между C # и JavaScript.

Затворы

Закрытие — это возможность для внутренней функции получить доступ к переменным внешней функции (даже если внешняя функция уже вернулась). Пока что C # и JavaScript равны. Когда дело доходит до thisобработки, они ведут себя по-разному, что важно знать, чтобы избежать неприятных сюрпризов.

В C # внутренняя функция имеет доступ к thisвнешней функции.

class C
{
  int i = 0;
  public void F()
  {
    Action a = () => this.i = 42;
    a();
    Console.WriteLine(i);
  }
}

Вызов F()распечатает 42. Соответствующий код JavaScript действителен. Но это не будет делать то же самое.

var o = {
  i : 0,
  F : function() {
    var a = function() { this.i = 42; };
    a();
    document.write(this.i);
  }
};
o.F();

Вывод в документ будет «0». Внутренняя функция действительно вызывается, но она не получит ссылку на oas this. Помните, что именно то, как вызывается функция , определяет значение this. Если он не вызывается с синтаксисом метода, thisбудет глобальный объект. Мы только что создали новую глобальную переменную iсо значением 42.

Проходя вручную this

Есть способ обработать последний пример: используя JavaScript applyили callфункции (разница в том, как передаются аргументы, в этом примере нет аргументов, поэтому оба работают одинаково). Ближайший родственник в C # — это методы расширения, где thisпараметр передается явно.

var p = {
  i : 0,
  F : function() {
    var a = function() { this.i = 42; };
    a.apply(this);
    document.write(this.i);
  }
};
 
p.F();

Последний пример выведет 42.

Захват thisвthat

В предыдущем примере thisбыл передан напрямую с помощью applyметода. Во многих случаях такой подход невозможен, т. Е. При передаче функции для последующего использования в качестве обратного вызова некоторой библиотекой. В этом случае соглашение заключается в захвате thisпеременной thatдля использования во внутренней функции.

var q = {
  i: 0,
  F: function F() {
    var that = this;
    var a = function () {
      that.i = 42;
    }
    a();
    document.write(this.i);
  }
}
 
q.F();

JavaScript не является C #

JavaScript определенно является мощным языком, но он совсем не похож на C #, как предполагает синтаксис. Я продолжу читать JavaScript: хорошие части, чтобы узнать больше об этом. Скорее всего, будет больше сообщений в блоге.

Ссылки на Amazon в этом посте являются спонсорскими.