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?
5 Answers 5
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>
2 Comments
.elements array onto the instance - eg, it means that $$(...).elements[0] can be accessed by doing $$(...)[0]getLastItem should be bound to the prototype of Array:
Array.prototype.getLastItem = function () { ... }
1 Comment
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...
Comments
You could achieve what you expected right from your current solution with a some changes
- use
functionto access thethiscontext - 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>
Comments
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>
2 Comments
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].
Array.prototype, notFunction.prototype.return Array.from(parent.querySelectorAll(selector));