Skip to content

Conversation

gifvex
Copy link
Contributor

@gifvex gifvex commented Aug 18, 2023

This is a suggestion PR for a JS::Object#to_a method.

The motivation is to be able to more naturally enumerate collections from JavaScript, without having to separately access the length property and index it:

# from
collection = JS.global[:document].querySelectorAll("p")
collection[:length].to_i.times do |i|
  element = collection[i]
  # ...
end

# to
JS.global[:document].querySelectorAll("p").to_a.each do |element|
  # ...
end

Unit tests cover some of the examples on MDN's Array.from() page.

@Largo
Copy link

Largo commented Feb 6, 2024

Edit: Turns out i was looking in the wrong place in irb.wasm!

I should have checked using:
JS::Object.new.method(:to_a).source_location

class JS::Object
def to_a
ary = []
self[:length].to_i.times do |i|
ary << self.call(:at, i).to_i
end
ary
end
end

Very useful method, but I thought that this fails for arrays with values other than numbers. I'm not sure what "as_array[_1]" does.

irb(main):002> JS.eval("return ['a', 'b', 'c']").to_a
=> [0, 0, 0]

Ok I figured out what _1 does:

"In Ruby, starting from version 2.7, _1, _2, _3, and so on are shorthand syntax for referencing the first, second, third, etc., parameters passed to a block when you don't explicitly name them. This feature is particularly useful to make the code more concise and readable when dealing with blocks that take parameters."

Clever.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants