web-dev-qa-db-fra.com

Définir la valeur par défaut des attributs d'objet javascript

Est-il possible de définir l'attribut par défaut d'un objet javascript tel que:

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

IE peut être ignoré, Chrome Frame m'a soulagé de ce mal de tête.

58
sandstrom

Depuis que j'ai posé la question il y a plusieurs années, les choses ont bien progressé. 

Les procurations font partie de ES6. L'exemple suivant fonctionne dans Chrome, Firefox, Safari et Edge :

var handler = {
  get: function(target, name) {
    return target.hasOwnProperty(name) ? target[name] : 42;
  }
};

var p = new Proxy({}, handler);

p.answerToTheUltimateQuestionOfLife; //=> 42

En savoir plus dans la documentation de Mozilla sur les procurations .

69
sandstrom

Il n’existe pas de moyen de définir cela en Javascript - renvoyer undefined pour des propriétés inexistantes fait partie de la spécification JavaScript de base. Voir la discussion pour cette question similaire . Comme je l’ai suggéré, une approche (bien que je ne puisse pas vraiment le recommander) consisterait à définir une fonction globale 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"

Mais cela conduirait à une série de codes non standard qui seraient difficiles à lire, et cela pourrait avoir des conséquences inattendues dans des domaines où vous vous attendriez à une valeur non définie Mieux vaut vérifier au fur et à mesure: 

var someVar = o.someVar || "my default";
25
nrabinowitz

Utilisez déstructuration (nouveauté de ES6)

Il y a beaucoup de documentation de Mozila ainsi qu'un fantastique article de blog qui explique la syntaxe mieux que moi.

Pour répondre à ta question

var emptyObj = {};
const { nonExistingAttribute = defaultValue } = emptyObj;
console.log(nonExistingAttribute); // defaultValue

Aller plus loin

Puis-je renommer cette variable? Sûr!

const { nonExistingAttribute: coolerName = 15} = emptyObj;
console.log(coolerName); // 15

Qu'en est-il des données imbriquées? L'amener sur!

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
11
alexdriedger

mon code est:

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

Cela ressemble certainement à l’utilisation typique d’objets prototypes:

// 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
10
jfriend00

Ou tu peux essayer ça

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

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

J'ai vu un article hier qui mentionne une propriété Object.__noSuchMethod__: JavascriptTips Je n'ai pas eu l'occasion de jouer avec elle, alors je ne connais pas le support du navigateur, mais vous pourriez peut-être l'utiliser d'une manière ou d'une autre?

2
James Long

Je parviens à cela avec la fonction object.assign

const defaultProperties = { 'foo': 'bar', 'bar': 'foo' }
const overwriteProperties = { 'foo': 'foo' }
const newObj = Object.assign(defaultProperties, overwriteProperties) // { 'foo': 'foo', 'bar': 'foo' }
2
Colin

Je suis surpris que personne n'ait encore mentionné l'opérateur ternaire.

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

De cette manière, même si la valeur de 'c' est 0, la valeur correcte sera toujours obtenue.

2
Alan Dong

La solution la plus simple:

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

À présent,

dict['last'] || 'Excluded'

retournera 'Exclus', qui est la valeur par défaut.

1
Gil Baggio

Je pense que l'approche la plus simple utilise Object.assign.

Si vous avez cette classe:

class MyHelper {
    constructor(options) {
        this.options = Object.assign({
            name: "John",
            surname: "Doe",
            birthDate: "1980-08-08"
        }, options);
    }
}

Vous pouvez l'utiliser comme ceci:

let helper = new MyHelper({ name: "Mark" });
console.log(helper.options.surname); // this will output "Doe"

Documentation (avec polyfill): https://developer.mozilla.org/it/docs/Web/JavaScript/Reference/Global_Objects/Object/assign

1
gianlucaparadise

C'est effectivement possible avec Object.create. Cela ne fonctionnera pas pour les propriétés "non définies". Mais pour ceux qui ont reçu une valeur par défaut.

var defaults = {
    a: 'test1',
    b: 'test2'
};

Ensuite, lorsque vous créez votre objet de propriétés, vous le faites avec Object.create

properties = Object.create(defaults);

Maintenant, vous aurez deux objets où le premier objet est vide, mais le prototype pointe vers l'objet defaults Tester:

console.log('Unchanged', properties);
properties.a = 'updated';
console.log('Updated', properties);
console.log('Defaults', Object.getPrototypeOf(properties));
0
Nils
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
0
Vlad V

Je suis venu ici à la recherche d'une solution car l'en-tête correspond à la description de mon problème, mais ce n'est pas ce que je cherchais mais j'ai une solution à mon problème (je voulais avoir une valeur par défaut pour un attribut qui serait dynamique comme la date ).

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

Le code ci-dessus était la solution pour laquelle je me suis finalement installé.

0
Jibin Philipose

Une approche serait de prendre un objet par défaut et de le fusionner avec l'objet cible. L'objet cible remplacerait les valeurs de l'objet par défaut.

jQuery a la méthode .extend() qui le fait. jQuery n'est pas nécessaire cependant, car il existe des implémentations de Vanilla JS telles que celles-ci peuvent être trouvées ici:

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

0
Doug Amos