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? Это все напоминает такую ситуацию: стоматологу, дергающему зубы через жопу вместо того, чтобы, кагбе намекнуть, что можно попробовать делать это через рот, предоставляют годный инструмент для удобного дерганья через жопу.

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

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

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

Нет, по моей логике bind не должн существовать, потому что он не делает них*я такого, чего нельзя было бы сделать без него тривиальнейшим образом. А this нужен для того, для чего и был прдназначен изначально — для связывания с контекстом вызова.

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

Я по моему в каждом твоем js-треде повторяю: этот язык слепленная из говна и палок куча крапа, не надо искать в нем логичность и красоту, их там нет, by design.

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

Это не сахар над bind. Они к bind не имеют никакого отношения.

Рилли?

func.apply(self, [args...])
func.call(self, args...)
func.bind(self, args...)()

Если и оставлять что-то, то только apply. Остальное прекрасно можно на нем свелосипедить. Но однако вопросов к call у тебя нет.

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

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

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

Они длают разные вещи. call и apply применяет функцию к объекту. А bind создает функцию связанную с конкретным объектом.

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

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

Как показывает практика, ссылка на функцию с привязанным контекстом это очень удобно. Собственно thisArg неспроста везде прыщом торчит.

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

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

Да, если взять микроскоп, то можно увидеть.

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

Давай сначала разберемся с call. Зачем он нужен если есть apply?

Это сахар, и чо? Он, с-нно, и не нужен особо, но н мешает.

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

Он, с-нно, и не нужен особо, но н мешает.

Бинго. А кто-то считает что нужен особо, и даже появился в первой спецификации.

А потом докумекали что встроенный карринг с прокидыванием прыща, тоже полезен, так появился bind.

Мешает он только эстетам, начитавшихся бреда про связь схемки и js.

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

что вариант с bind

кстати, вариант с call тут работает точно также, так что неудачный пример, доказывающий совершенно обратное.

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

начитавшихся бреда про связь схемки и js.

Это, кстати, правда, js в своей функциональной части — это просто копия схемы, по большому счету, отличие только в отсутствии макросистемы и first-class продолжений. Однако, я н считаю, что это хорошая часть js, хорошая часть js — это селф.

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

Хотелось бы узнать смысл термина «контекст вызова», ато реально непонятно при чём тут this и bind. Подозреваю что у тебя с этим моральнопсихологическая проблема, а не реальная техническая.

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

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

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

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

Следовательно это один из аргументов передаваемых при вызове, возможно передаваемых неявно. Это почти во всех популярных языках. На ранних стадиях развития C++ был препроцессором в C где методы определялись как функции с дополнительным аргументом.

Чего плохого в том что язык или библиотека предоставляет дополнительные способы манипулирования этим аргументом?

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

Плохо 2 вещи:

1) Язык засоряется мусором

2) Искажается семантика. Люди начинают писать код н понимая, что реально происходит. Потом все это отражеется на спецификациях и стандартах, вс усложняется. Даже просто сахар — это уже зло. А сахар искажающий смысл — это зло вдвойне. Тем более, как показал этот тред, никто так и не показал ни одного примера где он ДЕЙСТВИТЕЛЬНО нужен. Оказалось, что его употребление всегда обусловлено ошибочным пониманием.

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

Ты понимаешь что такое карринг? А зачем в стандартной библиотеке нужна готовая функция для него?

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

Зачем ты жрешь говно и жалуешься, что оно невкусное?

нет, тут должен быть другой вопрос: «Зачем ты программируешь на языке, ещё и жалуешься?»

это при том, что js я не люблю, но уважаю

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

ещё и жалуешься?

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

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

Рассуждая так можно решить что лишней сущностью тут таки является именно this, а bind - утилита для работы с this в дополнение к call и apply. Без this такие функции как apply остануться, но call и bind будут ненужны. Всё упроститься.

Но раз есть this, то нужны call и bind.

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

В общем, ситуация такова что с нативным bind код работает шустрее чем без него.

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

Люди, которые пишут код, не хотят каждый раз писать на коленке. Пусть тебе это покажется удивительным, но просто прими как факт. По твоей логике 90% стдлиба не нужно. А многим бы хотелось там иметь lodash, причем последние не пускают слюни на лоре.

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

Библиотека ES5 давно реализована на основе библиотеки ES3 и её варианты лежат на гитхабе, но используют почемуто преймущественно платформы с нативной реализацией ES5.

Зачем пилить свой лисапед когда есть готовое решение?

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

Без this такие функции как apply остануться

Не обязательно. Необходимость в ней без this тоже пропадает. Лексический скопинг сам по себе способен разрулить связывания. Но я бы сделал все с точностью наоборот. Просто — это когда явно.

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

Нативные функции работают быстрее

Это, кстати, как ни парадоксально, не всегда так. Например, я как-то тестировал map, она в некоторых средах была в 10-ки раз (!) медленней чем самописная. Когда за дело берутся всякие крокфорды всего можно ожидать.

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

лишней сущностью тут таки является именно this

А, ну да, забыл сказать, тогда и new не будет работать, да и вся прототипная система полетит к чертям. Вот такая вот «ненужная» сущность. Останется голая схема.

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

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

И вообще! Хаскель простейший язык! Да, в прилюдии тоже дофига реально лишнего, но сам по себе язык простейший.

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

Согласен, new не нужно. Функция-конструктор должна вызываться как обычная но внутри на результат вешается метатаблица^Wпрототип. Благо в 5-м стандарте появился Object.create так что можно писать уже в таком стиле.

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

в разных лиспах он есть

В лиспах он имеет нсколько другую семантику. Он берет в качестве аргумента список а не объект, в JS applay мощней чем в лиспе. Произвольное количество аргументов можно получить не только с помощью apply, например так

(define f (lambda x (for-each (lambda(el) (write el)) x)))
Может это как то связано, я хз В JS вообще количество аргументов всегда произвольной длинны, кстати, искаропки.

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

Нет, я не говорил, что new не нужно. new - это мощная абстракция, если бы его не было, его стоило бы накостылить. Я говорю о том, что без this new просто невозможен, это бред. А Object.create — это очередной высер крокфорда. Он означает всего лишь

ob={__proto__: {}}
Меня все это реально бесит.

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

Ну в JS тоже список вторым аргументом идёт, this указывается отдельно, а в лиспах он попросту не нужен. Так что семантика идентична.

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

Это я запостил, но что-то не очень активно там тема обсуждается. Там жеквери в почете.

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

Мне тоже такое в словарях ненравиться. Чтобы использовать Object как словарь надо делать обёртку которая модифицирует ключ перед проверкой(обычно это добавить суфикс или префикс) или использовать Map который есть не везде. Вот метатаблицы в lua вообще не отображаются на ключах, да и ключи могут быть произвольного типа. Особенность __proto__ тут в том что на этом поле навешаны дополнительные свойства делающие его невидимым в Object.keys или в for-in.

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

Нет. В JS объект — это не просто структура, это семантический объект, который строится к тому же динамически.

ob_={b:2}
ob={a:1, __proto__: ob_}

;(function(){console.log(this.b)}).apply(ob)
Тут могут быть и сложные цепочки наследования, все что угодно. В лиспе, конечно, можно такое поведение имитировать, но это уже будет не родной apply, причем сделать это в 2-3 строки не выйдет, будет большой и сложный код.

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

Чтобы использовать Object как словарь надо делать обёртку которая модифицирует ключ перед проверкой(обычно это добавить суфикс или префикс) или использовать Map который есть не везде

В принципе, можно просто в качестве прототипа выставить null и можно использовать как словарь.

использовать Map который есть не везде

А где его нет?

Вообще, map делается легко, например:

myMap=function(f){
   var newArr=[]
   for(var i=0; i<this.length; i++){
       newArr.push(f(this[i]))
   }
   return newArr
}
И работает быстрей нативного

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

Да и я о том, только ты малость не о том. Я же рассматриваю this как аргумент передаваемый в функцию, условно присваиваю ему номер -1(если использовать call то именно так он и выглядит, типа -1(this), 0(первый аргумент, он же arguments[0]), 1...)

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

Для наглядности можно сделать так:

function lispLikeAapply(fn,args){return fn.call.apply(fn.call, args);}

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

Это JavaScript а не ECMAScript, там есть режим --harmony в котором доступны навороты которые не вошли в текущий стандарт.

В том числе типы данных Map и Set. Во всяком случае в популярных движках эти плюшки есть.

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

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

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

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

arguments такой же список(массивоподобный объект) как и в лиспе. А то что элементами этого списка могут быть словари с особым поведением а не другие списки к теме разговора отношения не имеет.

Хотя только-что проверил такой код:

(function(){console.log(this);}).call(1)

В результате число-скаляр преобразовалось в число-объект(надо будет запомнить эту особенность). А в остальном разницы нет.

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

такой же список(массивоподобный объект) как и в лиспе

массив — это не список. Это объект с такой структурой {1:«a», 2: «b»}. Если положить на то, что объкт в js — это динамичская структура, фактически, функция, разница все равно есть. Eсли упрощенно:

(apply (lambda(x) x) '(1))
будет соответствовать
(function(){return this.x}).apply({x: 1})

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

Ты, в общем случае, на js, применяешь ФУНКЦИЮ к ОБЪЕКТУ. Второй аргумент apply опционален. В данном случае, ты применил функцию к null

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