What's the difference between drupalSettings and settings parameter in behaviors? When having the need to pass settings or parameters from PHP to JavaScript, i always used to do so according to a blog post from Acquia - create a dependency to drupalSettings, attach the settings on the PHP side and use the drupalSettings variable on the JS side.

my_module.libraries.yml:

my_lib:
  version: 1.x
  js:
    js/my_javascript.js: {}
  dependencies:
    - core/jquery
    - core/drupalSettings


my_module.module:

function my_module_page_attachments(&amp;$attachments) {
    $attachments['#attached']['drupalSettings']['my_module']['my_property'] = 'abc';
}


Finally my_javascript.js:

(function ($,Drupal,drupalSettings) {
  Drupal.behaviors.test = {
    attach: function(context,settings) {
      console.log(drupalSettings.my_module.my_property); // would output 'abc';
    }
  }
})(jQuery,Drupal,drupalSettings);


However, I came to a sudden realization that the settings variable of my attach function already contains exactly the same variable:

(function ($,Drupal) {
  Drupal.behaviors.test = {
    attach: function(context,settings) {
      console.log(settings.my_module.my_property); // would also output 'abc';
    }
  }
})(jQuery,Drupal);


So why is there even a separate way to load drupalSettings and it's proposed in every guide I found, when in fact we already have a variable containing our settings, so we don't need to mention the global drupalSettings variable?

Thanks for your clarification!

Update 1

I found out in my test behavior that the variable settings is a reference to drupalSettings, so if you modify one of the two, the other also has the direct changes, and they are therefore equal.

Drupal.behaviors.anotherTest = {
  attach: function(context,settings) {
    console.log(settings == drupalSettings); // outputs true
    drupalSettings.testproperty = 'abc';
    console.log(settings == drupalSettings); // still true
    console.log(settings.testproperty); //  outputs 'abc'
    // works also the other way around
    settings.testproperty = 'def';
    console.log(drupalSettings.testproperty); // outputs 'def' now
  }
}


This applies to every call of my behavior. On my rather complex project, the behavior gets called 12 times, and while the context variable changes on every call, settings is always equal to drupalSettings.
The thing to remember is that behaviors can fire both on page load and on AJAX requests.

Upon page load, the global and the parameter passed to the behavior should be identical.

During the course of page interaction, and depending on the AJAX commands, the settings parameter may be different when it fires.

When writing behaviors in Javascript, always use both the jQuery context to scope selectors, and the settings variable that get passed in to be safe and future proof your code even if you aren't using AJAX.