LINUX.ORG.RU

Зачем нужен bind?

 


1

2

Если я не прав, то поправьте, но я, хоть убей, не понимаю, нахрен нужна эта нелепая конструкция. Обычно, ее расхваливают, приводя примеры, к слову, столь же нелепые, как и она сама. Типо:


o={
arr: [],
add: function(x){this.arr.push(x)},
}

//удивительно(!!!), но так не работает:
g_arr=[1,2,3]
//g_arr.forEach(o.add)//TypeError: Cannot call method 'push' of undefined

//еще бы, this связывается с глобальным контекстом, с чего бы ей, внезапно, работать

g_arr.forEach(o.add, o)// O-o-o, а вот так работает
g_arr.forEach(o.add.bind(o)) // так тоже, это, типа, сильно лучше

// Или сделать вот так

o.add=o.add.bind(o)
g_arr.forEach(o.add)

Спрашивается, с чем ты изначально хотел связать this.arr? Если ты хотел связать ее с o.arr, то почему ты сразу не написал o.arr, зачем ты, сука, написал this? Это все напоминает такую ситуацию: стоматологу, дергающему зубы через жопу вместо того, чтобы, кагбе намекнуть, что можно попробовать делать это через рот, предоставляют годный инструмент для удобного дерганья через жопу.

Ладно, может я и заблуждаюсь, но хотелось бы увидеть пример хоть сколько-нибудь полезного применения.

Ответ на: комментарий от buddhist

Да я бы не сказал, что язык такой уж плохой сам по-себе. Это сраные ES5 - идиоты делают из него гавно, чем новей тем говенней. Изначально то он спроектирован нормально.

anonimous
() автор топика

По-моему, это для более общих случаев. Например, можно создавать набор методов(т.е. функций, которые используют this), а потом какой-то объект привязать к этим функциям. В общем, для создания всяких обёрток, презентеров и прочего. Кроме того, чтобы вызывать методы из коллбеков, в которых контекст не будет привязан к вашему объекту.(так работает, скажем, setTimeout)

function wrap(){
  return {
   full_name: [this.name, this.surname].join(' ')
  };
}
var operator = {name: 'Name', surname: 'Surname'}; // Тут может быть что-то другое еще.
presenter = wrap.bind(operator);
presenter();

Во всяких MVС-подобных фреймворках, как Backbone.js, bind можно встретить часто. И лучше на настоящих примерах понять, где это используется. Чуть позже постараюсь привести пример из жизни.

blan4
()

bind - это костыль, чутка починяющий хуевый лексический скоуп. В lua намного лучше это все.

obj:doSmth(arg)

то же самое, что

obj.doSmth(obj, arg)

И не надо костылей типа bind. Нужно передать что-то другое в качестве this - передавай как белый человек через парадный вход.

anonymous
()
Ответ на: комментарий от blan4
presenter = wrap.bind(operator);
presenter=function(){return wrap.call(operator)}

ну, если считать это большим выигрышем в выразительности, ради которого стоило уродовать язык, то да.

чтобы вызывать методы из коллбеков, в которых контекст не будет привязан к вашему объекту.(так работает, скажем, setTimeout)

В этих случаях все тривиально решается обрткой. Ощутимого профита нет

anonimous
() автор топика
Ответ на: комментарий от bj

Ты же вроде фанат прототипного программирования? Bind как раз про это.

Не вижу связи. Более того, прототипы — это позднее связывание, bind - строго наоборот.

anonimous
() автор топика
Ответ на: комментарий от anonymous

В js по дефолту в ф-циях лексическое связывание. Нахрена поверх него лепить еще одно? В этом и дибилизм разработчиков.

anonimous
() автор топика
Ответ на: комментарий от anonymous

Это ни о чем не говорит. Если в ЯП изначально порочная основа, проектируй его хоть дсятилетия, все равно получишь говно. Смолток создан за 9 утр.

anonimous
() автор топика
Ответ на: комментарий от anonimous

Изначально то он спроектирован нормально.

Он как раз изначально говно. Анонимус правильно написал про наколенку.

korvin_ ★★★★★
()
Ответ на: комментарий от korvin_

Я уже отписался выше по этому поводу. Говном его считают статик-б*ди, которые его понимают чуть менее чем них*я. Это схема и селф в одном флаконе (причем схема в нем — это bad_part)

anonimous
() автор топика
Ответ на: комментарий от anonimous

Говном его считают статик-б*ди

Нет, все, кроме JS-дрочеров, которые просто больше ничего осилить не в состоянии.

(причем схема в нем — это bad_part)

Наоборот.

korvin_ ★★★★★
()
Ответ на: комментарий от korvin_

которые просто больше ничего осилить не в состоянии.

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

anonimous
() автор топика
Ответ на: комментарий от anonymous

В lua всё то же самое, можно запилить bind так чтобы первый аргумент игнорировался а вместо него подставлялось нужное значение. Но на практике это не нужно в отличии от языка в котором во всех функциях используються строго 2 аргумента: this и arguments.

anonymous
()
Ответ на: комментарий от anonymous

Я че то не понял. Ты считаешь, значит, что в JS это нужно. Приведи пример, тогда, где это нужно(хотя бы сильно удобней, я уж не говорю о необходимости)

anonimous
() автор топика
Ответ на: комментарий от anonimous

и стила, чей ущербный мозг н способн понять динамику

При том, что он соавтор Схемы и автор CLTL? Ну-ну.

korvin_ ★★★★★
()
Ответ на: комментарий от anonimous

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

Собственно если проектировать библиотеку то без этого можно обойтись. А вот если необходимо использовать готовую, то тут ничего уже не поделаешь.

Лично у меня полно такого кода где bind используется в SetTimeout и AddEventListene.

Без этого конечно же можно обойтись(задачу можно решать разными путями), только вот ЗАЧЕМ?

anonymous
()
Ответ на: комментарий от anonymous

только вот ЗАЧЕМ?

Чтобы не плодить лишние сущности. Лишние сущности, даже опциональные, всегда ослабляют язык.

anonimous
() автор топика
Ответ на: комментарий от anonimous

Это как бы часть стандартной библиотеки, а не языка, хоть и прописана в ES5.

Ну что касается лишних сущностей языка, так это this сам по себе. В этом плане lua в выиграше.

anonymous
()
Ответ на: комментарий от anonimous

Вот реплика другого анонимуса с которой я вполне согласен Зачем нужен bind? (комментарий)

(Наверно попытаюсь вспомнить свой ЛОРовский пароль или таки скопирую свой старый /home где он запомнен, тогда и поговорим, ато както непривычно)

Сравнение JS и lua как ближайших аналогов тема интересная. Например тот же блок try в lua выглядит как вызов библиотечной функции что на мой взгляд некрасиво.

anonymous
()
Ответ на: комментарий от buddhist

Современный Интернет на этом говне замешан. Людям приходится так или иначе им обмазываться, безысходность, секешь?

fero ★★★★
()
Ответ на: комментарий от anonymous

Я не понял, о чем вообщ этот анонимус говорит. В js дефолтный лексический скоп. Зачем нужен еще один? Может сразу 10 запилить, что уж мелочиться?

anonimous
() автор топика
Ответ на: комментарий от anonimous

Не смешы мои плоские стопы, разработчик говорил, что жабаскрипт был спроектирован за несколько дней и бессонных ночей, поэтому, починяя косяки, стандарт петляет, как муравей Лэнгтона. Но в конце концов, всё устаканится, как жабаскрипт так и муравей.

fero ★★★★
()
Ответ на: комментарий от anonimous

Это никакой не лексический скоп, это полноценный аргумент функции. Ему просто присвоили отдельное название и вынесли из arguments отдельно.

anonymous
()
Ответ на: комментарий от fero

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

anonimous
() автор топика
Ответ на: комментарий от anonimous

Я, например, жабу не знаю и js ковырять только начал, но! Уже вижу, как ломают обратную совместимость, используют «недокументированные возможности», забивают на точки с запятой, живут молодостью и угарают по энергии.

fero ★★★★
()
Ответ на: комментарий от fero

Точки с запятой (в жс) для импотентов

anonymous
()
Ответ на: комментарий от anonymous

Это никакой не лексический скоп, это полноценный аргумент функции. Ему просто присвоили отдельное название и вынесли из arguments отдельно.

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

doSmth=function(){console.log(this.a)}
ob={a:1}
ob.doSmth=doSmth.bind(ob)
ob.doSmth()
То есть, это двоеточие — это и есть эквивалент bind. Это можно рассматривать как своего рода лексический скоп, о чм анонимус и упомянул. Внутренний неймспейс функции привязывается к контексту. Разница тут только в синтаксисе. Я повторюсь: это НЕ_НУЖНО. привязать функцию к любому контексту в любой момент можно и без этого. К тому же это противоречит идеологии JS, его динамической природе. Это противоречит взгляду на функцию как на абстракцию. По сути это специализация функции, аналогичная каррированию. В JS изначально подчеркивается, что функция представляет из себя нзависимую сущность, не связанную ни с каким объектом, даже если она объявлена как метод объекта.

anonimous
() автор топика
Ответ на: комментарий от anonimous

Функции имеют типы. Это такая хуевая типизация, привязать функции к первому аргументу.

anonymous
()
Ответ на: комментарий от anonimous

Тысячи их, а глова у меня одна, поэтому не забиваю её подобной ерундой.

fero ★★★★
()
Ответ на: комментарий от anonimous

doSmth.bind(ob)//можно присвоить другому объекту, но действия при вызове полюбому произойдут с ob и именно для этого bind и предусмотрен.

То что это можно рассматривать как скоп, так любой объект представляющий из себя словарь с наслдедованием ведёт себя как скоп и им можно так пользоваться, в других языках в том числе lua и python.

А что касается функций и методов, так в JS ВСЕ(!) функции являются методами. Тоесть this передаётся в любом случае. Только поумолчанию в обычном состоянии это глобальный объект, а в стрикте undefined.

То что функция может менять своё поведение в зависимости от this это нормально, повторюсь что this - параметр передаваенмый в функцию как и список аргументов.

Вот взять наш самый популярный console.log...

Чтобы распечатать построчно массив в одних системах можно написать так:

arr.forEach(console.log)

Но в других системах эта функция работает только с оригинальным объектов в качестве this и надо писать так:

arr.forEach(console.log.bind(console))

Иногда даже хочеться запилить такой патч:

for(method in console)if(typeof console[method] === 'function')console[method] = console[method].bind(console);

Только подобные вещи считаю нихаляльными и стараюсь их избегать.

anonymous
()
Ответ на: комментарий от bj

Что значит во время вызова? Во время вызова он опредляется при обычном раскладе fu.call(ob) или fu.apply(ob). Если функция уже связана fu=fu.bind(ob) связь определена статически, почти как в замыкании(отличие в том что здесь мы имеем полный доступ к enveronment).

anonimous
() автор топика
Ответ на: комментарий от anonimous

Если функция уже связана fu=fu.bind(ob)

Правильно, если. На практике связывают и непосредственно перед вызовом. Тот же forEach, например.

bj
()

Для mixinов очевидно же

Dantix ★★
()
Ответ на: комментарий от bj

И вообще, без bind в js совсем грустно, так как в этом поделии нет понятия ссылки на «метод». А оно хотя бы явный захват нужного контекста позволяет сделать.

bj
()

Допустим, нам необходимо передать какие-либо переменные в цикле в коллбэк:

for (var i = 0; i < 10; i++) {
    window.setTimeout(
        function() {
            console.log(i);
        },
        1000
    );
}

(В реальности это могло быть обращение по сети и т.п.)

Такой код будет работать неправильно, поскольку переменная свяжется по ссылке, то есть в момент вызова коллбэка цикл уже завершится, и i будет равно 10.

Одним из вариантов решения проблемы может быть использование bind (такое форматирование сделано специально для наглядности):

for (var i = 0; i < 10; i++) {
    window.setTimeout(
        (function(j) {
            console.log(j);
        }).bind(this, i),
        1000
    );
}

Это практически аналогично такому коду:

for (var i = 0; i < 10; i++) {
    window.setTimeout(
        (function(j) {
            return function() {
                console.log(j);
            };
        })(i),
        1000
    );
}

Можно видеть, что вариант с bind короче.

static_lab ★★★★★
()
Последнее исправление: static_lab (всего исправлений: 1)
Ответ на: комментарий от anonymous

Только поумолчанию в обычном состоянии это глобальный объект, а в стрикте undefined.

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

anonimous
() автор топика
Ответ на: комментарий от anonimous

о что в контексте глобального вызова this связыватся с глобальным объектом — абсолютно логично.

По твоей логике, this вообще-то не должен существовать. Без bind он превращается в тыкву.

bj
()
Ответ на: комментарий от bj

Правильно, если. На практике связывают и непосредственно перед вызовом. Тот же forEach, например.

А зачем на практике связывать непосредственно пред вызовом с помощью bind (для чего он не предназначен), если для этого есть родные call и apply? Когда ты просто, как ты говоришь «связываешь» байндом, ты на самом деле каждый раз создаешь новую функцию. Это, как минимум, странно.

anonimous
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.