Home > Enterprise >  Does assigning a variable to a method/function run it every time it's called?
Does assigning a variable to a method/function run it every time it's called?

Time:12-24

I'm trying to make sure I'm building this code as efficiently as possible, but one questions keeps lingering: When I assign a variable to a method, am I slowing down the code every time it's called?

My Example: (Yes, I'm technically using Google Apps Script, not JS, but I think the question applies to both)

Let's say I want to display the Subject of every Message in every Thread in my Gmail inbox 5 times (for some reason). Here's how I'd see that:

function myFunction(){
  let allThreads = GmailApp.getInboxThreads();

  var text = "";
  
  for(let x = 0 ; x < allThreads.length ; x  ){
    let thisThread = x;

    let allMessages = thisThread.getMessages();

    for(let y = 0 ; y < allMessages.length ; y  ){
      let thisMessage = y;

      let thisSubject = thisMessage.getSubject();

      let someNumber = 5;

      for( let z = 0; z < someNumber ; z  ){
        text  = " "   thisSubject;
      }
    }
  }

  Logger.log(text);
}

So, the actual question (finally): Am I calling the getSubject() method EVERY time I'm using the "thisSubject" variable?

Or even worse; Am I running

GmailApp.getInboxThreads()[x].getMessages()[y].getSubject()

every time?

I'm barely a programmer, but would converting it to a string, rather than a reference to a method (or function) make the code run faster? Especially if we're talking referencing it 1,000 times instead of 5.

for example:

//Replace

let thisSubject = thisMessage.getSubject();

//With

let thisSubject = JSON.parse(JSON.stringify(thisMessage.getSubject()));

Then, if we're expanding on that, would finding a way to Stringify only the necessary parts of even GmailApp.getInboxThreads be logical?

To throw another example out there for clarity; If I'm calling Google's SpreadsheetApp to get a sheet name such as:

let mySpreadsheet = SpreadsheetApp.openById('abc123xyz');
let mySheets = mySpreadsheet.getSheets();
let thisSheet = mySheets[1];
let sheetName = thisSheet.getName();

Am I killing my code each time I use sheetName by re-opening the spreadsheet, getting all the sheets in it, picking out the 2nd then pulling it's name all over again?

Or am I cacheing(cache-ing?) an instance of each result of the methods and pulling from them instead?

CodePudding user response:

Am I calling the getSubject() method EVERY time I'm using the "thisSubject" variable?

No. In the inner loop (that runs allThreads.length * allMessages.length tiems), you call it once, on the line:

let allMessages = thisThread.getMessages();

The line initializes a variable named allMessages and has it point to an array in memory. Elsewhere when allMessages is referenced, that existing array is looked up.

Note that you probably have a bug here:

for(let y = 0 ; y < allMessages.length ; y  ){
  let thisMessage = y;
  let thisSubject = thisMessage.getSubject();

You probably meant to do

for(let y = 0 ; y < allMessages.length ; y  ){
  let thisMessage = allMessages[y];
  let thisSubject = thisMessage.getSubject();

or, even better, don't mess with indicies at all, and use iterators and const:

for (const thisMessage of allMessages) {
  const thisSubject = thisMessage.getSubject();
  // ...

Am I killing my code each time I use sheetName by re-opening the spreadsheet, getting all the sheets in it, picking out the 2nd then pulling it's name all over again?

No - .getName() only runs once, and puts its result into memory, and sheetName is a variable that points to that value in memory. Further references to sheetName are trivial lookups to the existing value in memory.

Or am I cacheing(cache-ing?) an instance of each result of the methods and pulling from them instead?

That's right.


In general, caching function call results can be useful. For example, it's better to avoid:

for (const value of someArray) {
  const someOtherValue = getSomeValue();
  // more loop body...

Because someOtherValue doesn't depend on what's being iterated over, you could do

const someOtherValue = getSomeValue();
for (const value of someArray) {
  // more loop body...

and avoid the repeated calls of getSomeValue. But you aren't making such a mistake anywhere in your code; don't worry.

  • Related