1

I wish I would create something that will help me to get the last item from an array like this

$$("div", list).getLastItem()

my function is:

const $$ = (selector, parent = document) => {
 x = parent.querySelectorAll(selector);
 x = Array.prototype.slice.call(x);
 return x;
}

I was thinking of how to do it, but I'm unable to figure it out, I've tried to do it like this:

$$.prototype.getLastItem = ()=>{
return this.slice(-1)[0];
}

but it's giving an error: Uncaught TypeError: Cannot set property 'getLastItem' of undefined

1-How to implement this?

2-Why my code is not working?

asked Aug 26, 2020 at 4:23
4
  • Are you using jquery or just a plain javascript? Commented Aug 26, 2020 at 4:26
  • Vanilla Javascript Commented Aug 26, 2020 at 4:26
  • 1
    You're returning an Array, so you'd need to put it on Array.prototype, not Function.prototype. Commented Aug 26, 2020 at 4:27
  • ...and by the way, your function can just be return Array.from(parent.querySelectorAll(selector)); Commented Aug 26, 2020 at 4:28

5 Answers 5

1

Return an instance of a class which has a getLastItem method:

class Dollar {
 constructor(selector, parent = document) {
 this.elements = [...parent.querySelectorAll(selector)];
 }
 getLastItem() {
 return this.elements.slice(-1)[0];
 }
}
const $$ = (...args) => new Dollar(...args);
console.log($$('.something').getLastItem());
<div class='something'>something</div>
<div class='something'>something else</div>

To access the nth element, reference the instance's .elements[n] property.

If you also want to be able to access the underlying elements without going through .elements, assign to numeric properties in the constructor:

class Dollar {
 constructor(selector, parent = document) {
 this.elements = [...parent.querySelectorAll(selector)];
 Object.assign(this, this.elements);
 }
 getLastItem() {
 return this.elements.slice(-1)[0];
 }
}
const $$ = (...args) => new Dollar(...args);
const somethings = $$('.something');
console.log(somethings[0]);
console.log(somethings.getLastItem());
<div class='something'>something</div>
<div class='something'>something else</div>

answered Aug 26, 2020 at 4:29
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks your code is amazing. code you please explain this line Object.assign(this, this.elements);
That puts the numeric-indexed properties from the .elements array onto the instance - eg, it means that $$(...).elements[0] can be accessed by doing $$(...)[0]
0

getLastItem should be bound to the prototype of Array:

Array.prototype.getLastItem = function () { ... }
answered Aug 26, 2020 at 4:33

1 Comment

Do you think that this is a good implementation? because I've heard many times that it's not good to change anything inside the prototypes of the built-in javascript methods and functions
0

I'm not sure if you just want to get the last item or require creating a method for a function.

If you just want to get the last item, can't you just do:

const lastItem = $$('div').slice(-1)[0];

That seems to get the last div just fine...

answered Aug 26, 2020 at 4:37

Comments

0

You could achieve what you expected right from your current solution with a some changes

  • use function to access the this context
  • use New-Agnostic Constructor Pattern (as described in David Herman’s Effective JavaScript) to construct object without the need of using new
  • return the instance itself (return this) to use further defined method

function $$(selector, parent = document) {
 if (!(this instanceof $$)) {
 return new $$(selector, parent);
 }
 const x = parent.querySelectorAll(selector);
 this.selected = Array.prototype.slice.call(x);
 return this;
}
$$.prototype.getLastItem = function() {
 return this.selected.slice(-1)[0];
}
console.log($$("div").getLastItem())
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>

answered Aug 26, 2020 at 4:50

Comments

0

You can simply move function getLastItem inside $$ and assign it to x as x.getLastItem, use return x.slice(-1)[0] and return x. It will work.

Try it below.

const $$ = (selector, parent = document) => { 
 let x = parent.querySelectorAll(selector);
 x = Array.prototype.slice.call(x);
 x.getLastItem = () => {
 return x.slice(-1)[0];
 }
 return x;
}
console.log($$("div").getLastItem());
console.log($$("div")[0]);
<div id='test'></div>

answered Aug 26, 2020 at 4:45

2 Comments

could you please explain what this line is doing return this;
In my previous code this will return window object as you are working with arrow function. So getLastItem will be bind to window when you call $$(...). I feel it is better to bind getLastItem to specific object rather than window so I updated the code and bind it to x and return x. Now you can also use $$("div")[0].

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.