2016-06-15 22 views
8

Tôi đang cố gắng chỉ định sâu giá trị trong một đối tượng. Ví dụ:Phân bổ sâu đối tượng JavaScript theo nghĩa đen

const errors = {} 
if(errorOnSpecificField) { 
    // TypeError: Cannot read property 'subSubCategory' of undefined(…) 
    errors.subCategory.subSubCategory.fieldWithError = 'Error Message' 
} 

Ngay bây giờ, mà không lodash, tôi có thể làm:

const errors = {} 
if(errorOnSpecificField) { 
    errors.subCategory = errors.SubCategory || {} 
    errors.subCategory.subSubCategory = errors.SubCategory.subSubCategory || {} 
    errors.subCategory.subSubCategory.fieldWithError = 'Error Message' 
} 

Với lodash, tôi có thể làm điều này:

const errors = {} 
if(errorOnSpecificField) { 
    _.set(errors, 'subCategory.subSubCategory.fieldWithError', 'Error Message'); 
} 

Tôi cố gắng để tránh sử dụng một phần ba thư viện đảng. Có một giải pháp thanh lịch hơn, đặc biệt là bây giờ mà es2015 đã phá hủy đối tượng. Thao tác nghịch đảo rất dễ dàng:

let {subCategory : {subSubCategory: {fieldWithError}}} = errors 

Giải pháp thanh lịch cho phân bổ đối tượng sâu là gì? Cảm ơn!

+2

Object.assign()? - nó ghi đè lên tất cả các thuộc tính mặc dù –

+0

Như bạn đề cập, vì nó ghi đè các thuộc tính khác đã được thiết lập, điều này sẽ không hoạt động cho trường hợp của tôi – aherriot

+0

bạn có thể tìm kiếm một số triển khai 'mở rộng' –

Trả lời

0

Đây là một cách khá dễ đọc một cách an toàn gán cho đối tượng sâu:

(((errors||{}).subCategory||{}).subSubCategory||{}).fieldWithError = 'Error Message' 

Điều đó không tạoerrors.subCategory.subSubCategory nếu nó chưa tồn tại, mặc dù.

+2

Điều này thực sự không hoạt động đối với bài tập. Để truy cập, có, nhưng không phải để tạo thuộc tính. – Bergi

+0

Hmm ... Nó sẽ không tạo ra 'errors.subCategory.subSubCategory', nhưng nó sẽ gán cho nó một cách an toàn nếu nó đã tồn tại. –

0

Câu trả lời ngắn, không có không có cách nào sạch để làm điều này mà không cần viết một phương pháp cho nó (tbh bạn chỉ có thể sử dụng phương pháp từ lodash mà không cần nhập khẩu toàn bộ thư viện)

... tuy nhiên ...

CẢNH BÁO Điều này chỉ dành cho vui. Đừng thử điều này trong sản xuất (req es6).

Object.prototype.chainSet = function() { 
    let handler = { 
    get (target, name) { 
     if (!(name in target)) { 
     target[name] = new Proxy({}, handler) 
     } 
     return target[name] 
    } 
    } 

    return new Proxy(this, handler) 
} 

sử dụng:

let a = {} 
a.chainSet().foo.bar.baz = 1 
a.foo.bar.baz // => 1 
0

Object.assign() sẽ chỉ làm việc tốt cho những gì bạn đang yêu cầu.

let errors = { otherField: "value" }; 
let newobj = {subCategory : {subSubCategory: {fieldWithError: "Error goes here"}}}; 
Object.assign(errors, newobj); 

sản lượng này:

{ 
    otherField:'value', 
    subCategory: { 
    subSubCategory: { 
     fieldWithError:'Error goes here' 
    } 
    } 
} 
+1

nếu 'errors = {subCategory: {x:" y "}}' và bạn gán 'newobj', thì thuộc tính' x' bị "remove" (toàn bộ đối tượng 'subCategory' được hoán đổi). OP đang tìm cách tránh điều đó. –

0

Bạn có thể thử một cái gì đó như dưới đây:

function ErrorRegistry(obj) 
{ 
    this.errors = obj || {}; 
    this.addError = function(k, msg) 
    { 
     var keys = k.split('.'); 
     var o = this.errors; 
     for(var i = 0, l = keys.length, last = l-1; i<l; i++) 
     { 
      if(typeof o[keys[i]] === 'undefined') 
       o[keys[i]] = {}; 
      if(i == last) 
       o[keys[i]] = msg; 
      else 
       o = o[keys[i]]; 
     } 
    }; 
} 
var errors = {'subCategory1':{'fieldWithError1':'Error1'}}; 
var errorRegistry = new ErrorRegistry(errors); 
errorRegistry.addError('subCategory1.fieldWithError2', "Error2"); 
errorRegistry.addError('subCategory1.subSubCategory1.fieldWithError3', "Error3"); 
errorRegistry.addError('subCategory1.subSubCategory2.fieldWithError4', "Error4"); 
errors = errorRegistry.errors; 
console.log(errors); 
Các vấn đề liên quan