2017-08-28 9 views
0

私のサイトへの訪問者の数をブラウザ/バージョン別に記録したjsonオブジェクトがあるとします。JavaScript:存在しない可能性のあるオブジェクトにネストされたプロパティを追加する

let data = { 
    browsers: { 
     chrome: { 
      43 : 13, 
      44 : 11 
     }, 
     firefox: { 
      27: 9 
     } 
    } 
} 

特定のブラウザを増分するには、いくつかのキーが存在するかどうかを確認し、そうでない場合は作成する必要があります。

let uap = UAParser(request.headers['user-agent']); 

if (typeof uap.browser !== 'undefined') { 

    if (typeof data.browsers === 'undefined') 
     data.browsers = {} 

    if (typeof data.browsers[uap.browser.name] === 'undefined') 
     data.browsers[uap.browser.name] = {} 

    if (typeof data.browsers[uap.browser.name][uap.browser.version] === 'undefined') 
     data.browsers[uap.browser.name][uap.browser.version] = 0 

    data.browsers[uap.browser.name][uap.browser.version] += 1; 
} 

私のデータ構造が深くなればなるほど、よりクレイジーなものが得られます。

javascriptでこれを行うには、もっときちんとした方法が必要なように感じます。 はいつもです。誰でもここで私を啓発することはできますか?

+1

- lodash。それはあなたが必要とするものを行う[get](https://lodash.com/docs/4.17.4#set)メソッドを持っています: '_.set(object、 'a [0] .b.c'、4); ' – alexmac

+0

typeof ...の代わりにObject.prototype.hasOwnProperty()を使用してください。 –

+0

@DenisGiffelerは、もっと長いことをしているようです。私は自分のコードを短縮しようとしています – roryok

答えて

2

この短いコードは、トリックを行う必要があるのと同じ:

if (uap.browser) { // typeof is pretty much redundant for object properties. 
    const name = uap.browsers.name; // Variables for readability. 
    const version = uap.browser.version; 

    // Default value if the property does not exist. 
    const browsers = data.browsers = data.browsers || {}; 
    const browser = browsers[name] = browsers[name] || {}; 
    browser[version] = browser[version] || 0; 

    // Finally, increment the value. 
    browser[version]++; 
} 

=== {})を使用していたはずの===を使用していたことに注意してください。

const browsers = data.browsers = data.browsers || {}; 

最後の部分:それが存在する場合は、それ自体であることをdata.browsersを設定data.browsers = data.browsers || {}

はのは、この行を説明しましょう。それがまだない場合は、新しい空のオブジェクトに設定されます。
それから、その全体の値はアクセスを容易にするためbrowsersに割り当てられます。

ここで、短いコードは最優先事項ではありませんが、このような場合はコードをもっと読みやすくすることができます。

+0

oops。はい、私はそれが '='であるべき '==='を見ています - それに感謝します – roryok

+0

@roryok:np。私は「短いコード」について少しの免責事項を追加しました。最後に、読みやすさを求めています。これは必ずしも「短い」という意味ではないかもしれません( 'name' /' version'が良い例です)。この回答を受け入れてくれてありがとう! – Cerbrus

0

あなたはif文を放棄し、このようにそれを行うことができます。

uap.browser = uap.browser || {} 

、本質的にそれない場合のみ、はるかに短い

0

ここには非常にきれいで包括的なソリューションがありますProxy()私はそれをきれいにする必要がないか、ブラウザに依存しないようにする必要がある場合、標準のECMAscript 5である2番目のソリューションを用意しています。

var handler = { 
    get: function (target, property) { 
     if (property !== "toJSON" && target[property] === undefined) { 
      target[property] = new Proxy ({}, handler); 
     } 
     return target[property]; 
    } 
} 
var jsonProxy = new Proxy ({}, handler); 

jsonProxy.non.existing.property = 5; 
jsonProxy.another.property.that.doesnt.exist = 2; 
jsonProxy["you"]["can"]["also"]["use"]["strings"] = 20; 

console.log (JSON.stringify (jsonProxy)); 

あなたはクラスではなく、より詳細な構文で同じことを行うことができます。すでにこのような操作のための優れたライブラリがあり

var DynamicJSON = function() {}; 
DynamicJSON.prototype.get = function (property) { 
    if (this[property] === undefined) { 
     this[property] = new DynamicJSON(); 
    } 
    return this[property]; 
}; 
DynamicJSON.prototype.set = function (property, value) { 
    this[property] = value; 
}; 

var jsonClass = new DynamicJSON(); 
jsonClass.get("non").get("existing").set("property", 5); 
jsonClass.get("you").get("have").get("to").get("use").set("strings", 20); 

console.log (JSON.stringify (jsonClass)); 
関連する問題