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.
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.
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 .
Object.getEntriesnie 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;na if (!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.
var emptyObj = {};
const { nonExistingAttribute = defaultValue } = emptyObj;
console.log(nonExistingAttribute); // defaultValue
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
Nie ma sposobu, aby to ustawić w JavaScript - zwracanie undefinedw 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 zdefiniowanie getPropertyfunkcji 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";
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ę na false. (e.g. o.someVar ||
nulllub falsew 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
attribute1: defaultValue1znajduje się w prototypie, a console.log wylicza tylko elementy ustawione w obiekcie najwyższego poziomu, a nie w prototypie. Ale wartość jest taka, jak moje console.log(emptyObj.attribute1)pokazy.
JSON.stringify(emptyobj). Byłem zmuszony stworzyć metodę, która zwraca wszystkie atrybuty w odpowiedzi na ten problem
mó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)
}
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.assignfunkcja
const 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" }
overwritePropertiesw 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
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ą.
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';
String()tego naprawić? Jak w:val = dict[String('anotherkey')] || 'anotherval';
d = {x: 1, y: 0}to, d['y'] || 100a nie błędnie daje 100. Następnie wypróbuj swój pomysł, który jest d[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)
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ć?
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ść.
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
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 defaultsobiekt. Testować:
console.log('Unchanged', properties);
properties.a = 'updated';
console.log('Updated', properties);
console.log('Defaults', Object.getPrototypeOf(properties));
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/
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.