Установить значение по умолчанию атрибутов объекта javascript

Есть ли способ установить атрибут по умолчанию для объекта javascript, чтобы:

var emptyObj = {};
// do some magic
emptyObj.nonExistingAttribute // => defaultValue

IE можно игнорировать, Chrome Frame избавил меня от этой головной боли.

Ответ 1

Поскольку я задал вопрос несколько лет назад, все прошло хорошо.

Прокси являются частью 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.

Ответ 2

Невозможно установить это в 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";

Ответ 3

Использовать деструктуризацию (новое в 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

Ответ 4

Это похоже на типичное использование объектов на основе 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

Ответ 5

мой код:

function(s){
    s = {
        top: s.top || 100,    // default value or s.top
        left: s.left || 300,  // default value or s.left
    }
    alert(s.top)
}

Ответ 6

Или вы можете попробовать это

dict = {
 'somekey': 'somevalue'
};

val = dict['anotherkey'] || 'anotherval';

Ответ 7

Я добился этого с помощью функции 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" }

Ответ 8

Я думаю, что самый простой подход использует 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

Ответ 9

Самое простое из всех решений:

dict = {'first': 1,
        'second': 2,
        'third': 3}

Теперь

dict['last'] || 'Excluded'

вернет "Исключено", что является значением по умолчанию.

Ответ 10

Вчера я увидел статью, в которой упоминается свойство Object.__noSuchMethod__: JavascriptTips У меня не было возможности поиграть с ним, поэтому я не знаю о поддержке браузера, но, возможно, вы могли бы использовать это в некотором роде?

Ответ 11

Я удивлен, что никто не упомянул троичного оператора.

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, оно все равно получит правильное значение.

Ответ 12

Фактически это возможно сделать с 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));

Ответ 13

Один из подходов - взять объект по умолчанию и объединить его с целевым объектом. Целевой объект будет переопределять значения в объекте по умолчанию.

jQuery имеет метод .extend(), который делает это. Однако jQuery не нужен, поскольку существуют варианты реализации JS Vanilla, которые можно найти здесь:

http://gomakethings.com/vanilla-javascript-version-of-jquery-extend/

Ответ 14

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

Ответ 15

Мне кажется, это самый простой и читаемый способ сделать это:

let options = {name:"James"}
const default_options = {name:"John", surname:"Doe"}

options = Object.assign({}, default_options, options)

Ссылка Object.assign()

Ответ 16

Я пришел сюда в поисках решения, потому что заголовок соответствовал моему описанию проблемы, но это не то, что я искал, но я нашел решение своей проблемы (я хотел иметь значение по умолчанию для атрибута, который был бы динамическим, например, date).

let Blog = {
title  : String,
image  : String,
body   : String,
created: {type: Date, default: Date.now}
}

Приведенный выше код был решением, за которое я наконец-то остановился.