Czy istnieje sposób na ustawienie domyślnego atrybutu obiektu javascript, takiego jak:
var emptyObj = {};
// do some magic
emptyObj.nonExistingAttribute // => defaultValue
IE można zignorować, Chrome Frame uwolnił mnie od tego bólu głowy.
javascript
sandstrom
źródło
źródło
Odpowiedzi:
Odkąd zadałem to pytanie kilka lat temu, sprawy potoczyły się ładnie.
Serwery proxy są częścią ES6. Poniższy przykład działa w Chrome, Firefox, Safari i Edge :
var handler = { get: function(target, name) { return target.hasOwnProperty(name) ? target[name] : 42; } }; var p = new Proxy({}, handler); p.answerToTheUltimateQuestionOfLife; //=> 42
Przeczytaj więcej w dokumentacji Mozilli na temat serwerów proxy .
źródło
Object.getEntries
nie można wywołać serwera proxy :(Object.entries
, możesz zmodyfikować procedurę obsługi, aby ustawić właściwości, gdy są one dostępne. Zmieńreturn target.hasOwnProperty(name) ? target[name] : 42;
naif (!target.hasOwnProperty(name)) target[name] = 42; return target[name];
.Użyj destrukturyzacji (nowość w ES6)
Jest świetna dokumentacja Mozili, a także fantastyczny wpis na blogu, który wyjaśnia składnię lepiej niż ja.
Odpowiedzieć na Twoje pytanie
var emptyObj = {}; const { nonExistingAttribute = defaultValue } = emptyObj; console.log(nonExistingAttribute); // defaultValue
Idąc dalej
Czy mogę zmienić nazwę tej zmiennej? Pewnie!
const { nonExistingAttribute: coolerName = 15} = emptyObj; console.log(coolerName); // 15
A co z danymi zagnieżdżonymi? Dawaj!
var nestedData = { name: 'Awesome Programmer', languages: [ { name: 'javascript', proficiency: 4, } ], country: 'Canada', }; var {name: realName, languages: [{name: languageName}]} = nestedData ; console.log(realName); // Awesome Programmer console.log(languageName); // javascript
źródło
Nie ma sposobu, aby to ustawić w JavaScript - zwracanie
undefined
w przypadku nieistniejących właściwości jest częścią podstawowej specyfikacji Javascript. Zobacz dyskusję dotyczącą tego podobnego pytania . Jak tam zasugerowałem, jednym podejściem (chociaż nie mogę tego naprawdę polecić) byłoby zdefiniowaniegetProperty
funkcji globalnej :function getProperty(o, prop) { if (o[prop] !== undefined) return o[prop]; else return "my default"; } var o = { foo: 1 }; getProperty(o, 'foo'); // 1 getProperty(o, 'bar'); // "my default"
Doprowadziłoby to jednak do powstania wielu niestandardowych kodów, które byłyby trudne do odczytania dla innych i mogłoby mieć niezamierzone konsekwencje w obszarach, w których można oczekiwać lub chcieć niezdefiniowanej wartości. Lepiej po prostu sprawdzić na bieżąco:
var someVar = o.someVar || "my default";
źródło
var someVar = o.someVar || "my default";
będzie miał potencjalnie nieoczekiwane wyniki, gdy o.someVar zostanie wypełniony, ale zostanie oszacowany na false (np. null, 0, "").someVar = o.someVar === undefined ? o.someVar : "my default";
byłoby lepiej. Zwykle używam||
samego, gdy wartość domyślna również ocenia się nafalse. (e.g.
o.someVar ||null
lubfalse
w ten sam sposób jak nieruchomość nieustawioną, w którym to przypadku ma to podwójne zadanie. Jednak ostrzeżenie jest uczciwe.someVar = o.someVar === undefined ? "my default" : o.someVar;
, tylko drobny problem, ale trochę mnie rzucił, kiedy pierwszy raz wypróbowałem twój kod ;-)To z pewnością brzmi jak typowe użycie obiektów opartych na protojach:
// define a new type of object var foo = function() {}; // define a default attribute and value that all objects of this type will have foo.prototype.attribute1 = "defaultValue1"; // create a new object of my type var emptyObj = new foo(); console.log(emptyObj.attribute1); // outputs defaultValue1
źródło
attribute1: defaultValue1
znajduje się w prototypie, a console.log wylicza tylko elementy ustawione w obiekcie najwyższego poziomu, a nie w prototypie. Ale wartość jest taka, jak mojeconsole.log(emptyObj.attribute1)
pokazy.JSON.stringify(emptyobj)
. Byłem zmuszony stworzyć metodę, która zwraca wszystkie atrybuty w odpowiedzi na ten problemmój kod to:
function(s){ s = { top: s.top || 100, // default value or s.top left: s.left || 300, // default value or s.left } alert(s.top) }
źródło
function foo( array $kwargs = array() ) { // Fill in defaults for optional keyworded arguments. $kwargs += array( 'show_user' => true, 'show_links' => false, ); ...
Sposób, w jaki to osiągam, to
object.assign
funkcjaconst defaultProperties = { 'foo': 'bar', 'bar': 'foo' }; const overwriteProperties = { 'foo': 'foo' }; const newObj = Object.assign({}, defaultProperties, overwriteProperties); console.log(defaultProperties); // {"foo": "bar", "bar": "foo"} console.log(overwriteProperties); // { "foo": "foo" }; console.log(newObj); // { "foo": "foo", "bar": "foo" }
źródło
overwriteProperties
w prawidłowy sposób:const newObj = Object.assign({}, defaultProperties, overwriteProperties)
Myślę, że najprostszym podejściem jest użycie
Object.assign
.Jeśli masz tę klasę:
class MyHelper { constructor(options) { this.options = Object.assign({ name: "John", surname: "Doe", birthDate: "1980-08-08" }, options); } }
Możesz go używać w ten sposób:
let helper = new MyHelper({ name: "Mark" }); console.log(helper.options.surname); // this will output "Doe"
Dokumentacja (z wypełnieniem polyfill): https://developer.mozilla.org/it/docs/Web/JavaScript/Reference/Global_Objects/Object/ assign
źródło
Najprostsze ze wszystkich rozwiązań:
dict = {'first': 1, 'second': 2, 'third': 3}
Teraz,
dict['last'] || 'Excluded'
zwróci wartość „Wykluczone”, która jest wartością domyślną.
źródło
dict = {'first': 0, 'second': 1, 'third': 2}
a.b.c.d
. Jeśli a, d lub c są nieokreślone, napotkasz błąd, ale możesz to zrobić(((a || {}).b || {}).c || {}).d) || "default"
Albo możesz spróbować
dict = { 'somekey': 'somevalue' }; val = dict['anotherkey'] || 'anotherval';
źródło
String()
tego naprawić? Jak w:val = dict[String('anotherkey')] || 'anotherval';
d = {x: 1, y: 0}
to,d['y'] || 100
a nie błędnie daje 100. Następnie wypróbuj swój pomysł, który jestd[String('y')] || 100
- nadal niewłaściwie daje 100, kiedy powinien dać 0.Wydaje mi się, że jest to najprostszy i najbardziej czytelny sposób:
let options = {name:"James"} const default_options = {name:"John", surname:"Doe"} options = Object.assign({}, default_options, options)
Odwołanie do obiektu Object. assign ()
źródło
Widziałem wczoraj artykuł, w którym wspomniano o
Object.__noSuchMethod__
właściwości: Porady Javascript Nie miałem okazji się nią bawić, więc nie wiem o obsłudze przeglądarek, ale może mógłbyś to w jakiś sposób wykorzystać?źródło
Dziwię się, że nikt jeszcze nie wspomniał o operatorze trójskładnikowym.
var emptyObj = {a:'123', b:'234', c:0}; var defaultValue = 'defaultValue'; var attr = 'someNonExistAttribute'; emptyObj.hasOwnProperty(attr) ? emptyObj[attr] : defaultValue;//=> 'defaultValue' attr = 'c'; // => 'c' emptyObj.hasOwnProperty(attr) ? emptyObj[attr] : defaultValue; // => 0
W ten sposób, nawet jeśli wartość „c” jest równa 0, nadal otrzyma poprawną wartość.
źródło
Object.withDefault = (defaultValue,o={}) => { return new Proxy(o, { get: (o, k) => (k in o) ? o[k] : defaultValue }); } o = Object.withDefault(42); o.x //=> 42 o.x = 10 o.x //=> 10 o.xx //=> 42
źródło
W rzeczywistości jest to możliwe
Object.create
. Nie będzie działać dla „niezdefiniowanych” właściwości. Ale dla tych, którym nadano wartość domyślną.var defaults = { a: 'test1', b: 'test2' };
Następnie, kiedy tworzysz obiekt właściwości, robisz to z
Object.create
properties = Object.create(defaults);
Teraz będziesz mieć dwa obiekty, w których pierwszy obiekt jest pusty, ale prototyp wskazuje na ten
defaults
obiekt. Testować:console.log('Unchanged', properties); properties.a = 'updated'; console.log('Updated', properties); console.log('Defaults', Object.getPrototypeOf(properties));
źródło
Jednym podejściem byłoby pobranie obiektu domyślnego i scalenie go z obiektem docelowym. Obiekt docelowy przesłania wartości w obiekcie domyślnym.
jQuery ma rozszerzenie
.extend()
metodę, która to robi. jQuery nie jest jednak potrzebne, ponieważ istnieją proste implementacje JS, takie jak można znaleźć tutaj:http://gomakethings.com/vanilla-javascript-version-of-jquery-extend/
źródło
Przyszedłem tutaj, szukając rozwiązania, ponieważ nagłówek pasował do opisu mojego problemu, ale to nie jest to, czego szukałem, ale znalazłem rozwiązanie mojego problemu (chciałem mieć domyślną wartość dla atrybutu, który byłby dynamiczny, jak data ).
let Blog = { title : String, image : String, body : String, created: {type: Date, default: Date.now} }
Powyższy kod był rozwiązaniem, na które ostatecznie się zdecydowałem.
źródło