@KenBuja is correct. You should use the Expects function for this case if using a for loop.
The rendering engine for Online (JS API) is optimized for performance. So it only requests the data that's required by the layer's style by default. If you specify a field outside of an Arcade expression, the API knows to request data from that field for rendering. In the case of Arcade, the expression is evaluated for the fields required to make it work. When $feature.FIELDNAME is used, it's easy for the engine to figure out the required fields. That's why the alternative expression works. However, you can use Expects to directly tell the rendering engine which fields it should expect to request from the service. This can be a list of fields as Ken points out, or you can also define template strings like the following:
Expects("*"); // requests all fields. Don't do this if you have a ton of attributes.
Expects("Year_*") // requests all fields that begin with "Year_". (e.g. "Year_2000", "Year_2010") would be requested, but "Y2004" wouldn't).
On a side note, you could take advantage of the number function to condense the initial expression like this:
Expects($feature,'*_20*');
var fieldList = ['Dorian_2019','Sally_2020','Ian_2022','Nicole_2022','Idalia_2023'];
var total = 0;
for (var f in fieldList) {
// adds 1 if "YES"
// adds 0 if not "YES"
total += Number($feature[fieldList[f]] == 'YES');
}
return total;
Or use the reduce function to avoid a for loop altogether. You still need Expects for this to work...
Expects($feature,'*_20*');
var fieldList = ['Dorian_2019','Sally_2020','Ian_2022','Nicole_2022','Idalia_2023'];
function add (total, fieldName){ total + Number($feature[fieldName] == 'YES') }
Reduce(fieldList, add, 0);