It is, but other standard methods such as insert
or splice
don’t seem to work… at least I can’t seem to make them work.
So, then magic?
The problem is that those references (despite some pre-processor syntactic sugar which aims to achieve some array-like syntax) are not really JS Array objects.
(They’re actually OSA API function references)
( presumably someone decided to implement unshift
for them, in addition to push
, which despite appearances, is not actually JS’s Array.push
method )
I noticed attributesRun
property of textContent
returned an array, and I had the feeling that, in order to prepend elements to that array, I could try .unshift
method. A feeling, I think.
Not quite, ironically
return typeof (
row
.textContent
.attributeRuns
);
// → function
while …
return (
row
.textContent
.attributeRuns
).toString();
// → [object ArraySpecifier]
ArraySpecifier
is a class which Apple wrote for the JXA interface, deliberately making it look a bit like a JS Array, with [n]
preprocessed to the new class’s own .at(n)
method, and a "push"
intended to remind us of Array.push
, though it actually does something rather different (introduces a new member to a non-array OSA collection structure)
Ditto "unshift"
, which they don’t seem to have documented, but you have very helpfully discovered for us
PS, if you try this:
(() => {
"use strict";
const
bike = Application("bike"),
doc = bike.documents.at(0),
row = doc.rows.at(0),
attributeRun = bike.AttributeRun({
bold: true
}, "additional text ");
return Automation.getDisplayString(
row
.textContent
.attributeRuns
);
})();
You will harvest:
Application("Bike")
.documents.at(0).rows.at(0).textContent.attributeRuns
which reveals that although the preprocessor will accept forms like:
Application("Bike")
.documents[0].rows[0].textContent.attributeRuns
from the user, to give the impression that documents
, rows
etc are arrays, on grounds of familiarity or ease of use,
they are not actually JS Array
s beneath the hood, and lack nearly all of JS Array’s methods and properties (though they do implement a .length
property)
Note that you can obtain a genuine Array as a result of calling the .attributeRuns function ( adding ()
to get a function call expression .attributeRuns()
but using the real Array.push
on that resulting array won’t add a new attribute run to the underlying OSA collection.
Array.push
and ArraySpecifier.push
are two quite different beasts.
Yes, of course ! Because it’s necessary to use trailing parenthesis to obtain the actual value; as you clarified below. I mean, it’s really a method instead of a property.
Thank you for the info about ArraySpecifier
class. Very useful !
PS: Methods are indeed properties. It’s just that functions are stored there, instead of saturated values.