Achshar
Achshar

Reputation: 5243

Value assignment and return variable in same line

I have following code

var s = storage('foo');
s.bar = 100;
storage('foo', s);

storage returns an object from some storage media. I then change the value of one property of the object and send it to storage again. My question is is there any way to make it a one liner? Something like

storage('foo', storage('foo').bar = 100);

But the above code only saves 100 instead of entire foo object.

Here is the storage function, it stores on localstorage but makes it object storage instead of string storage:

function storage(item, value) {
    if(value!=null) {
        var result = (storage()) ? storage() : {};
        if(item) result[item] = value;
        return localStorage.setItem('storage', JSON.stringify(result))
    } else return (item) ? storage()[item] : JSON.parse(localStorage.getItem('storage'));
}

Edit: So I ended up with following one line change in storage function. But this does not account for multidimensional usage. So I will welcome any suggestions.

function storage(item, value, property) {
    ...
        if(item) (property) ? result[item][property] = value : result[item] = value;
    ...
}

Upvotes: 1

Views: 2488

Answers (3)

Felix Kling
Felix Kling

Reputation: 816790

The reasonably thing to do, if you cannot change the storage function, is to create another function:

function set_storage(obj, prop, val) {
    var s = storage(obj);
    obj[prop] = val;
    storage(obj, s);
}

// usage
set_storage('foo', 'bar', 100);

If you can change storage though, this would be an even better way. jQuery.data works similarly.

There are ways to do this in (almost) one line, with the help of the comma operator [MDN], but it ain't pretty:

var s = storage('foo');
storage('foo', (s.bar = 100, s));

Since you said storage is your function, overloading it seems to be a good way. It would go like this:

function storage(key, prop, val) {
    var storage = JSON.parse(localStorage.getItem('storage'));

    if(arguments.length === 0) {
        return storage;
    }
    else if (arguments.length === 1) {
        // only one argument passed, return the value with key `key`
        return storage[key];
    }
    else if (arguments.length === 2) {
        // set `key` to `prop` (`prop` contains the actual value)
        storage[key] = prop;
    }
    else {
        // set property `prop` of object in `key` to value `val`
        storage[key][prop] = val;
    }
    localStorage.setItem('storage', JSON.stringify(storage));
}

// Usage

// get `foo`:
var foo = storage('foo');

// set `foo`:
storage('foo', {bar: 42});

// set foo.bar
storage('foo', 'bar', 100);

I hope it gives you some idea.

Upvotes: 2

Sjoerd
Sjoerd

Reputation: 75629

You can make a function which accepts a function that changes the object:

function changeObject(key, func) {
    var obj = storage(key);
    func(obj);
    storage(key, obj);
}

changeObject('foo', function (s) { s.bar = 100; });

Upvotes: 0

Matt
Matt

Reputation: 75327

As storage returns an object, theres a (very) good chance you can do*;

storage('foo').bar = 100;

console.log(storage('foo').bar); // should give 100.

... directly, as objects are "pass by reference"-esque.


* A situation where this would not be the case would be where storage returns a copy of the object stored, rather than the object itself; therefore any updates you make to the returned object will not have an affect on the object in storage.

Upvotes: 0

Related Questions