javascriptオブジェクト属性のデフォルト値を設定します


82

次のようにjavascriptオブジェクトのデフォルト属性を設定する方法はありますか?

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

IEは無視できますが、ChromeFrameはその頭痛の種から私を解放しました。


すべての存在しない属性または単に既知の属性名?
js1568 2011

回答:


114

数年前に質問して以来、物事は順調に進んでいます。

プロキシは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のプロキシに関するドキュメントをご覧ください。


Internet Explorer(Edgeより前)のサポートを計画している場合は、運が悪いです。caniuse.com / #search = proxy また、polyfillgithub.com / tvcutsem / harmony
reflectは

21
おめでとうございます、あなたはフェニックスを獲得しました(ゴールドバッジ:少なくとも1年後にあなた自身の質問の1つに答え、最も人気のある答えの投票数を少なくとも2倍にした答えで)
Ziggy 2017年

Object.withDefault =(defaultValue、o = {})=> new Proxy(o、{get:(o、k)=>(k in o)?o [k]:defaultValue}); o = Object.withDefault(42); = 10 OX // => 10 o.xx // => 42 OX // => 42牛
ヴラドV

したがって、プロキシを使用するObject.getEntriesと、プロキシで呼び出すことができないことも意味します:(
Meredith

1
あなたが意味する場合はObject.entries、それらがアクセスされたとき、あなたはセットのプロパティにハンドラを変更することができます。に変更return target.hasOwnProperty(name) ? target[name] : 42;if (!target.hasOwnProperty(name)) target[name] = 42; return target[name];ます。
dosentmatter

28

Javascriptでこれを設定する方法はありません-undefined存在しないプロパティを返すことは、コアJavascript仕様の一部です。この同様の質問の説明を参照してください。そこで提案したように、1つのアプローチ(実際にはお勧めできませんが)は、グローバル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"

しかし、これは他の人が読むのが難しい非標準のコードの束につながり、未定義の値を期待または必要とする領域に意図しない結果をもたらす可能性があります。あなたが行くようにちょうどチェックする方が良いです:

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

10
警告:var someVar = o.someVar || "my default";o.someVarが設定されているが、falseと評価されると予期しない結果が生じる可能性があります(例:null、0、 "")。someVar = o.someVar === undefined ? o.someVar : "my default";の方がいい。||デフォルトでもfalse. (e.g. o.someVar ||と評価される場合、私は通常、単独で使用します。
0`

5
これは良い点です。これは、false-y値が有効な入力である場所では機能しないため、このパターンを使用する場合はそれを考慮する必要があります。しかし、多くの場合、明示的に設定されたプロパティを、nullまたはfalse未設定のプロパティと同じように扱うことは理にかなっています。この場合、これは二重の義務を果たします。ただし、警告は公正です。
nrabinowitz 2012年

5
@Shanimalあなたの例は間違った方法です、それはsomeVar = o.someVar === undefined ? "my default" : o.someVar;マイナーな問題にすぎないはずですが、私が最初にあなたのコードを試したとき、それは私を少し投げました;-)
Metalskin 2013

はい@Metalskin未定義の値は気にしませんか?笑。申し訳ありませんが、間違いがあなたにあまり時間をかけなかったことを願っています:)
Shanimal 2013

28

破壊を使用する(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

11

これは確かに、プロトタイプベースのオブジェクトの典型的な使用法のように聞こえます。

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

console.log(emptyObj)を呼び出すと、{}が返されます。not {attribute1: 'defaultValue1'}
throrin19 2013年

2
はい。attribute1: defaultValue1はプロトタイプ上にあり、console.logは、プロトタイプではなく、最上位オブジェクトに設定されたアイテムのみを列挙するためです。しかし、私のconsole.log(emptyObj.attribute1)示すように、価値はそこにあります。
jfriend00 2013年

それは正しいですが、それはJSON.stringify(emptyobj)。と同じ問題です。この問題に対応してすべての属性を返すメソッドを作成することを余儀なくされました
throrin19 2013年

11

私のコードは:

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

1
このソリューションは、PHPで行うものと似ているため、最も気に入っています。 function foo( array $kwargs = array() ) { // Fill in defaults for optional keyworded arguments. $kwargs += array( 'show_user' => true, 'show_links' => false, ); ...
マイクフィンチ

10

私がこれを達成する方法は、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" }

5
あなたもの値が上書きされている。この行うoverwriteProperties正しい方法は次のとおりです。const newObj = Object.assign({}, defaultProperties, overwriteProperties)
サンフランシスコPuga

6

最も簡単なアプローチはを使用することだと思います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"

ドキュメント(ポリフィル付き):https://developer.mozilla.org/it/docs/Web/JavaScript/Reference/Global_Objects/Object/assign


5

またはあなたはこれを試すことができます

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

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

15
dict ['anotherkey']が0の場合、悪い考えです。–
Ray Toal

:たぶん、あなたはこの検討すべきであるcodereadability.com/...
ebragaparah

@RayToalでは、それをString()修正しませんか?のように:val = dict[String('anotherkey')] || 'anotherval';
GodstimeOsarobo19年

いいえ、申し訳ありませんが、そうではありません。同じ問題。まず実行します。それを試してみてくださいd = {x: 1, y: 0}そしてd['y'] || 100その後である、あなたのアイデアを試してみていない、それは誤って100を与えるd[String('y')] || 100-それはまだそれが0に与える必要があるときに不適切な100を与える
レイTOAL

4

すべてのソリューションの中で最も単純:

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

さて、

dict['last'] || 'Excluded'

デフォルト値である「Excluded」を返します。


3
あなたがわずかに異なる口述を持っている場合、これは失敗します:dict = {'first': 0, 'second': 1, 'third': 2}
VladV18年6

1
これは、存在しない可能性のある値を連鎖させるための優れた方法でもあります。たとえばa.b.c.d。、D、またはcが未定義の場合は、エラーを打つ、あなただけ行うことができます(((a || {}).b || {}).c || {}).d) || "default"
hobberwickey

3

これは私にはそうするための最も簡単で読みやすい方法のようです:

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

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

Object.assign()リファレンス


アンダースコアライブラリにはそのための_.defaults(object、* defaults)メソッドがあると答えるつもりでしたが、ライブラリがなくても答えは同じになります!
DaniCE

2

昨日、Object.__noSuchMethod__プロパティについて言及している記事を見ました。JavascriptTips試してみる機会がなかったので、ブラウザのサポートについてはわかりませんが、何らかの方法で使用できますか?


そのページも見ました。同じHNの記事を読んだに違いありません。ただし、メソッドのみ。これはdefineGetterで実行できますが、残念ながらECMA5にはありません。彼らは私の見解ではもっと悪い別のゲッター/セッターアプローチを採用していません(事前にプロパティの定義が必要です)。
sandstrom 2011

これは将来の答えになるかもしれません:)ブラウザがすぐにそこに到達することを期待しましょう:)♬
jave.web 2015年

1
将来の答えはプロキシ
James Long

@JamesLongはい、あなたは正しいです!未来が到来したことがわかりました:)私が質問をした3年後、これは現在FF(および他のブラウザ)で機能します。以下に回答を追加しました。
sandstrom 2015

2

三項演算子についてまだ誰も言及していないことに驚いています。

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であっても、正しい値を取得します。


1
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

つまり...プロキシを使用すると、すべての優れたObjectメソッドを失うことになります:(
Meredith

0

これは実際にはで行うことができますObject.create。「未定義」のプロパティでは機能しません。しかし、デフォルト値が与えられているものについては。

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

次に、プロパティオブジェクトを作成するときに、 Object.create

properties = Object.create(defaults);

これで、最初のオブジェクトが空である2つのオブジェクトが作成されますが、プロトタイプはそのdefaultsオブジェクトを指しています。テストする:

console.log('Unchanged', properties);
properties.a = 'updated';
console.log('Updated', properties);
console.log('Defaults', Object.getPrototypeOf(properties));

0

1つのアプローチは、デフォルトオブジェクトを取得し、それをターゲットオブジェクトとマージすることです。ターゲットオブジェクトは、デフォルトオブジェクトの値を上書きします。

jQueryにはこれを行う.extend()メソッドがあります。ただし、次のようなバニラJS実装があるため、jQueryは必要ありません。

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


-1

ヘッダーが問題の説明と一致したため、解決策を探してここに来ましたが、探していたものではありませんでしたが、問題の解決策が得られました(日付などの動的な属性のデフォルト値が必要でした)。

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

上記のコードは、私が最終的に解決したソリューションでした。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.