Dijit widgets provide the ability to write custom setters and getters, whose logic is executed when calling the set and get methods. dijit/_WidgetBase also provides a _set method, which is very important when writing widgets, but can cause a bit of confusion due to its name.

set

The set method provides a public API for setting one or more properties on a widget instance.

// Set a single property "foo" to the value "bar"
myWidget.set("foo", "bar");

// Set multiple property values at once
myWidget.set({
    foo: "bar",
    baz: "qux"
});

Using the set method when updating widget properties is important, as it will in turn call any custom setter method defined for that property. Custom setter methods are defined following the pattern _setFooAttr, where “foo” is the name of the property:

declare(_WidgetBase, {
    foo: "",
    _setFooAttr: function (value) {
        // Perform custom logic, and update the foo property
    }
});

Note that in addition to performing custom logic, the custom setter is typically also responsible for updating the corresponding property’s value — Dijit doesn’t do this automatically when a custom setter method is defined. This allows the custom setter to potentially transform the incoming value before updating the property.

Your first thought might be to simply update the value directly (e.g. this.foo = value;), but there is one major flaw to that approach. dijit/_WidgetBase inherits from dojo/Stateful, which also provides the watch method. However, it is incapable of notifying watchers of direct property updates. In other words, if we take this approach, watchers registered for this property will never fire!

_set

In a pure dojo/Stateful instance, set is responsible for notifying watchers, but in the case of Dijit, as we’ve already seen, it is already responsible for delegating to our custom setter in the first place, so there needs to be a distinct API for notifying watchers. That’s where _set comes in.

As its underscore-prefixed name suggests, _set is an internal method intended to be used from within _WidgetBase extensions. Its purpose is quite simple – it updates the value of the indicated instance property, and also fires any watchers for that property.

Thus, the correct way of properly updating a property within a custom setter is to call _set:

_setFooAttr: function (value) {
    // Perform custom logic...

    // ...and update the instance property
    this._set("foo", value);
}

Putting it all together

Here is an example featuring a widget with a custom setter for the foo property. We instantiate the widget and add a watcher so we can see how _set interacts with it.

require([
    "dojo/_base/declare",
    "dijit/_WidgetBase",
    "dojo/domReady!"
], function (declare, _WidgetBase) {
    var MyWidget = declare(_WidgetBase, {
        foo: "",
        _setFooAttr: function (value) {
            console.log("Setting value of foo to " + value);
            this._set("foo", value);
        }
    });

    var widget = new MyWidget().placeAt(document.body);
    widget.startup();

    widget.watch("foo", function (property, oldValue, value) {
        console.log("Watcher for 'foo' fired, changing property value from " +
            oldValue + " to " + value);
    });
    
    widget.set("foo", "bar");
});

Upon running this example, we will see the following console output:

"Setting value of foo to bar"
"Watcher for 'foo' fired, changing property value from  to bar"

If we had only performed this.foo = value in the setter instead, the second line would not appear, since the watcher would never fire.

In summary, _set is a crucial part of writing custom setters for widgets, while set is the public API responsible for firing these custom setters in the first place.