21.10.2014, 19:14
|
Кандидат Javascript-наук
|
|
Регистрация: 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, если чо.
|
|
21.10.2014, 20:19
|
|
|
Регистрация: 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
?
|
|
21.10.2014, 20:30
|
Кандидат Javascript-наук
|
|
Регистрация: 14.10.2014
Сообщений: 117
|
|
Octane,
Смысл в том, что когда у тебя получается вот такая вот хрень а1(... a2(...a3(....a4(....)))) гораздо легче это писать в объектном стиле a1.a2.a3.a4. Дело даже не в записи как таковой, а в том, что ты запариваешься куда какие параметры передавать. В данном случае, явная передача объекта проще.
|
|
22.10.2014, 15:20
|
|
Быдлокодер;)
|
|
Регистрация: 19.11.2010
Сообщений: 4,338
|
|
Не расширяй никогда Object.prototype, а остальные прототипы можно, но аккуратно.
Пример из личного опыта:
Object.prototype.get = function () { ... };
Потом где то в коде была функция:
function foo(params) {
params = params || {};
params.get = params.get || '*'; // И тут всё ломается
}
|
|
22.10.2014, 15:39
|
Кандидат Javascript-наук
|
|
Регистрация: 14.10.2014
Сообщений: 117
|
|
Сообщение от kobezzza
|
И тут всё ломается
|
А что у тебя сломалось, я не понял?
|
|
22.10.2014, 18:21
|
|
Быдлокодер;)
|
|
Регистрация: 19.11.2010
Сообщений: 4,338
|
|
Сообщение от terminator-101
|
А что у тебя сломалось, я не понял?
|
У меня есть функция, которая принимает объект-параметр, в объекте есть свойство, которое в случае, если не задано устанавливается в значение по умолчанию, но этого не происходит, т.к. в прототипе Object есть свойство с таким же именем
params.get = params.get || '*';
Т.е. вместо значения по умолчанию мы получаем ссылку на значение из прототипа и всё ломается.
|
|
22.10.2014, 19:01
|
|
Профессор
|
|
Регистрация: 11.09.2010
Сообщений: 8,804
|
|
Сообщение от kobezzza
|
Не расширяй никогда Object.prototype
|
Да что там, бывает что встроенные свойства малину портят.
Благо, есть Object.create(null), но все равно бесит.
__________________
В личку только с интересными предложениями
|
|
22.10.2014, 19:16
|
Кандидат Javascript-наук
|
|
Регистрация: 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 и пр, равно как и в случае созданного ненативного объекта. Тут дело не в бобине, какбы.
|
|
22.10.2014, 19:21
|
|
Быдлокодер;)
|
|
Регистрация: 19.11.2010
Сообщений: 4,338
|
|
terminator-101, в данном случая я "забыл", но такую багу очень легко поймать путём подключения сторонней библиотеки.
Цитата:
|
Ну, если ты сам расширял, ты должен был, наверное помнить,об этом.
|
Я работаю одновременно над кучей проектов, сумарная кодовая база несколько сотен тысяч строк кода и разумеется помнить обо всём я не могу, поэтому пишу "очевидный" код, а не танцую с бубнами.
Цитата:
|
И это может произойти не только с расширением Object, но и вообще с чем угодно.
|
Может, но с Object.prototype шанс словить такую багу близится к 100%, если только не городить свои неймспейсы, но это будет бред.
Последний раз редактировалось kobezzza, 22.10.2014 в 19:24.
|
|
|
|