Edit in JSFiddle

(function()
{
  
  //get a reference to the password field and define a data attribute
  //that we can switch to indicate whether the password should be heard
  var password = document.getElementById('password');
  password.setAttribute('data-hearing-type', 'password');

  //create an assertive live region to speak the password value 
  //and hide it with off-left positioning so it's not otherwise visible
  var speaker = document.createElement('span');
  speaker.setAttribute('aria-live', 'assertive');
  speaker.setAttribute('style', 'position:absolute;left:-1000em;');
  
  //append the live region after the password field 
  //n.b. this will still be part of the screenreaders normal reading order
  //however form navigation is usually limited to tabbing between fields
  //and since it's not in the tab order it won't be reached that way
  password.parentNode.appendChild(speaker);
  
  
  //bind an input event to the password field
  password.addEventListener('input', function()
  {
    //if the password field should be heard, copy its value to the speaker
    if(password.getAttribute('data-hearing-type') == 'text')
    {
      speaker.innerHTML = password.value;
    }
  
  }, false);
  

  //create a trigger button to switch the hear functionality on and off
  //defining two data attributes to store the language for each state 
  //and then setting the initial text to match the default off state
  var hear = document.createElement('button');
  hear.type = 'button';
  hear.setAttribute('data-hearing-password', 'Hear Password');
  hear.setAttribute('data-hearing-text', 'Mute Password');
  hear.appendChild(document.createTextNode(hear.getAttribute('data-hearing-password')));
  
  //append the button after the password field and speaker
  password.parentNode.appendChild(hear);
  
  //bind a click event to the button
  hear.addEventListener('click', function(e)
  {
    //invert the current hearing state between on ("text") and off ("password")
    var type = password.getAttribute('data-hearing-type') == 'password' ? 'text' : 'password';
    
    //apply the new state to the password field and update the button language
    password.setAttribute('data-hearing-type', type);
    hear.firstChild.nodeValue = hear.getAttribute('data-hearing-' + type);
    
    //if the type is "text" copy the password to the speaker, else clear it
    speaker.innerHTML = type == 'text' ? password.value : '';
    
    //prevent any default action (e.g. some browsers might submit the form)
    e.preventDefault();
  
  }, false);
  
})();
<form action="#">
  <fieldset>
    <legend>Login information</legend>
    <p>
      <label for="username">Username:</label>
      <input name="username" id="username" type="text" value="" />
    </p>
    <p>
      <label for="password">Password:</label>
      <input name="password" id="password" type="password" value="" />
    </p>
  </fieldset>
</form>