Комментарии 32
Подождите, но вы сравниваете генерацию «классов», а не экземпляров, иначе вы бы никогда не получили таких «результатов». В чем смысл такого сравнения?
+5
«Никогда не говори никогда» © :)
Вот тестик наваял по генерации экземпляров jsperf.com/clonejs-vs-new
Вот тестик наваял по генерации экземпляров jsperf.com/clonejs-vs-new
+1
А что удивительно в том, что пройтись по объекту и скопировать все свойства, дольше, чем просто задать прототип?
0
Сколько в среднем вы создаете экземпляров от одного класса? 1-2? иногда сотни-тысячи, но значительно реже.
new быстрее clone в 2-5 раз, но при этом clone быстрее класса-конструктора в 20-30 раз.
Если вам нужны сотни экземпляров, можете добавить конструктор в прототип, и использовать new для инстанцирования:
new быстрее clone в 2-5 раз, но при этом clone быстрее класса-конструктора в 20-30 раз.
Если вам нужны сотни экземпляров, можете добавить конструктор в прототип, и использовать new для инстанцирования:
var myClass = {
constructor: function(){},
method: function(){}
};
myClass.constructor.prototype = myClass;
var instance = new myClass.constructor;
+2
Ведь
__proto__
is deprecated? Или нет? Как c поддержкой в Strict Mode?0
с чего вы взяли что он deprecated? Даже в IE 11 обещают его поддержку.
+1
Да, кажется ECMAScript 6 собираются стандартизировать это свойство, но судя по публикациям это свойство использовать не рекомендуют, потому что в ECMAScript 5 его нет.
Но мне самому интересно: насколько правильно использовать
Но мне самому интересно: насколько правильно использовать
__proto__
?0
Мне кажется, уже можно использовать, т.к. из ECMAScript 6 его врядли выпилят, и если даже такое недоразумение случится, то функцию clone всегда можно переписать с использованием Object.create или функций-конструкторов.
0
developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/setPrototypeOf
Буду обновлять комментарии, да…
Буду обновлять комментарии, да…
+1
Лучше всего читать последнюю версию стандарта ( html-копия ). В нём есть свойство __proto__ и, даже, функция Reflect.setPrototypeOf
+1
Хороший пример генерирования псевдоклассов и наследования дает Typescript.
0
Сомнительный выигрыш в производительности при потери читаемости и лёгкости статического анализа. Например PhpStrom не может понять какие методы «класса» есть у объекта созданного с помощью вашего метода clone.
Обретите для себя es6-классы, благо, есть много имплиментаций.
Обретите для себя es6-классы, благо, есть много имплиментаций.
+1
es6-классы как поддерживаются IDE, например WebStorm? Потому что я уже почти созрел для перехода на них. Я даже созрел для полного перехода на ES6, но решил таки дождаться утверждения.
+1
У Sublime есть дополнение, называется Javascript next. Классы и лямбды видит)
0
На данный момент в WebStorm/PhpStorm есть поддержка es6 стандарта, примерно, 2012 года.
Есть поддержка: классы, деструктуризация, let, rest, spread, дефолтные значения у функций, стрелочные функции, QuasiLiterals (строковые шаблоны)
Нету: объектной деструктуризации, разряженного массива как шаблона деструктуризации, дефолтных значений деструктуризации.
Это основное. Пользоваться вполне можно, но к сожалению, PhpStorm периодически зависает и вываливает сообщение о нехватке памяти — ничего серьёзного, после этого продолжает работать, просто время отнимает.
Ещё traceur встроенный в PhpStorm старой версии и я не нашел как обновить или указать свой.
Есть поддержка: классы, деструктуризация, let, rest, spread, дефолтные значения у функций, стрелочные функции, QuasiLiterals (строковые шаблоны)
Нету: объектной деструктуризации, разряженного массива как шаблона деструктуризации, дефолтных значений деструктуризации.
Это основное. Пользоваться вполне можно, но к сожалению, PhpStorm периодически зависает и вываливает сообщение о нехватке памяти — ничего серьёзного, после этого продолжает работать, просто время отнимает.
Ещё traceur встроенный в PhpStorm старой версии и я не нашел как обновить или указать свой.
+1
Почему бы тогда сразу не задавать __proto__?
var donald = {name: "Donald", __proto__: talkingDuck$};
+2
для совместимости с IE
0
Я ни в коем случае не говорю, что Ваш код или подход плохой или неправильный, просто как вариант:
Можно это дело оформить как graceful degradation:
Тогда вызов
Можно это дело оформить как graceful degradation:
var protohack = (function() {
function Clone(properties) {
for (var propName in properties){
this[propName] = properties[propName];
}
}
if ({__proto__: Clone.prototype} instanceof Clone) {
return new Function('o', 'return o;'); // No-op, от глобального скопа
}
return function(o) {
if (!o || !o.__proto__ || typeof o.__proto__ !== 'object') {
return o; // В объекте не перекрывается __proto__, или это вообще не объект. Возвращаем обратно как есть
}
Clone.prototype = o.__proto__;
delete o.__proto__;
return new Clone(o); // Возвращаем новый объект с нужным [[prototype]]
}
})();
Тогда вызов
var donald = protohack({name: "Donald", __proto__: talkingDuck$});
вернет одно и тоже и в ES5 и в дремучем ES3. 0
Странно называть функцию clone, когда она на самом деле не клонирует:
Ну и в бенчмарке у вас замер «new constructor» замеряет совсем не то, что вы думаете — совсем даже не скорость создания объекта, а скорость присвоения свойства prototype (FF, Chrome страдают от этого, Safari — нет)
var a = { ref: HUGE_OBJECT };
var b = clone(a);
b.ref = null;
a = null;
// а HUGE_OBJECT-то утёк
Ну и в бенчмарке у вас замер «new constructor» замеряет совсем не то, что вы думаете — совсем даже не скорость создания объекта, а скорость присвоения свойства prototype (FF, Chrome страдают от этого, Safari — нет)
+2
Спасбо Quadratoff, статья хороша :)
Но всё же «люто плюсую» предыдущий комментарий от mraleph.
Если можете, пожалуйста — попдравьте.
Не вводите в заблуждение тех, кто не знает, что это не clone ^)
Хотя бы приписочку о, например:
Но всё же «люто плюсую» предыдущий комментарий от mraleph.
Если можете, пожалуйста — попдравьте.
Не вводите в заблуждение тех, кто не знает, что это не clone ^)
Хотя бы приписочку о, например:
jQuery.extend(true, {}, oldObject);
0
Подскажите пожалуйста ещё, вот, например:
clonejs
clonejs-nano
Вот как всё таки, используя их, мне сделать мне этот would not affect ?
Пробовал на следующем очень простом, согласитесь, объекте:
Делал:
Во всех случаях после:
изменялся и сам «родительский» obj, т.е. становилось:
Попробовал после этого почитать внимательно доку и API, понимаю, что, наверное, что-то делаю не так. Использовал и:
Тоже не помогло… Наверное как-то не так использовал.
Но, всё же, может быть как-то можно что-нибудь упростить в концепции, так сказать «for the rest of us»?
Заранее спасибо :)
clonejs
… lazy shallow copy…
it would not affect the cloned object (prototype)
clonejs-nano
… lazy shallow copy…
it would not affect the cloned object (prototype)
Вот как всё таки, используя их, мне сделать мне этот would not affect ?
Пробовал на следующем очень простом, согласитесь, объекте:
var obj = {
s : {
ss: 1
}
};
Делал:
var cln = clone (obj);
// и
var cln = clone.byProto (obj, {});
// и
var cln = clone.byConstructor (obj, {});
// и
var cln = clone.byObjectCreate (obj, {});
Во всех случаях после:
cln.s.ss = 5;
изменялся и сам «родительский» obj, т.е. становилось:
console.log ( obj.s.ss ); // 5
Попробовал после этого почитать внимательно доку и API, понимаю, что, наверное, что-то делаю не так. Использовал и:
obj.$clone();
cln.$clone();
Тоже не помогло… Наверное как-то не так использовал.
Но, всё же, может быть как-то можно что-нибудь упростить в концепции, так сказать «for the rest of us»?
Заранее спасибо :)
0
Ключевое слово shallow.
0
Не не не, привожу полную цитату с git, раз уж…
Т.е. если в child что-то менять, то parent не должен «затрагиваться».
Вы почитали бы https://github.com/quadroid/clonejs, привёл же ссылки.
clone function produces new objects — Clones.
Clone object — this is the lazy shallow copy, i.e., it is actually not a copy, it's just a reference to the object, with one difference: if you will add/replace any of its properties, it would not affect the cloned object (prototype).
All JavaScript objects are clones of Object.prototype (except itself and objects, created by Object.create(null)).
Т.е. если в child что-то менять, то parent не должен «затрагиваться».
Вы почитали бы https://github.com/quadroid/clonejs, привёл же ссылки.
0
В обратную сторону, когда меняю родительский объект, тоже не работает.
Тестирую в Google Chrome 29.0.1547.65.
Тестирую в Google Chrome 29.0.1547.65.
0
Про обратную сторону я не говорил ;)
Для решения этой проблемы в cloneJS клонируемые объекты-классы (behaviors), должны быть immutable.
Для решения этой проблемы в cloneJS клонируемые объекты-классы (behaviors), должны быть immutable.
+1
Вот как всё таки, используя их, мне сделать мне этот would not affect ?
не вырывайте фразу из контекста:
if you will add/REplace any of its properties, it would not affect the cloned object (prototype).
Это не замена свойства:
cln.s.ss = 5;
Я писал про
… lazy shallow copy…
+1
По поводу утечки — да, проблема, но для освобождения памяти наверное все-таки правильней использовать оператор delete (b.ref), и тогда эта утечка сразу выплывет наружу.
Возможно, стоит сделать метод
Возможно, стоит сделать метод
clone.clearAllOf(a)
, для рекурсивного удаления всех свойств. 0
Оператор
Далее ведь я не обязательно хочу свойство удалять, я его допустим хочу обновить, а утечка все равно случится.
Дополнительное наблюдение, если вы пишете код в стиле:
где
delete
лучше вообще не использовать (за исключением очень крайних случаев), от него одно падение производительности. Еще он обладает таким интересным парадоксальным свойством (по крайней мере на V8), что после его применения объем занимаемой объектом памяти может возрасти (а не уменьшится).Далее ведь я не обязательно хочу свойство удалять, я его допустим хочу обновить, а утечка все равно случится.
Дополнительное наблюдение, если вы пишете код в стиле:
var p = { a: 1, b: 2 };
var q = clone(p);
q.a++;
var u = clone(p);
u.b++;
some_f(q);
some_f(u);
где
some_f
работает с полями a / b, то some_f
будет работать медленнее, чем она работала будь q
и u
созданы обычным конструктором, потому что они имею разные скрытые классы и как результат доступ к полям становится полиморфным.0
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Публикации
Изменить настройки темы
Нужны ли в JavaScript классы? часть 2