1

I am trying to have a object that takes in fields like this:

var User = function(params) {
    if(params){
        this.id = params.id;
        this.name = params.name;
        ..
    }
}
  • if a property of a field in the model, it sets them
  • if it does not match the model it does not get included in the model
  • if the property is not there it does not set it

So if you do this:

var data = {
    id: 123,
    foo: 'bar'
};

var user = new User(data);

JSON.stringify(user); // { id: 123 }

What's the easiest way to do this? I can only think to do a conditional for each property.

3
  • What's wrong with your attempt? Seems fine to me. Commented Jun 1, 2015 at 19:03
  • use an extend() function Commented Jun 1, 2015 at 19:11
  • @falsarella the issue was the undefined property. Answer is below to return a parsed stringified version of itself. Commented Jun 1, 2015 at 19:19

4 Answers 4

2
function (params) {
    var properties = ['id', 'name', ..];
    for (var i = 0, length = properties.length; i < length; i++) {
        var property = properties[i];
        if (params[property]) {
            this[property] = params[property];
        }
    }
}
Sign up to request clarification or add additional context in comments.

Comments

1

Sincerely, you don't need conditionals. Your attempt is perfectly fine. Just execute the following code:

function User(params, hiddenNew) {
    if (params) {
        //if a property of a field in the model, it sets them
        //if it does not match the model it does not get included in the model
        this.id = params.id;
        this.name = params.name;
    }
    //you can have additional functions here, or add it to its prototype
    this.logMe = function() {
        console.log(this);
    };
    //if the property is not there it does not set it
    for (key in this) {
        if (this[key] == undefined) {
            delete this[key];
        }
    }
    return this;
}
var data = {
    id: 123,
    foo: 'bar'
};

var user = new User(data);
user.logMe(); // testing function

And the user object will be exactly what you want:

User {id: 123}

6 Comments

Why the downvote? Can the downvoter explain the reason?
+1 from me. With the behavior of undefined being as it is, this passes the few conditions the OP gave. There's still a difference in the object which may or may not play any role, but largely it's irrelevant whether the property is actually undefined or just undefined.
This is actually the best way to do it. One tweak is to do return JSON.parse(JSON.stringify(this)); in the model. This strips out the undefined automatically. Thanks!
@deceze I don't want the undefined because I am using it to automatically build a query, and so the query would fail.
Turns out this is not as good as I thought, it strips the methods out so I can no longer use User to run its methods after I instantiate it. Going to have to figure out a new pattern. ended up just adding a new method User.prototype.model = function(data){ return JSON.parse(JSON.stringify(new User(data))); }; seems silly, but works.
|
1

There's no other way than conditionally-adding them, but you can simplify it.

Since JavaScript is a dynamically-typed language and it also enforces duck-typing, don't expect something like classes that could auto-magically prevent adding unexpected properties.

See the following code snippet for a possible simplification.

function BaseObject() {}

BaseObject.prototype = {
  defineRequiredProperties: function(requiredProperties, propertyMap) {
    if (!(requiredProperties instanceof Array)) {
      throw Error("'requiredProperties` argument must be an array!");
    }

    if (typeof propertyMap == "object") {
      var that = this;

      Object.keys(propertyMap).forEach(function(propertyName) {
        // Better do this because you'll be able to check if a 
        // property exists even if it's defined in the prototype chain
        if (requiredProperties.indexOf(propertyName) > -1) {
          that[propertyName] = propertyMap[propertyName];
        }
      });
    }
  }
};

// As OP requested, this prevents this custom function from being iterated.
// It's still callable but not enumerable
Object.defineProperty(BaseObject.prototype, "defineRequiredProperties", {
    enumerable: false
});

function User(params) {
  this.defineRequiredProperties(["id", "name"], params);
}

// This is effecitvely derive BaseObject (actually, chaining the
// BaseObject prototype) in order to share defineRequiredProperties
// across all your custom prototypes and be DRY (Don't Repeat Yourself)
User.prototype = Object.create(BaseObject.prototype);

var user = new User({
  id: 11,
  name: "Matías",
  lastName: "Fidemraizer"
});

document.getElementById("result").textContent = JSON.stringify(user);
<div id="result"></div>

20 Comments

This doesn't pass the requirement "if the property is not there it does not set it" -- it sets it to null (e.g., remove name: "Matías" and run it)
What @Tom said. if you have the object look like this: this.id = null; this.name = null; this.anotherField = null; you get {"id":11,"name":"Matías","anotherField":null}
@PixMach Now it passes the requirement ;) I've updated the code
@PixMach Sorry? An unexisting property is undefined, obviously
@PixMach Read my last comment. I believe you're wrong, or show me a code snippet where you can prove your statement (for example in jsFiddle.net).
|
-3

How about you extend the user properties with passed properties? That way anything new will be added to the user. http://api.jquery.com/jquery.extend/

1 Comment

I'm not using jquery, but wouldn't that make the result: { id:123, foo: 'bar', name: null } That's the opposite of what I want.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.