Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 21.10.2014, 19:14
Кандидат Javascript-наук
Посмотреть профиль Найти все сообщения от terminator-101
 
Регистрация: 14.10.2014
Сообщений: 117

Безопасный Monkey Patching
Сейчас в JS считается дурным тоном расширение прототипов, особенно нативных объектов. ИМХО, это связано с одной стороны, тем, что в JS приходит много народу из статических языков, которые просто не понимают профита, с другой — вопросами оптимизации. Где то читал, что Во времена расцвета Prototype.js это наоборот считалось Best Practice. Да и в руби, например, вроде от него нос не воротят. Ну ладно, времена меняются.

Я тут подумал, а почему бы не сделать вот так
show=function(x){console.log(x); return x}
Object.prototype.call=function(f){return f(this.valueOf())}

// Примеры использования
"foo".call(show)
"foo bar baz".split(" ").call(show)
;({one: 1, two: 2}).call(show)
;({one: 1, two: 2}).call(function(o){for(var i in o){show(o[i])}})

//  foo
//  [ 'foo', 'bar', 'baz' ]
//  { one: 1, two: 2 }
//  1
//  2

Так мы получаем почти то же самое, правда с ущербным синтаксисом через жопу вызова, типа колбеков, но избавляемся от претензий статик-клоунов по-поводу неожиданных эффектов, т.к. главный объект расширен единственным методом. А уже на основе этого можно делать любые обертки. call можно сделать enumerable=false, если чо.
Ответить с цитированием
  #2 (permalink)  
Старый 21.10.2014, 20:19
Отправить личное сообщение для Octane Посмотреть профиль Найти все сообщения от Octane  
Регистрация: 10.07.2008
Сообщений: 3,873

А смысл твоего метода call, если того же результата можно добиться написав по-человечески:
function show(x) {
    console.log(x);
    return x;
}

show("foo");

show("foo bar baz".split(" "));

show({
    one: 1,
    two: 2
});

(function (o) {
    for (var i in o) {
        show(o[i])
    }
})({
    one: 1,
    two: 2
});

//  foo
//  [ 'foo', 'bar', 'baz' ]
//  { one: 1, two: 2 }
//  1
//  2
?
Ответить с цитированием
  #3 (permalink)  
Старый 21.10.2014, 20:30
Кандидат Javascript-наук
Посмотреть профиль Найти все сообщения от terminator-101
 
Регистрация: 14.10.2014
Сообщений: 117

Octane,
Смысл в том, что когда у тебя получается вот такая вот хрень а1(... a2(...a3(....a4(....)))) гораздо легче это писать в объектном стиле a1.a2.a3.a4. Дело даже не в записи как таковой, а в том, что ты запариваешься куда какие параметры передавать. В данном случае, явная передача объекта проще.
Ответить с цитированием
  #4 (permalink)  
Старый 22.10.2014, 15:20
Аватар для kobezzza
Быдлокодер;)
Отправить личное сообщение для kobezzza Посмотреть профиль Найти все сообщения от kobezzza
 
Регистрация: 19.11.2010
Сообщений: 4,338

Не расширяй никогда Object.prototype, а остальные прототипы можно, но аккуратно.

Пример из личного опыта:

Object.prototype.get = function () { ... };


Потом где то в коде была функция:

function foo(params) {
    params = params || {};
    params.get = params.get || '*'; // И тут всё ломается
}
__________________
kobezzza
code monkey
Ответить с цитированием
  #5 (permalink)  
Старый 22.10.2014, 15:39
Кандидат Javascript-наук
Посмотреть профиль Найти все сообщения от terminator-101
 
Регистрация: 14.10.2014
Сообщений: 117

Сообщение от kobezzza
И тут всё ломается
А что у тебя сломалось, я не понял?
Ответить с цитированием
  #6 (permalink)  
Старый 22.10.2014, 18:21
Аватар для kobezzza
Быдлокодер;)
Отправить личное сообщение для kobezzza Посмотреть профиль Найти все сообщения от kobezzza
 
Регистрация: 19.11.2010
Сообщений: 4,338

Сообщение от terminator-101 Посмотреть сообщение
А что у тебя сломалось, я не понял?
У меня есть функция, которая принимает объект-параметр, в объекте есть свойство, которое в случае, если не задано устанавливается в значение по умолчанию, но этого не происходит, т.к. в прототипе Object есть свойство с таким же именем

params.get = params.get || '*';


Т.е. вместо значения по умолчанию мы получаем ссылку на значение из прототипа и всё ломается.
__________________
kobezzza
code monkey
Ответить с цитированием
  #7 (permalink)  
Старый 22.10.2014, 19:01
Аватар для danik.js
Профессор
Отправить личное сообщение для danik.js Посмотреть профиль Найти все сообщения от danik.js
 
Регистрация: 11.09.2010
Сообщений: 8,804

Сообщение от kobezzza
Не расширяй никогда Object.prototype
Да что там, бывает что встроенные свойства малину портят.
Благо, есть Object.create(null), но все равно бесит.
__________________
В личку только с интересными предложениями
Ответить с цитированием
  #8 (permalink)  
Старый 22.10.2014, 19:16
Кандидат Javascript-наук
Посмотреть профиль Найти все сообщения от terminator-101
 
Регистрация: 14.10.2014
Сообщений: 117

kobezzza,
Ну, если ты сам расширял, ты должен был, наверное помнить,об этом. Это называется не "ломается", а "ошибся". И это может произойти не только с расширением Object, но и вообще с чем угодно. Это стандартная хрень
proto={get_: function(){}}
O=function(){}
O.prototype=proto

o1=Object.create(proto)
o2=new O


function foo(params){
   params=params||{}
   params.get_=params.get_||"*"
}


foo(o1)
foo(o2)
alert([o1.get_, o2.get_]) //

То есть, это произошло бы и в случае расширения String, Regexp и пр, равно как и в случае созданного ненативного объекта. Тут дело не в бобине, какбы.
Ответить с цитированием
  #9 (permalink)  
Старый 22.10.2014, 19:21
Аватар для kobezzza
Быдлокодер;)
Отправить личное сообщение для kobezzza Посмотреть профиль Найти все сообщения от kobezzza
 
Регистрация: 19.11.2010
Сообщений: 4,338

terminator-101, в данном случая я "забыл", но такую багу очень легко поймать путём подключения сторонней библиотеки.

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

Цитата:
И это может произойти не только с расширением Object, но и вообще с чем угодно.
Может, но с Object.prototype шанс словить такую багу близится к 100%, если только не городить свои неймспейсы, но это будет бред.
__________________
kobezzza
code monkey

Последний раз редактировалось kobezzza, 22.10.2014 в 19:24.
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск