The reason it works, is what the code is simply doing, is building the exact JSL needed into a character string, and then using the Eval(Parse(…….)) to tell JMP to submit the character strings value to JMP.
If you take your specific example, the hard coded syntax to accomplish what you want is
ob[TableBox(1)] << add row ({"1", "2", "3", 4});
So, if one can build the above line of code into a character string, the character string can then be submitted to JMP using the Eval(Parse()) combination of functions. Here is a simple expansion of your script to hopefully make this clear
rowContents2 = {"1","2","3",4};
// Create a character string variable with the required syntax
myString = "ob[TableBox(1)] << add row (" || char(rowContents2) || ");";
// Write the string to the log to show what it looks like
show( myString );
// Run the character string variable
Eval( Parse( myString ) );
Jim