Есть ли способ установить атрибут по умолчанию для объекта javascript, чтобы:
var emptyObj = {};
// do some magic
emptyObj.nonExistingAttribute // => defaultValue
IE можно игнорировать, Chrome Frame избавил меня от этой головной боли.
Есть ли способ установить атрибут по умолчанию для объекта javascript, чтобы:
var emptyObj = {};
// do some magic
emptyObj.nonExistingAttribute // => defaultValue
IE можно игнорировать, Chrome Frame избавил меня от этой головной боли.
Поскольку я задал вопрос несколько лет назад, все прошло хорошо.
Прокси являются частью ES6. Следующий пример работает в Chrome, Firefox, Safari и Edge:
var handler = {
get: function(target, name) {
return target.hasOwnProperty(name) ? target[name] : 42;
}
};
var p = new Proxy({}, handler);
p.answerToTheUltimateQuestionOfLife; //=> 42
Подробнее в Документация Mozilla по Proxies.
Невозможно установить это в Javascript - возврат undefined
для несуществующих свойств является частью основной спецификации Javascript. См. обсуждение этого аналогичного вопроса. Как я и предложил, один подход (хотя я не могу его рекомендовать) должен был бы определить глобальную функцию getProperty
:
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"
Но это приведет к кучке нестандартного кода, который будет трудно читать другим, и это может иметь непреднамеренные последствия в тех областях, где вы ожидаете или хотите значение undefined. Лучше просто проверить, как вы идете:
var someVar = o.someVar || "my default";
Использовать деструктуризацию (новое в ES6)
Существует отличная документация от Mozila, а также фантастическая запись в блоге, которая объясняет синтаксис лучше, чем я.
var emptyObj = {};
const { nonExistingAttribute = defaultValue } = emptyObj;
console.log(nonExistingAttribute); // defaultValue
Могу ли я переименовать эту переменную? Конечно!
const { nonExistingAttribute: coolerName = 15} = emptyObj;
console.log(coolerName); // 15
А как насчет вложенных данных? Принеси это!
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
Это похоже на типичное использование объектов на основе protoype:
// 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
мой код:
function(s){
s = {
top: s.top || 100, // default value or s.top
left: s.left || 300, // default value or s.left
}
alert(s.top)
}
Или вы можете попробовать это
dict = {
'somekey': 'somevalue'
};
val = dict['anotherkey'] || 'anotherval';
Я добился этого с помощью функции object.assign
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" }
Я думаю, что самый простой подход использует Object.assign
.
Если у вас есть этот класс:
class MyHelper {
constructor(options) {
this.options = Object.assign({
name: "John",
surname: "Doe",
birthDate: "1980-08-08"
}, options);
}
}
Вы можете использовать его следующим образом:
let helper = new MyHelper({ name: "Mark" });
console.log(helper.options.surname); // this will output "Doe"
Документация (с помощью polyfill): https://developer.mozilla.org/it/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
Самое простое из всех решений:
dict = {'first': 1,
'second': 2,
'third': 3}
Теперь
dict['last'] || 'Excluded'
вернет "Исключено", что является значением по умолчанию.
Вчера я увидел статью, в которой упоминается свойство Object.__noSuchMethod__
: JavascriptTips У меня не было возможности поиграть с ним, поэтому я не знаю о поддержке браузера, но, возможно, вы могли бы использовать это в некотором роде?
Я удивлен, что никто не упомянул троичного оператора.
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
Таким образом, даже если значение "c" равно 0, оно все равно получит правильное значение.
Фактически это возможно сделать с Object.create
. Он не будет работать для "неопределенных" свойств. Но для тех, которым было присвоено значение по умолчанию.
var defaults = {
a: 'test1',
b: 'test2'
};
Затем, когда вы создаете свой объект свойств, вы делаете это с помощью Object.create
properties = Object.create(defaults);
Теперь у вас будет два объекта, где первый объект пуст, но прототип указывает на объект defaults
. Чтобы проверить:
console.log('Unchanged', properties);
properties.a = 'updated';
console.log('Updated', properties);
console.log('Defaults', Object.getPrototypeOf(properties));
Один из подходов - взять объект по умолчанию и объединить его с целевым объектом. Целевой объект будет переопределять значения в объекте по умолчанию.
jQuery имеет метод .extend()
, который делает это. Однако jQuery не нужен, поскольку существуют варианты реализации JS Vanilla, которые можно найти здесь:
http://gomakethings.com/vanilla-javascript-version-of-jquery-extend/
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
Мне кажется, это самый простой и читаемый способ сделать это:
let options = {name:"James"}
const default_options = {name:"John", surname:"Doe"}
options = Object.assign({}, default_options, options)
Я пришел сюда в поисках решения, потому что заголовок соответствовал моему описанию проблемы, но это не то, что я искал, но я нашел решение своей проблемы (я хотел иметь значение по умолчанию для атрибута, который был бы динамическим, например, date).
let Blog = {
title : String,
image : String,
body : String,
created: {type: Date, default: Date.now}
}
Приведенный выше код был решением, за которое я наконец-то остановился.