Используя var self = this или .bind (this)? [закрыто]

Мне было любопытно, какой путь обычно предпочтительнее, или если есть даже предпочтение, учитывая эти два варианта:

$.ajax({
    url: '../Component/GetSearchFilters',
    success: function (response) {
        console.log("Outer scope:", this);
    }.bind(this)
});

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

47 голосов | спросил Sean Anderson 15 Maypm14 2014, 22:58:01

6 ответов


40

Вещи, которые способствовали бы var self = this;

  • bind не поддерживается в IE8 и Safari5 . Если вы хотите создать библиотеку или код, поддерживающий устаревшие браузеры, то var self = this будет более дружественным к браузеру.

  • Иногда обратные вызовы привязаны к определенному контексту при выполнении, как в случае с jQuery $.each, где this - текущий элемент. Если вы не хотите потерять этот контекст, но все же хотите иметь родительский контекст, то это еще одна причина использовать var self = this;.

  • Вызов bind создает новую функцию с принудительным контекстом. Этот шаг создания функции может быть проблемой производительности в больших масштабах, особенно если вы вызываете bind внутри цикла.

Причины, благоприятствующие bind

  • Производительность не будет проблемой, если вы просто создали связанную функцию один раз и повторно использовали ее в нескольких местах. Как вы можете создать связанную функцию и вызвать эту связанную функцию в цикле (вместо вызова bind в цикле).

  • bind также освобождает вас от явного использования кода call(customContext) или apply(customContext).

  • Поиск области (поиск переменных, если не найден в текущей области) может представлять проблему производительности, особенно в очень глубоких областях. Вы, наверное, слышали о том, что «лучше перейти на локальный».

Я не говорю, что bind плохо (я сам их широко использую). Его просто нужно использовать в правильных ситуациях. Кроме того, проблемы производительности для обоих могут быть настолько незначительными, их можно увидеть только в том случае, если вы намереваетесь делать вещи менее чем за 16 мс (делайте что-нибудь в 60 кадров в секунду).

ответил Joseph 15 Maypm14 2014, 23:09:38
14

Просто добавьте другую альтернативу вместо того, чтобы делать

var self = this;
something( function () {
    // callback stuff
} );

можно также сделать это:

( function( self ) {
    something( function () {
        // callback stuff
    } );
} )( this );

Это лучше? Это может зависеть. Недостатки - это еще одна область и более глубокий уровень отступов.

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

Можно также сказать, что это не слишком читаемо, хотя я бы лично утверждал, что bind( this ) действительно намного читабельнее.

Я просто хотел указать на другой вариант, поскольку у меня есть больше вариантов выбора, как правило, хорошо.

ответил Ingo Bürk 16 Mayam14 2014, 02:55:36
6

Простое правило большого пальца использовать bind, если вам не нужно ссылаться на исходный this контекст. Если исходный this контекст необходим, обязательно используйте переменную self.

 $.ajax({
    url: '../Component/GetSearchFilters',
    success: function (response) {
        console.log("Outer scope:", this);
    }.bind(this)
});

против

var me = this;
$.ajax({
    url: '../Component/GetSearchFilters',
    success: function (response) {
        console.log("Outer scope:", me);
    }
});

Использование bind - это немного более консультироваться и читать легче, чем переменная me, но один путь над другим действительно не имеет большого значения.

ответил pllee 16 Mayam14 2014, 01:43:07
6

В первую очередь стоит отметить self; по умолчанию self является псевдонимом для окна window. Если вы переопределите это с помощью var self, вы в порядке, но если вы забудете добавить эту строку, и вы используете self во внутренней области, предполагая, что она ссылается на ваш внешний scope, есть потенциал для некоторых неприятных ошибок, которые трудно отследить.

По этой причине я, как правило, использую какой-то другой идентификатор: that, _this, некоторая переменная, указывающая, какой тип она есть, например app если это относится к чему-то, что я вызываю «приложение», view, если это представление и т. д. В этом случае, если вы находитесь в строгом режиме или правильно набиваете свой код на объект для использования неопределенных переменных вы получите уведомление, если вы забудете добавить этот псевдоним.

ответил Turner Hayes 1 +04002014-10-01T01:22:54+04:00312014bEurope/MoscowWed, 01 Oct 2014 01:22:54 +0400 2014, 01:22:54
2

В зависимости от того, что вы делаете, использование bind будет немного медленнее или медленнее. Я выяснил, что задаю этот вопрос, размышляя, лучше ли закрывать набор переменных или передавать и связывать их как аргументы (они никогда не меняются).

Вот код, который я написал, чтобы проверить это. Вы можете изменить значения I и J, чтобы настроить петли. Когда дело доходит до фактического исполнения, они сравнимы по скорости (закрытие было немного быстрее). Если, конечно, оптимизатор не доберется до него, а затем закрытие примерно в 4 раза быстрее. Тем не менее, инстанцирование примерно в 2-3 раза медленнее с привязкой.

Эти тесты были выполнены в Firefox 33

 function q(a, b){
  var a = {a:a}, b = {b:b};
  return {
    p:function(){ return a.a + b.b; },
    s:function(){ return a.a - b.b; },
    m:function(){ return a.a * b.b; },
    d:function(){ return a.a / b.b; },
    get_a:function(){ return a.a; },
    get_b:function(){ return b.b; },
    set_a:function(v){ a.a = v; },
    set_b:function(v){ b.b = v; },
  };
}

var I = 1000, J = 100;
var i, j;
var t0 = performance.now()
for(i = 0; i < I; i++){
  var k = new q(5, 6);
  for(j = 0; j < J; j++){
    k.p() + k.s() + k.m() + k.d();
  }
}
var t1 = performance.now();

document.write(t1 - t0)
document.write("<br/>")

var p;

(function(){
  function abp(a,b){ return a.a + b.b; }
  function abs(a,b){ return a.a - b.b; }
  function abm(a,b){ return a.a * b.b; }
  function abd(a,b){ return a.a / b.b; }
  function ga(a){ return a.a; }
  function gb(b){ return b.b; }
  function sa(a,v){ a.a = v; }
  function sb(b,v){ b.b = v; }
  function w(a, b){
    var a = {a:a}, b = {b:b};
    var m = {};
    m.p = abp.bind(m,a,b);
    m.s = abs.bind(m,a,b);
    m.m = abm.bind(m,a,b);
    m.d = abd.bind(m,a,b);
    m.get_a = ga.bind(m,a);
    m.get_b = gb.bind(m,b);
    m.set_a = sa.bind(m,a);
    m.set_b = sb.bind(m,b);
    return m;
  }
  p = w;
})();

var t2 = performance.now()
for(i = 0; i < I; i++){
  var k = new p(5, 6);
  for(j = 0; j < J; j++){
    k.p() + k.s() + k.m() + k.d();
  }
}
var t3 = performance.now();

document.write(t3 - t2)

TL; DR: .bind работает медленнее.

ответил BlindWanderer 4 22014vEurope/Moscow11bEurope/MoscowTue, 04 Nov 2014 10:16:25 +0300 2014, 10:16:25
1

Так как никто еще не упомянул об этом. jQuery прокси - работающее кросс-браузерное решение:

$.ajax({
    url: '/echo/json/',
    success: $.proxy(function(){
        console.log(this === window); // true
    }, this)
});

this обычно ссылается на объект jqXhr в обратном вызове успеха.

http://jsfiddle.net/thLhh54q/

ответил Johan 4 22014vEurope/Moscow11bEurope/MoscowTue, 04 Nov 2014 10:41:52 +0300 2014, 10:41:52

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132