0

Few days after since I started to make the plugin, I wondered what's the difference between these 2 codes and why second code doesn't work.

The first one looks like this:

<div class="searching">
    <ul>
        <li></li>
    </ul>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

(function($) {
  $.fn.slideInit = function() {
    const myGallery = $(this),
          myList = myGallery.find('li');

    <!-- Log Section -->
    console.log(myList);
    <!----------------->
  };
} (jQuery));
$('.searching').slideInit();

This code works fine what I expected. Variable myGallery can be defined inside of the code block.

And the second one which doesn't work looks like this:

(function($) {
  $.fn.slideInit = function() {
    const defaults = {
      myGallery: $(this),
      myList: myGallery.find('li')
    };

    <!-- Log Section -->
    console.log(defaults.myList);
    <!----------------->
  };
} (jQuery));
$('.searching').slideInit();

What I've done in this code is just added the variables inside of an object which called defaults, but when I run this code, an error pops up:

index.html:59 Uncaught ReferenceError: myGallery is not defined

I think there's something difference between those 2 codes but couldn't find or figured out by myself.

Would you guys teach me why the myGallery that is scoped by the variable default can't be defined?

l3lue
  • 531
  • 4
  • 16
  • 1
    It should be `defaults.myGallery.find('li')`, or just declare the `$(this)` item outside of `defaults` and use it then. – darklightcode Dec 27 '18 at 11:04
  • 1
    Possible duplicate of [Self-references in object literals / initializers](https://stackoverflow.com/questions/4616202/self-references-in-object-literals-initializers) – Jeto Dec 27 '18 at 11:05
  • @darklightcode Even if it's scoped by `defaults` already? – l3lue Dec 27 '18 at 11:05
  • 1
    @calmwave - It isn't. That isn't how scope works in JavaScript, an object initializer ("object literal") doesn't create a new scope. If this isn't a duplicate of the question Jeto points to above, that question and its answers are certainly very close and should help you understand a bit more about this. – T.J. Crowder Dec 27 '18 at 11:07
  • @T.J.Crowder Maybe I should go to search about scope. Thank you for commenting. – l3lue Dec 27 '18 at 11:08
  • 1
    @calmwave - :-) Very briefly: Only functions, blocks, and parameter lists create new scope. (It was only functions in ES5 and earlier. Blocks only create new scope for `let`, `const`, `class`, and `function` declarations in strict mode. Parameter lists create new scope if you use advanced parameter list features, like default values.) – T.J. Crowder Dec 27 '18 at 11:11
  • @T.J.Crowder Big respect for detail commenting. Thank you so much and Happy Holiday season :> – l3lue Dec 27 '18 at 11:20

2 Answers2

2

You have to define your var outside your literal or reference it using this

const defaults = {
      myGallery: "DONALD DUCK",
      myList: function() { console.log(this.myGallery) }
    };
 
 defaults.myList();
Mosè Raguzzini
  • 15,399
  • 1
  • 31
  • 43
1

The problem is here:

const defaults = {
  myGallery: $(this),
  myList: myGallery.find('li') // <====
};

There is no myGallery variable in scope at that point. You can either call $() twice, add myList after-the-fact, or use a myGallery variable:

const defaults = {
  myGallery: $(this),
  myList: $(this).find('li')
};

or

const defaults = {
  myGallery: $(this)
};
defaults.myList = defaults.myGallery.find('li');

or

const myGallery = $(this);
const defaults = {
  myGallery,
  myList: myGallery.find('li')
};
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875