Лучшая замена deprecated __proto__ при литеральном создании объекта
C наступающим!
Начал знакомиться с JS, в основном - на этом сайте, спасибо Вам! К вопросу - сначала заготовил значения по умолчанию - конструктор: var MyDb = function (name) { this.name=name; this.objStoreList=['fromCons']; this.origin='coreJSON' // other props} И есть объект (будет получаться в виде JSON по XHR) var myDbs = { dbsList: [ {name:'CoreDb',objStoreList:['theFirst1']}, {name:'OtherDb'}, {name:'MiscDb', origin:'miscJSON'} ], up2Date:TS22().TimeStamp, //etc...}; И необходимо заполнить отсутствующие свойства и методы объектов из массива dbsList дефолтными из конcтруктора MyDb (сохраняя уже имеющиеся значения). Сначала вдохновился примерами с prototype#наследование-через-ссылку-proto: Через цикл myDbs.dbsList.forEach делал item.__proto__ = new MyDb Что прекрасно меня удовлетворяло, ибо в прототипе каждого объекта были зарезервированы дефолтные значения. Однако потом прочитал, что использование __proto__ - bad practice и вообще - оно deprecated. Тогда я, тоже через цикл myDbs.dbsList.forEach сделал var tempMyDb = new MyDb; for (var key in tempMyDb) { if (item.hasOwnProperty(key)) {continue;} item[key]=tempMyDb[key];}; Таким образом, каждый объект из массива получил недостающие свойства как собственные (hasOwnProperty), а не в его прототипе. Причём var tempMyDb = new MyDb;я загнал в цикл forEach сознательно, чтобы у каждого item была своя ссылка на отдельный объект, и ещё один var tempMyDb = new MyDb;после всех циклов, чтобы разрушить связь. :) Потому что, в противном случае, действие myDbs.dbsList.forEach(function(item,i){ if (i==0) {item.objStoreList.push('Settings','Pettings', 'Elems')} }); почему-то меняло свойство не только у item[0], но и у всех объектов, получивших ссылку на это свойство. В общем, мне самому не нравится, так как никакого наследования у меня не получается, что-то с иерархией не то. :p Хочется ведь, чтобы каскад был направлен в одну сторону - меняя св-во в конструкторе (или в прототипе, или ещё где), я меняю у всех наследников, а если меняю у наследника - ничего не должно влиять на родителей или братьев. Собственно, вопрос звучит так, наверное: хотелось бы привязать заданные литерально объекты к определённому конструктору, чтобы менять свойства и методы централизованно и каскадно (если будет цепочка наследования). Простите за сумбур, JS - мой первый язык программирования, и на начальной стадии. :p P.S.: пока писал всё это, подумал, что м.б. будет правильно каждый элемент в массиве подменять объект new MyDb, через tempVar заменив дефолтные значения на уже имеющиеся? Т.о., они все будут привязаны к конструктору MyDb и сохранят то, что имеют. Дело в том, что помимо вложенности по наследованию тут предполагается ещё и вложенность объектов по сути myDbs.dbsList[i].ObjStoreList[j].IndxList[k], у каждого из которых предполагается свой прототип(или конструктор). :blink: P.P.S.: Спасибо тем, кто хотя бы прочёл это. |
Можешь попробовать вот такую парашу:
extend=function(src, trg){for(var i in src) trg[i]=src[i]} function Db(ob){ extend(ob, this) return this } Db.prototype.foo=1 Db.prototype.bar=1 Db.prototype.baz=1 dbs={ list: [ {foo: 10}, {foo: 100, bar: 10} ] } for(var i in dbs.list) dbs.list[i]=new Db(dbs.list[i]) console.log( dbs.list[0].foo, dbs.list[0].bar, dbs.list[0].baz, dbs.list[1].foo, dbs.list[1].bar, dbs.list[1].baz, dbs.list[0].constructor, dbs.list[1].constructor, dbs.list[0].hasOwnProperty("foo"), dbs.list[0].hasOwnProperty("bar"), dbs.list[0].hasOwnProperty("baz"), dbs.list[1].hasOwnProperty("foo"), dbs.list[1].hasOwnProperty("bar"), dbs.list[1].hasOwnProperty("baz") ) // 10 1 1 100 10 1 [Function: Db] [Function: Db] true false false true true false Так у тебя восстановится вся иерархия. Но по-хорошему, следовало бы сраным комитетчикам яйца оторвать. __proto__ , в общем случае, без бубнов, ничем не заменишь, это сердце языка, блять. Вроде, какой то setPrototypeOf обещают, посмотрим. |
krutoy, 1) пощади JS, не учи новичков говнокоду, 2) сраным комитетчикам, наверное, виднее? Никто у тебя гибкости не отнимает, setPrototypeOf полностью аналогичен сеттеру __proto__.
ssadfaf, учи сразу ES6 и ES7. Это пока что неутвержденные (но близящиеся к тому) версии стандарта JS, сейчас ими можно пользоваться через компиляцию. В ES6 задача решается элементарно встроенными средствами: class Character { constructor(data) { Object.assign(this, {//Default properties hp: 1000, energy: 500, speed: 100 }, data); } } function loadCharacters() { return [ new Character({hp: 10000, energy: 10000, speed: 10}), new Character({hp: 100}), new Character() ]; } console.log(loadCharacters()); Для решения на ES5- тебе нужна функция extend из, например, underscore или jQuery, выглядеть это будет так (в примере применен underscore): function Character(data) { _.extend(this, {//Default properties hp: 1000, energy: 500, speed: 100 }, data); } function loadCharacters() { return [ new Character({hp: 10000, energy: 10000, speed: 10}), new Character({hp: 100}), new Character() ] } Наследование, как можно было заметить, ни в том, ни в другом случае не нужно. |
|
Мне сегодня снились прототипы... :dance:
Спасибо Вам всем за отклик. :thanks: В обратном порядке: Erolast, сенкс за ссылки, добавил в букмаркс. Последнюю, правда, уже читал. :p Насчёт jQuery и прочего - мне ещё чистый JS изучать и изучать. Эти библиотеки прекрасны, но есть опасность, получив их неограниченные возможности и не разбравшись в основах, тупо фигачить по шаблонам и примерам, пока не упрешься в какую-нибудь проблему, которую ты и сформулировать-то не сможешь. Вот как сейчас, например.:) Касательно ES6 - а как скоро он будет имплементирован в webkit Android? По моей задумке хочу сделать себе лайтового универсального помощника на ПК и Андроид (от 4.4, чтобы с поддержкой indexeddb и HTML5). Посмотрел на в таблицы совместимости через MDN - setPrototypeOf и Object.assign пока как-то не очень с мобильными платформами. Но за надежду на лучшее - сенкс. krutoy, я, наверное, сильно переврал Ваш код, но у меня не получилось. Я пока во всяких this плаваю, как топор. Вот мои конструктор и расширитель: var MyDb11111 = function (x3) { extend(x3, this); return this; } MyDb11111.prototype.name='nameFromPrototype'; MyDb11111.prototype.objStList=['objStListFromPrototype0', 'objStListFromPrototype1']; MyDb11111.prototype.origin='originFromPrototype'; MyDb11111.prototype.destination='destinationFromPrototype'; var extend=function(src, trg){for(var key in src) trg[key]=src[key]};А вот тестовая функция: function TestPest242() { var myDbs = {dbsList:[{name:'CoreDb',origin:'zz_core'},{name:'Misc'},{name:'BkMrks',destination:'stayHere', objStList:['Hrefs']}],up2Date:TS22().TimeStamp}; for(var key in myDbs.dbsList) myDbs.dbsList[key]=new MyDb11111(myDbs.dbsList[key]); var testMyDb = new MyDb11111; // (1) тест на возможность создания нового объекта myDbs.dbsList.push(testMyDb); // (2) тест на возможность добавления нового объекта MyDb11111.prototype.newProperty='newPropertyFromPrototype'; // (3) тест на возможность добавления нового свойства для всех объектов myDbs.dbsList.forEach(function(item,i){ // тесты: if (i==0) {item.objStList.push('Settings','Pettings', 'Elems');}; // (4) нет своих, push новых if (i==1) {item.objStList.push('Elems1')}; // (5) нет своих, push новых if (i==1) {item.origin = 'MiscJSON'}; // (6) нет своих, создание новых if (i==2) {item.objStList.push('Elems2')}; // (7) есть свои, push новых if (i==2) {item.destination = 'zz_core'}; // (8) есть свои, изменение значения if (i==3) {item.objStList.push('Elems3')}; // (9) нет своих, push новых if (i==3) {item.newProperty = 'propertyNext'}; // (10) нет своих, создание новых }); myDbs.dbsList.forEach(function(item,i){ console.log(" i " + i ); for (var key in item) {console.log(' ownProp: ' + item.hasOwnProperty(key) +' >>> '+ key + " = " + item[key] );}});}Консоль: i 0 ownProp: true >>> name = CoreDb ownProp: true >>> origin = zz_core ownProp: false >>> objStList = objStListFromPrototype0,objStListFromPrototype1,Settings,Pettings,Elems,Elems1,Elems3 ownProp: false >>> destination = destinationFromPrototype ownProp: false >>> newProperty = newPropertyFromPrototype i 1 ownProp: true >>> name = Misc ownProp: true >>> origin = MiscJSON ownProp: false >>> objStList = objStListFromPrototype0,objStListFromPrototype1,Settings,Pettings,Elems,Elems1,Elems3 ownProp: false >>> destination = destinationFromPrototype ownProp: false >>> newProperty = newPropertyFromPrototype i 2 ownProp: true >>> name = BkMrks ownProp: true >>> destination = zz_core ownProp: true >>> objStList = Hrefs,Elems2 ownProp: false >>> origin = originFromPrototype ownProp: false >>> newProperty = newPropertyFromPrototype i 3 ownProp: true >>> newProperty = propertyNext ownProp: false >>> name = nameFromPrototype ownProp: false >>> objStList = objStListFromPrototype0,objStListFromPrototype1,Settings,Pettings,Elems,Elems1,Elems3 ownProp: false >>> origin = originFromPrototype ownProp: false >>> destination = destinationFromPrototypeСобственно, большинство тестов пройдены успешно, кроме главных. Например, при наличии своего свойства-массива // (7) есть свои, push новыхвсё происходит правильно. А вот если // (4), (5), (9) нет своих, push новыхто в них происходит тупо добавление в прототип с искажением всего массива. Есть предположение, что это как-то связано с тем, что массив - сам по себе объект и JS оперирует ссылками вместо примитивов, о чём предупреждалось в примере с хомяками с общим животом, но моего понимания всех связей ещё очень недостаточно. ЧЯДНТ? :help: |
Цитата:
Цитата:
Цитата:
|
Цитата:
Касательно темы топа - скорее всего, на данном этапе придётся действовать постепенно. Поскольку знаний и понимания не хватает, буду оперировать тем, что есть. Я более-менее разобрался с обычными массивами, буду оттуда брать множества Dbs,objecStores,Indexes с их параметрами и перекручивать их через new MyDb. Или так, как уже писал: Цитата:
И вообще - странно, JSON появился и распространился уже достаточно давно, и, мне кажется, что вопрос с отнесением к какому-то классу (псевдоклассу) литерально заданных объектов должен быть уже обсосан со всех сторон. |
Цитата:
Цитата:
Цитата:
Цитата:
|
ssadfaf,
все так и должно работать, так как это св-во наследуется. чтобы работало по другому, надо создать свое свойство в объекте, которое затрет наследуемое extend=function(src, trg){for(var i in src) trg[i]=src[i]} function Db(ob){ extend(ob, this) return this } Db.prototype.arr=["foo"] dbs={ list: [ {} ] } for(var i in dbs.list) dbs.list[i]=new Db(dbs.list[i]) dbs.list[0].arr.push("bar") console.log(Db.prototype.arr, dbs.list[0].arr) dbs.list[0].arr=[] dbs.list[0].arr.push("baz") console.log(Db.prototype.arr, dbs.list[0].arr) // [ 'foo', 'bar' ] [ 'foo', 'bar' ] // [ 'foo', 'bar' ] [ 'baz' ] В Вашем изначальном случае с __proto__ в подобной ситуации тоже менялось свойство прототипа а не самого объекта, просто у каждого объекта, в Вашем случае, был свой "личный" прототип, что неверно, с точки зрения проектирования. item.__proto__ = new MyDb // это неверно. // правильно вот так parent=new MyDb item.__proto__=parent и тогда бы было то же самое. Ваш Вариант не имеет смысла, с тем же успехом можно было тупо экстендить каждый item extend=function(src, trg){for(var i in src) if(!trg[i]) trg[i]=src[i]} pattern={foo: 1, bar: 2, baz: 3} dbs={ list: [ {foo: 10}, {foo: 100, bar: 10} ] } for(var i=0; i<dbs.list.length; i++){ extend(pattern, dbs.list[i]) } for(var i=0; i<dbs.list.length; i++){ console.log(dbs.list[i]) } // { foo: 10, bar: 2, baz: 3 } // { foo: 100, bar: 10, baz: 3 } , а нужно делегирование (если нужно конечно). |
Вложений: 2
krutoy, спасибо! Да, я не чётко мыслю => не чётко излагаю.
Ваш последний вариант лучше всего для меня на данном этапе. Наверное, я действительно не до конца понимаю, что хочу получить. Всё от того, что я делаю себе помощника в изучении HTML/CSS/JS, попутно изучая их. Вот такая вот рекурсия. :) Уже сделал себе заметки и сохранение параметров страниц в LocalStorage c импортом/экспортом в CSV (рис.#1) и решил заняться indexeddb, попутно разбираясь с объектами, ибо элементов на странице стал просто удивительно много. Например, для работы обычными массивами сделал себе нечто вроде проводника (в прилагаемой картинке #2), но тут подумалось, что правильнее было бы сразу работать сразу с объектами (элементами окна, объектами базы данных, файлами JS, etc.), однако и тут всё не так просто. :help: Хотелось сразу проектировать в своём "проводнике", чтобы "рисовать" объекты мышкой, а они чтобы - сразу в JSON. У меня так сейчас так с обычными массивами - тыкаю мышкой по экрану, а в результате имею нечитаемую строку с неограниченным количеством вложений. Да и читать её не надо, так как она всегда выводится древом на экран. Надеюсь, рано или поздно так будет и с объектами. Erolast, тоже спасибо, но я сначала хочу получить базовые знания по HTML, CSS и JS, а потом уж расширять свои возможности. Видите, я даже не до конца понимаю, что я хочу, и что JS в принципе может. Чисто в качестве хобби, никто меня не гонит и результат не спрашивает. Раньше, в детстве - да, было дело, на VBA приходилось такие чудеса в цейтноте на работе вытворять (по образцам из NorthWind.mdb), что потом даже краснеть сил не оставалось. :) И такие "программы" жили годами, блин, а ведь я даже не настоящий А насчёт невнимательности - с возрастом когнитивные способности не улучшаются, я примерно 90% Ваших слов просто не понимаю, да и остальные 10 приходится гуглить :D , так что не обижайтесь, я Вас не игнорирую. Такая небольшая шутка перед праздниками, настроение.:lol: |
Часовой пояс GMT +3, время: 11:55. |