Simulate the way that PHP receives the form Let's say I have this form:

&lt;form action="/user/store" method="POST" enctype="multipart/form-data"&gt;
    Name: &lt;input type="text" name="name"&gt;&lt;br&gt;
    Male: &lt;input type="radio" name="gender" value="male"&gt;&lt;br&gt;
    Female: &lt;input type="radio" name="gender" value="female"&gt;&lt;br&gt;
    Photo: &lt;input type="file" name="photo"&gt;&lt;br&gt;
    Hobbies: &lt;select name="hobbies[]" multiple&gt;
        &lt;option value="sport"&gt;Sport&lt;/option&gt;
        &lt;option value="movies"&gt;Movies&lt;/option&gt;
        &lt;option value="music"&gt;Music&lt;/option&gt;
        &lt;option value="games"&gt;Games&lt;/option&gt;
    &lt;/select&gt;&lt;br&gt;
    Accept the terms?&lt;input type="checkbox" name="terms"&gt;&lt;br&gt;
    &lt;input type="submit"&gt;
&lt;/form&gt;


If I submit it to a PHP server with my data, this is the result:

array (size=5)
  'name' =&gt; string 'John' (length=4)
  'gender' =&gt; string 'male' (length=4)
  'hobbies' =&gt; 
    array (size=2)
      0 =&gt; string 'sport' (length=5)
      1 =&gt; string 'music' (length=5)
  'terms' =&gt; string 'on' (length=2)
  'photo' =&gt; 
    object(Symfony\Component\HttpFoundation\File\UploadedFile)[9]
      private 'test' =&gt; boolean false
      private 'originalName' =&gt; string 'test.jpg' (length=8)
      private 'mimeType' =&gt; string 'image/jpeg' (length=10)
      private 'size' =&gt; int 130677
      private 'error' =&gt; int 0


I want to have similar results with JavaScript, so I wrote this function:

//Add event listener for the form submit to the document
$(document).on('submit', 'form', function(e){
    //Prevent form submitting
    e.preventDefault();
    var form = $(':input').not(':submit,:button,:image,:radio,:checkbox');
    $.merge(form, $(':checked').not('option'));
    var data = [], input, name;

    form.each(function(i, obj){
        input = {};
        name = obj.name;
        if(name.indexOf('[]') &lt; 0) {
            input['name'] = name;
            if(obj.type==='file'){
                var files = obj.files;
                input['value'] = files[files.length - 1];
            } else {
                input['value'] = obj.value;
            }
        } else {
            name = name.replace('[]', '');
            if(name in data){
                var tmp = input['value'];
                if(obj.type==='file'){
                    input['value'] = $.merge(tmp, obj.files);
                } else if(obj.type === 'select-multiple') {
                    input['value'] = $.merge(tmp, $.map(obj.selectedOptions, function(option, i){
                        return option.value;
                    }));
                } else {
                    input['value'] = $.merge(tmp, obj.value);
                }
            } else {
                data[name] = {};
                if(obj.type === 'file'){
                    input['value'] = obj.files;
                } else if(obj.type === 'select-multiple') {
                    input['value'] = $.map(obj.selectedOptions, function(option, i){
                        return option.value;
                    });
                } else {
                    input['value'] = [];
                    input['value'].push(obj.value);
                }
            }
        }
        data.push(input);
     });
});


And this return (JSON format):

[
    {"name":"firstname","value":"John"},
    {"name":"photo","value":
        {
            "webkitRelativePath":"",
            "lastModifiedDate":"2014-09-08T18:29:36.000Z",
            "name":"test.jpg",
            "type":"image/jpeg","size":130677
        }
    },
    {"name":"hobbies","value":["sport","music"]},
    {"name":"gender","value":"male"},
    {"name":"terms","value":"on"}
]


Is there any better way to do that? By better code, I mean less code. I don't mind if it will become slower.
I’m not sure if you still maintain this code but if so, you could consider using a FormData object. I see it has been documented on MDN since 2015 and the link to the specification points to whatwg.org, which has been archived since 2012. I found a post on SO from 2011 that uses it. That way you wouldn’t have to manually query the DOM for inputs (I.e. var form = $(':input').not(':submit,:button,:image,:radio,:checkbox'); $.merge(form, $(':checked').not('option'));)- you could just iterate over a newly created FormData object. You would still need to alter input names to remove the brackets when multiple values are allowed.

You might be able to remove jQuery as a dependency, unless there are specific plugins used on the page. For more information, check out youmightnotneedjquery.com/.



I see places where bracket notation is used to alter properties of objects, like below: 


input['name'] = name;



and


input['value'] = files[files.length - 1];



However dot notation could be used instead, just as it is used to check the type of the object being iterated over (i.e. if(obj.type==='file'){). It is "faster to write and clearer to read"1

1https://stackoverflow.com/a/4968448/1575353