The 2nd Parameter of .style()/.attr()
When using something like:
.attr("fill", someParameter);
D3 checks to see if someParameter is a function or a constant.
If someParameter is a constant, "all elements are given the same attribute value", afterall we're using a constant. (see also, D3 documentation). 
If someParameter is a function, D3 uses function.apply() (see also, MDN's function.apply() documentation) to call that function for each item in the selection, providing it with 3 parameters: 
- the current datum (by convention d),
- the index of the current item (by convention i),
- and the group of nodes in the selection (inconsistent convention, I'll use nodeshere).
The use of apply also allows specification of this, which is the current element (which is also: nodes[i]).
The use of function.apply() defines d, i, and nodes only within the function provided. 
This makes sense, if you provide a constant, there is nothing to apply, er, apply to and no need to.
What happens when you supply d['name'] as the 2nd argument for .style()/.attr()
If using:
.attr("fill", d.color)`
d in the above has no relation to the datum. If you haven't declared d and given it the property color yourself, it'll be undefined here. D3 doesn't call a function here with apply to define d - you aren't providing a function to do so with.
Only if d.color evaluates to function(d) { return d.color; } would you be able to do what you are asking about. This would be a very unusual form with D3.
If d is undefined you'll likely throw an error when accessing d.color as you've seen. If d is defined, but d.color isn't a function, it'll be treated as a constant and every element will gain a property with the same value. 
Consequently, this is why we see the format:
.attr("fill", function(d,i,nodes) { return ... });
Stop Here
It is possible in theory, but not advisable, to accomplish what you think should be possible.
I'm only sharing because 
- I've had this lying around for a while 
- It shows how much of a workaround is required to achieve the pattern you are asking about (without pre-defining your functions as properties of some object named d).
Again it's not advisable to use - but you can, technically, dynamically create an accessor function for a given property, or nested property, of the datum with a proxy. 
With this you could use the form:
.attr("fill", d.color) 
When accessing any of the proxy (d) properties (here color) it would need to return the appropriate accessor function (function(d) { return d.color;}) which would then be passed to .attr() and have the appropriate datum bound to it. You can only use the property, you wouldn't be able to use d.x + 2.
// create a proxy `d` to return accessor functions, 
var d = new Proxy({},{ get: f })
var data = [
  {style:{fill:"steelblue",stroke:{color:"crimson", width:4}},width: 30, y: 50, x: 10},
  {style:{fill:"yellow",stroke:{color:"orange", width:2}},width: 20, y: 50, x: 50},
  {style:{fill:"crimson",stroke:{color:"steelblue", width:8}},width: 30, y: 50, x: 80}
]
var svg = d3.select("body").append("svg");
svg.selectAll(null)
  .data(data)
  .enter()
  .append("rect")
  .attr("x", d.x)
  .attr("y", d.y)
  .attr("width", d.width)
  .attr("height",d.width)
  .attr("fill",d.style.fill)
  .attr("stroke-width",d.style.stroke.width)
  .attr("stroke", d.style.stroke.color);
  
  
  
// To resolve paths (https://stackoverflow.com/a/45322101/7106086):
function resolve(path, obj) {
    return path.reduce(function(prev, curr) {
        return prev ? prev[curr] : null
    }, obj || self)
}
// Proxy to dynamically access properties of any depth:
function f(obj, prop) {
    if(prop in obj) return obj[prop];
    else { 
       var g = function() {
          var accessor = function(d) {
            return resolve(accessor._path_,d);
          }
          // keep track of path:
          if(obj._path_) accessor._path_ = [...obj._path_,prop];
          else (accessor._path_) = [prop];
          return accessor;
       }
       return obj[prop] = new Proxy(g(), {get:f});     
    }
 }
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>