jQuery split these in 1.6 and the change is still working its way through everyone’s habits, because attr('checked') kept doing roughly the right thing for years. An attribute is what is written in the markup and it does not change; a property is the live state of the DOM node, which is what the user has actually done to it.
<input type="checkbox" id="terms" checked>
$('#terms').attr('checked'); // "checked" — the markup, and it never moves
$('#terms').prop('checked'); // true, then false the moment the user clicks
$('#terms').attr('checked', false); // does not uncheck a box the user touched
$('#terms').prop('checked', false); // does
$('#logo').attr('src'); // "img/logo.png" — the literal attribute
$('#logo').prop('src'); // "http://example.com/img/logo.png" — resolved
The dividing line is whether the thing has a state or is only text. checked, selected, disabled, readOnly and indeterminate are states, so they are properties; href, colspan, title and every data- attribute are markup, so they are attributes. The reason old code appears to work is removeAttr('disabled'), which happens to reset the property as well — right up until something has set the property directly, at which point removing the attribute changes nothing and the button stays dead. The src and href pair is the other half of this and it catches people going the other way: attr() hands back the relative string that is in the document, prop() hands back the absolute URL the browser resolved, and comparing the two against each other never matches.