Triggering based on words or phrases entered in a text box

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;







up vote
1
down vote

favorite












I am working on a simple loop that when a user enters text into a textbox if certain words or phrases are entered, xyz is triggered. I have my code working as needed but am looking for way to improve / optimize it.



$("#input_test").on("keyup",function()
var common = false;

var inputVal = $(this).val().toLowerCase().replace(/[^a-zA-Z ]/g, "");

var triggerWords = ['hello there','world', 'hello world', 'how do I turn this on', 'general kenobi'];


var common = triggerWords.some(function(v)
return inputVal.indexOf(v) !== -1;
);

if(common)
$('#showme').show(300);
else
$('#showme').hide(300);


);


Working JSFiddle







share|improve this question





















  • triggerWordsLen feels unnecessary, but other than that its pretty good (although its badly indented at least here), shouldn´t need any optimization unless you are dealing with thousands of words/phrases to check
    – juvian
    Apr 3 at 16:39










  • @juvian the main reason I have triggerWordsLen is so it doesn’t calculate .length on every iteration. I wanted to get into this habit so that I don't do something crazy like for(var i = 0; i < someComplexFunction(); i++) in the future :D
    – Ardz
    Apr 3 at 16:53










  • length is a property and not a function so it won´t calculate on every iteration. For more details check stackoverflow.com/a/17995000/3308055. But yes, for a function call you would do that so you can get used to it that way
    – juvian
    Apr 3 at 17:03






  • 1




    @juvian super intersting read, thank you for that!
    – Ardz
    Apr 3 at 17:11










  • One of your trigger words have an upper case letter, but you are converting the input to lower case, so it can never match.
    – Kruga
    Apr 4 at 14:24
















up vote
1
down vote

favorite












I am working on a simple loop that when a user enters text into a textbox if certain words or phrases are entered, xyz is triggered. I have my code working as needed but am looking for way to improve / optimize it.



$("#input_test").on("keyup",function()
var common = false;

var inputVal = $(this).val().toLowerCase().replace(/[^a-zA-Z ]/g, "");

var triggerWords = ['hello there','world', 'hello world', 'how do I turn this on', 'general kenobi'];


var common = triggerWords.some(function(v)
return inputVal.indexOf(v) !== -1;
);

if(common)
$('#showme').show(300);
else
$('#showme').hide(300);


);


Working JSFiddle







share|improve this question





















  • triggerWordsLen feels unnecessary, but other than that its pretty good (although its badly indented at least here), shouldn´t need any optimization unless you are dealing with thousands of words/phrases to check
    – juvian
    Apr 3 at 16:39










  • @juvian the main reason I have triggerWordsLen is so it doesn’t calculate .length on every iteration. I wanted to get into this habit so that I don't do something crazy like for(var i = 0; i < someComplexFunction(); i++) in the future :D
    – Ardz
    Apr 3 at 16:53










  • length is a property and not a function so it won´t calculate on every iteration. For more details check stackoverflow.com/a/17995000/3308055. But yes, for a function call you would do that so you can get used to it that way
    – juvian
    Apr 3 at 17:03






  • 1




    @juvian super intersting read, thank you for that!
    – Ardz
    Apr 3 at 17:11










  • One of your trigger words have an upper case letter, but you are converting the input to lower case, so it can never match.
    – Kruga
    Apr 4 at 14:24












up vote
1
down vote

favorite









up vote
1
down vote

favorite











I am working on a simple loop that when a user enters text into a textbox if certain words or phrases are entered, xyz is triggered. I have my code working as needed but am looking for way to improve / optimize it.



$("#input_test").on("keyup",function()
var common = false;

var inputVal = $(this).val().toLowerCase().replace(/[^a-zA-Z ]/g, "");

var triggerWords = ['hello there','world', 'hello world', 'how do I turn this on', 'general kenobi'];


var common = triggerWords.some(function(v)
return inputVal.indexOf(v) !== -1;
);

if(common)
$('#showme').show(300);
else
$('#showme').hide(300);


);


Working JSFiddle







share|improve this question













I am working on a simple loop that when a user enters text into a textbox if certain words or phrases are entered, xyz is triggered. I have my code working as needed but am looking for way to improve / optimize it.



$("#input_test").on("keyup",function()
var common = false;

var inputVal = $(this).val().toLowerCase().replace(/[^a-zA-Z ]/g, "");

var triggerWords = ['hello there','world', 'hello world', 'how do I turn this on', 'general kenobi'];


var common = triggerWords.some(function(v)
return inputVal.indexOf(v) !== -1;
);

if(common)
$('#showme').show(300);
else
$('#showme').hide(300);


);


Working JSFiddle









share|improve this question












share|improve this question




share|improve this question








edited Apr 3 at 17:13
























asked Apr 3 at 15:37









Ardz

92




92











  • triggerWordsLen feels unnecessary, but other than that its pretty good (although its badly indented at least here), shouldn´t need any optimization unless you are dealing with thousands of words/phrases to check
    – juvian
    Apr 3 at 16:39










  • @juvian the main reason I have triggerWordsLen is so it doesn’t calculate .length on every iteration. I wanted to get into this habit so that I don't do something crazy like for(var i = 0; i < someComplexFunction(); i++) in the future :D
    – Ardz
    Apr 3 at 16:53










  • length is a property and not a function so it won´t calculate on every iteration. For more details check stackoverflow.com/a/17995000/3308055. But yes, for a function call you would do that so you can get used to it that way
    – juvian
    Apr 3 at 17:03






  • 1




    @juvian super intersting read, thank you for that!
    – Ardz
    Apr 3 at 17:11










  • One of your trigger words have an upper case letter, but you are converting the input to lower case, so it can never match.
    – Kruga
    Apr 4 at 14:24
















  • triggerWordsLen feels unnecessary, but other than that its pretty good (although its badly indented at least here), shouldn´t need any optimization unless you are dealing with thousands of words/phrases to check
    – juvian
    Apr 3 at 16:39










  • @juvian the main reason I have triggerWordsLen is so it doesn’t calculate .length on every iteration. I wanted to get into this habit so that I don't do something crazy like for(var i = 0; i < someComplexFunction(); i++) in the future :D
    – Ardz
    Apr 3 at 16:53










  • length is a property and not a function so it won´t calculate on every iteration. For more details check stackoverflow.com/a/17995000/3308055. But yes, for a function call you would do that so you can get used to it that way
    – juvian
    Apr 3 at 17:03






  • 1




    @juvian super intersting read, thank you for that!
    – Ardz
    Apr 3 at 17:11










  • One of your trigger words have an upper case letter, but you are converting the input to lower case, so it can never match.
    – Kruga
    Apr 4 at 14:24















triggerWordsLen feels unnecessary, but other than that its pretty good (although its badly indented at least here), shouldn´t need any optimization unless you are dealing with thousands of words/phrases to check
– juvian
Apr 3 at 16:39




triggerWordsLen feels unnecessary, but other than that its pretty good (although its badly indented at least here), shouldn´t need any optimization unless you are dealing with thousands of words/phrases to check
– juvian
Apr 3 at 16:39












@juvian the main reason I have triggerWordsLen is so it doesn’t calculate .length on every iteration. I wanted to get into this habit so that I don't do something crazy like for(var i = 0; i < someComplexFunction(); i++) in the future :D
– Ardz
Apr 3 at 16:53




@juvian the main reason I have triggerWordsLen is so it doesn’t calculate .length on every iteration. I wanted to get into this habit so that I don't do something crazy like for(var i = 0; i < someComplexFunction(); i++) in the future :D
– Ardz
Apr 3 at 16:53












length is a property and not a function so it won´t calculate on every iteration. For more details check stackoverflow.com/a/17995000/3308055. But yes, for a function call you would do that so you can get used to it that way
– juvian
Apr 3 at 17:03




length is a property and not a function so it won´t calculate on every iteration. For more details check stackoverflow.com/a/17995000/3308055. But yes, for a function call you would do that so you can get used to it that way
– juvian
Apr 3 at 17:03




1




1




@juvian super intersting read, thank you for that!
– Ardz
Apr 3 at 17:11




@juvian super intersting read, thank you for that!
– Ardz
Apr 3 at 17:11












One of your trigger words have an upper case letter, but you are converting the input to lower case, so it can never match.
– Kruga
Apr 4 at 14:24




One of your trigger words have an upper case letter, but you are converting the input to lower case, so it can never match.
– Kruga
Apr 4 at 14:24










1 Answer
1






active

oldest

votes

















up vote
1
down vote













Performance




I have my code working as needed but am looking for way to improve / optimize it.




If you want to improve the performances there are a few things you can do.



Testing



The first thing is that you can run tests and see how code style and logic can effect performance. Javascript testing is a little tricky. You can not just run the functions. You need to make sure you are not being tricked by the optimiser



I have added a basic Javascript performance tester to the bottom to highlight the following points.



Slow iterators



The Array iteration functions such as Array.some are generally slower than writing a standard for, for of or while loop. The reason is because functions incur a lot of additional overhead each time they are call. They need their own memory, special structures to hold the current scope, and closure values. All this is added to the JavaScript heap and called the function's "context".



On top of that the actual function Array.some has to do some checks to make sure that the arguments you pass are correct and can be used. This all adds to the time to run the function.



For of loops are faster



Using a for...of loop avoids all that overhead and for this example is about 60% faster (on Chrome)



var triggerWords = ['hello there','world', 'hello world', 'how do I turn this on', 'general kenobi'];
for(const word of triggerWords )
if(inputVal.indexOf(word)
$("#showme).show(300);
return; // all done exit the key up event


$("#showme).hide(300);


Native power!



But the problem is still the iteration. Using JavaScript to check each string in turn is never going to utilize a modern CPU's true power. But there is a way to have the search done using pure native code.



RegExp will do the test in a fraction of the time.



Building the regular expression from array of string is expensive, so you would not use this method if the search string (triggerWords) changes each test. But if the the search is the same each time, you can build the regExp at the start and you get around a 1000% performance boost.



// create at start;
var triggerWords = ['hello there','world', 'hello world', 'how do I turn this on', 'general kenobi'];
const reg = new RegExp(triggerWords.join("|"),"gi")

// inside the key event
if(reg.test(inputVal))
$("#showme).show(300);
else
$("#showme).hide(300);



The cost of libraries



The easiest way to get a performance boost is to drop the libraries.



Without jQuery the code looks like.



const wordSearch = /hello there|world|hello world|how do I turn this on|general kenobi/gi;
inputTest.addEventListener("keyup", (event) =>
if( wordSearch.test(inputTest.value.replace(/[^a-z ]/gi,"")) )
showme.classList.remove('hide');
else
showme.classList.add('hide');

);


And add a hide class to the CSS.



 .hide display : none; 


The next snippet shows it all put together, copied from your fiddle (a page needing well over 1Mbyte of javascript to run) to a total of less than 1000bytes for all the code, css, and markup






const wordSearch = /hello there|world|hello world|how do I turn this on|general kenobi/gi;
inputTest.addEventListener("keyup", (event) =>
if( wordSearch.test(inputTest.value.replace(/[^a-z ]/gi,"")) )
showme.classList.remove('hide');
else
showme.classList.add('hide');

);

#showme
padding-top:15px;

.muted
padding-top:15px;
font-size:12px;
color:#ccc;

.hide
display : none;

<p>
Enter a word or phrase to search:
</p>
Search: <input id ="inputTest" type="text" placeholder="Word / Phrase">
<div id="showme" class="hide">
<iframe src="https://giphy.com/embed/Nx0rz3jtxtEre" width="240" height="120" frameBorder="0" class="giphy-embed" allowFullScreen></iframe>
</div>
<div class="muted">Indexed words / phrases:
<ul>
<li>hello there</li>
<li>world</li>
<li>hello</li>
<li>hello world</li>
<li>how do I turn this on</li>
<li>general kenobi</li>
</ul>
</div>





Example performance comparisons.



The snipped tests the 3 search methods Array.some, for..of and regExp



It uses the worst case scenario and runs the tests many 1000's of times. The test order is random to stop the optimizer slewing one method over another, and the result of each search are socked up by a global variable to stop the optimizer from just removing the inner loops completely



Let the test run until the mean times start to stabilize then click the page to compare the performance results.






/*===========================================================================
Set up test data.
One big array with

===========================================================================*/
const rand = (max) => Math.random() * max | 0;
const innerLoopCount = 1000;
var c = "aabbaa";
var b = "skjht kjhlvuh svrtgkj abcdef ghijklmn opqrst uvwxyz1 234567890 ";
var a = ;
for(i = 0; i < 10; i ++) a.push(b.substr(rand(b.length -10), rand(8) + 2)) ;
var reg = new RegExp(a.join("|"),"gi");
document.addEventListener("click",() => stop = true )
var stop = false;

var soak = 0; // this is to prevent optimiser removing test code. It soaks up entropy generated by the functions :P
function testA()
var i = 0, found;
const now = performance.now()
while(i++ < innerLoopCount)
var found = a.some(function(word)
return c.indexOf(word) > -1;
)

soak += found ? 1:0;

return performance.now() - now

function testB()
const now = performance.now()
var i = 0, found;
while(i++ < innerLoopCount)
found = false;
for(const word of a)
if(c.indexOf(word) > -1)
found = true;
break;


soak += found ? 1:0;

return performance.now() - now;

function testC()
const now = performance.now()
var i = 0, found;
while(i++ < innerLoopCount)

found = reg.test(c);
//for(const word of a)
// if(c.indexOf(word) > -1)
// found = true;
// break;
//
//
soak += found ? 1:0;

return performance.now() - now;



const tests = [
count : 0, time : 0, run : testA, status : statusElementA, name : " 'Array.some' : ",
count : 0, time : 0, run : testB, status : statusElementB, name : " 'for...of' : ",
count : 0, time : 0, run : testC, status : statusElementC, name : " 'regExp' : ",
];
function testing()
var testsCount = tests.length;

for(var i = 0;i < 100; i ++) 0];
selTest.time += selTest.run();
selTest.count += 1;

for(const test of tests)
test.mean = test.time / test.count;
test.status.textContent = `$test.name mean $test.mean.toFixed(3)ms over $test.count cycles.`;

if(!stop)

setTimeout(testing,100);
else
tests.sort((a,b) => a.mean - b.mean);
const slowest = tests[tests.length -1].mean;
var win = " 🐇 <span class='winner'>Fastest</span>";
let test;
for(test of tests)
test.status.textContent += (test.mean / slowest * 100).toFixed(1) + "%"
if( win )
test.status.innerHTML += win;
test.status.className = "champ";
win = undefined;


test.status.innerHTML += " 🐢 <span class='looser'>Slowest</span>"
test.status.className = "lost";


setTimeout(testing,100);

body 
font-family : arial;
font size : large;
text-align : center;

h4
font-size : small;

.winner
color : green;


.looser
color : red;

.champ
background : #CFC;
font-weight : 700;

transition: all 0.5s ease-out;

.lost
background : #FCC;
transition: all 0.5s ease-out;



<h3>Javascript Array.some V for...of V regExp</h3>
<h4>Click on the page to stop testing.</h4>
<div id="statusElementA"></div>
<div id="statusElementB"></div>
<div id="statusElementC"></div>








share|improve this answer





















  • The regex should not have the global flag, since subsequent calls to .test will be wrong. Documentation
    – Kruga
    Apr 4 at 14:19










  • This is a crazy amount of info! I love it! Thank you so much for helping me understand.
    – Ardz
    Apr 4 at 14:34










Your Answer




StackExchange.ifUsing("editor", function ()
return StackExchange.using("mathjaxEditing", function ()
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
);
);
, "mathjax-editing");

StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");

StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "196"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
convertImagesToLinks: false,
noModals: false,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);








 

draft saved


draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f191175%2ftriggering-based-on-words-or-phrases-entered-in-a-text-box%23new-answer', 'question_page');

);

Post as a guest






























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes








up vote
1
down vote













Performance




I have my code working as needed but am looking for way to improve / optimize it.




If you want to improve the performances there are a few things you can do.



Testing



The first thing is that you can run tests and see how code style and logic can effect performance. Javascript testing is a little tricky. You can not just run the functions. You need to make sure you are not being tricked by the optimiser



I have added a basic Javascript performance tester to the bottom to highlight the following points.



Slow iterators



The Array iteration functions such as Array.some are generally slower than writing a standard for, for of or while loop. The reason is because functions incur a lot of additional overhead each time they are call. They need their own memory, special structures to hold the current scope, and closure values. All this is added to the JavaScript heap and called the function's "context".



On top of that the actual function Array.some has to do some checks to make sure that the arguments you pass are correct and can be used. This all adds to the time to run the function.



For of loops are faster



Using a for...of loop avoids all that overhead and for this example is about 60% faster (on Chrome)



var triggerWords = ['hello there','world', 'hello world', 'how do I turn this on', 'general kenobi'];
for(const word of triggerWords )
if(inputVal.indexOf(word)
$("#showme).show(300);
return; // all done exit the key up event


$("#showme).hide(300);


Native power!



But the problem is still the iteration. Using JavaScript to check each string in turn is never going to utilize a modern CPU's true power. But there is a way to have the search done using pure native code.



RegExp will do the test in a fraction of the time.



Building the regular expression from array of string is expensive, so you would not use this method if the search string (triggerWords) changes each test. But if the the search is the same each time, you can build the regExp at the start and you get around a 1000% performance boost.



// create at start;
var triggerWords = ['hello there','world', 'hello world', 'how do I turn this on', 'general kenobi'];
const reg = new RegExp(triggerWords.join("|"),"gi")

// inside the key event
if(reg.test(inputVal))
$("#showme).show(300);
else
$("#showme).hide(300);



The cost of libraries



The easiest way to get a performance boost is to drop the libraries.



Without jQuery the code looks like.



const wordSearch = /hello there|world|hello world|how do I turn this on|general kenobi/gi;
inputTest.addEventListener("keyup", (event) =>
if( wordSearch.test(inputTest.value.replace(/[^a-z ]/gi,"")) )
showme.classList.remove('hide');
else
showme.classList.add('hide');

);


And add a hide class to the CSS.



 .hide display : none; 


The next snippet shows it all put together, copied from your fiddle (a page needing well over 1Mbyte of javascript to run) to a total of less than 1000bytes for all the code, css, and markup






const wordSearch = /hello there|world|hello world|how do I turn this on|general kenobi/gi;
inputTest.addEventListener("keyup", (event) =>
if( wordSearch.test(inputTest.value.replace(/[^a-z ]/gi,"")) )
showme.classList.remove('hide');
else
showme.classList.add('hide');

);

#showme
padding-top:15px;

.muted
padding-top:15px;
font-size:12px;
color:#ccc;

.hide
display : none;

<p>
Enter a word or phrase to search:
</p>
Search: <input id ="inputTest" type="text" placeholder="Word / Phrase">
<div id="showme" class="hide">
<iframe src="https://giphy.com/embed/Nx0rz3jtxtEre" width="240" height="120" frameBorder="0" class="giphy-embed" allowFullScreen></iframe>
</div>
<div class="muted">Indexed words / phrases:
<ul>
<li>hello there</li>
<li>world</li>
<li>hello</li>
<li>hello world</li>
<li>how do I turn this on</li>
<li>general kenobi</li>
</ul>
</div>





Example performance comparisons.



The snipped tests the 3 search methods Array.some, for..of and regExp



It uses the worst case scenario and runs the tests many 1000's of times. The test order is random to stop the optimizer slewing one method over another, and the result of each search are socked up by a global variable to stop the optimizer from just removing the inner loops completely



Let the test run until the mean times start to stabilize then click the page to compare the performance results.






/*===========================================================================
Set up test data.
One big array with

===========================================================================*/
const rand = (max) => Math.random() * max | 0;
const innerLoopCount = 1000;
var c = "aabbaa";
var b = "skjht kjhlvuh svrtgkj abcdef ghijklmn opqrst uvwxyz1 234567890 ";
var a = ;
for(i = 0; i < 10; i ++) a.push(b.substr(rand(b.length -10), rand(8) + 2)) ;
var reg = new RegExp(a.join("|"),"gi");
document.addEventListener("click",() => stop = true )
var stop = false;

var soak = 0; // this is to prevent optimiser removing test code. It soaks up entropy generated by the functions :P
function testA()
var i = 0, found;
const now = performance.now()
while(i++ < innerLoopCount)
var found = a.some(function(word)
return c.indexOf(word) > -1;
)

soak += found ? 1:0;

return performance.now() - now

function testB()
const now = performance.now()
var i = 0, found;
while(i++ < innerLoopCount)
found = false;
for(const word of a)
if(c.indexOf(word) > -1)
found = true;
break;


soak += found ? 1:0;

return performance.now() - now;

function testC()
const now = performance.now()
var i = 0, found;
while(i++ < innerLoopCount)

found = reg.test(c);
//for(const word of a)
// if(c.indexOf(word) > -1)
// found = true;
// break;
//
//
soak += found ? 1:0;

return performance.now() - now;



const tests = [
count : 0, time : 0, run : testA, status : statusElementA, name : " 'Array.some' : ",
count : 0, time : 0, run : testB, status : statusElementB, name : " 'for...of' : ",
count : 0, time : 0, run : testC, status : statusElementC, name : " 'regExp' : ",
];
function testing()
var testsCount = tests.length;

for(var i = 0;i < 100; i ++) 0];
selTest.time += selTest.run();
selTest.count += 1;

for(const test of tests)
test.mean = test.time / test.count;
test.status.textContent = `$test.name mean $test.mean.toFixed(3)ms over $test.count cycles.`;

if(!stop)

setTimeout(testing,100);
else
tests.sort((a,b) => a.mean - b.mean);
const slowest = tests[tests.length -1].mean;
var win = " 🐇 <span class='winner'>Fastest</span>";
let test;
for(test of tests)
test.status.textContent += (test.mean / slowest * 100).toFixed(1) + "%"
if( win )
test.status.innerHTML += win;
test.status.className = "champ";
win = undefined;


test.status.innerHTML += " 🐢 <span class='looser'>Slowest</span>"
test.status.className = "lost";


setTimeout(testing,100);

body 
font-family : arial;
font size : large;
text-align : center;

h4
font-size : small;

.winner
color : green;


.looser
color : red;

.champ
background : #CFC;
font-weight : 700;

transition: all 0.5s ease-out;

.lost
background : #FCC;
transition: all 0.5s ease-out;



<h3>Javascript Array.some V for...of V regExp</h3>
<h4>Click on the page to stop testing.</h4>
<div id="statusElementA"></div>
<div id="statusElementB"></div>
<div id="statusElementC"></div>








share|improve this answer





















  • The regex should not have the global flag, since subsequent calls to .test will be wrong. Documentation
    – Kruga
    Apr 4 at 14:19










  • This is a crazy amount of info! I love it! Thank you so much for helping me understand.
    – Ardz
    Apr 4 at 14:34














up vote
1
down vote













Performance




I have my code working as needed but am looking for way to improve / optimize it.




If you want to improve the performances there are a few things you can do.



Testing



The first thing is that you can run tests and see how code style and logic can effect performance. Javascript testing is a little tricky. You can not just run the functions. You need to make sure you are not being tricked by the optimiser



I have added a basic Javascript performance tester to the bottom to highlight the following points.



Slow iterators



The Array iteration functions such as Array.some are generally slower than writing a standard for, for of or while loop. The reason is because functions incur a lot of additional overhead each time they are call. They need their own memory, special structures to hold the current scope, and closure values. All this is added to the JavaScript heap and called the function's "context".



On top of that the actual function Array.some has to do some checks to make sure that the arguments you pass are correct and can be used. This all adds to the time to run the function.



For of loops are faster



Using a for...of loop avoids all that overhead and for this example is about 60% faster (on Chrome)



var triggerWords = ['hello there','world', 'hello world', 'how do I turn this on', 'general kenobi'];
for(const word of triggerWords )
if(inputVal.indexOf(word)
$("#showme).show(300);
return; // all done exit the key up event


$("#showme).hide(300);


Native power!



But the problem is still the iteration. Using JavaScript to check each string in turn is never going to utilize a modern CPU's true power. But there is a way to have the search done using pure native code.



RegExp will do the test in a fraction of the time.



Building the regular expression from array of string is expensive, so you would not use this method if the search string (triggerWords) changes each test. But if the the search is the same each time, you can build the regExp at the start and you get around a 1000% performance boost.



// create at start;
var triggerWords = ['hello there','world', 'hello world', 'how do I turn this on', 'general kenobi'];
const reg = new RegExp(triggerWords.join("|"),"gi")

// inside the key event
if(reg.test(inputVal))
$("#showme).show(300);
else
$("#showme).hide(300);



The cost of libraries



The easiest way to get a performance boost is to drop the libraries.



Without jQuery the code looks like.



const wordSearch = /hello there|world|hello world|how do I turn this on|general kenobi/gi;
inputTest.addEventListener("keyup", (event) =>
if( wordSearch.test(inputTest.value.replace(/[^a-z ]/gi,"")) )
showme.classList.remove('hide');
else
showme.classList.add('hide');

);


And add a hide class to the CSS.



 .hide display : none; 


The next snippet shows it all put together, copied from your fiddle (a page needing well over 1Mbyte of javascript to run) to a total of less than 1000bytes for all the code, css, and markup






const wordSearch = /hello there|world|hello world|how do I turn this on|general kenobi/gi;
inputTest.addEventListener("keyup", (event) =>
if( wordSearch.test(inputTest.value.replace(/[^a-z ]/gi,"")) )
showme.classList.remove('hide');
else
showme.classList.add('hide');

);

#showme
padding-top:15px;

.muted
padding-top:15px;
font-size:12px;
color:#ccc;

.hide
display : none;

<p>
Enter a word or phrase to search:
</p>
Search: <input id ="inputTest" type="text" placeholder="Word / Phrase">
<div id="showme" class="hide">
<iframe src="https://giphy.com/embed/Nx0rz3jtxtEre" width="240" height="120" frameBorder="0" class="giphy-embed" allowFullScreen></iframe>
</div>
<div class="muted">Indexed words / phrases:
<ul>
<li>hello there</li>
<li>world</li>
<li>hello</li>
<li>hello world</li>
<li>how do I turn this on</li>
<li>general kenobi</li>
</ul>
</div>





Example performance comparisons.



The snipped tests the 3 search methods Array.some, for..of and regExp



It uses the worst case scenario and runs the tests many 1000's of times. The test order is random to stop the optimizer slewing one method over another, and the result of each search are socked up by a global variable to stop the optimizer from just removing the inner loops completely



Let the test run until the mean times start to stabilize then click the page to compare the performance results.






/*===========================================================================
Set up test data.
One big array with

===========================================================================*/
const rand = (max) => Math.random() * max | 0;
const innerLoopCount = 1000;
var c = "aabbaa";
var b = "skjht kjhlvuh svrtgkj abcdef ghijklmn opqrst uvwxyz1 234567890 ";
var a = ;
for(i = 0; i < 10; i ++) a.push(b.substr(rand(b.length -10), rand(8) + 2)) ;
var reg = new RegExp(a.join("|"),"gi");
document.addEventListener("click",() => stop = true )
var stop = false;

var soak = 0; // this is to prevent optimiser removing test code. It soaks up entropy generated by the functions :P
function testA()
var i = 0, found;
const now = performance.now()
while(i++ < innerLoopCount)
var found = a.some(function(word)
return c.indexOf(word) > -1;
)

soak += found ? 1:0;

return performance.now() - now

function testB()
const now = performance.now()
var i = 0, found;
while(i++ < innerLoopCount)
found = false;
for(const word of a)
if(c.indexOf(word) > -1)
found = true;
break;


soak += found ? 1:0;

return performance.now() - now;

function testC()
const now = performance.now()
var i = 0, found;
while(i++ < innerLoopCount)

found = reg.test(c);
//for(const word of a)
// if(c.indexOf(word) > -1)
// found = true;
// break;
//
//
soak += found ? 1:0;

return performance.now() - now;



const tests = [
count : 0, time : 0, run : testA, status : statusElementA, name : " 'Array.some' : ",
count : 0, time : 0, run : testB, status : statusElementB, name : " 'for...of' : ",
count : 0, time : 0, run : testC, status : statusElementC, name : " 'regExp' : ",
];
function testing()
var testsCount = tests.length;

for(var i = 0;i < 100; i ++) 0];
selTest.time += selTest.run();
selTest.count += 1;

for(const test of tests)
test.mean = test.time / test.count;
test.status.textContent = `$test.name mean $test.mean.toFixed(3)ms over $test.count cycles.`;

if(!stop)

setTimeout(testing,100);
else
tests.sort((a,b) => a.mean - b.mean);
const slowest = tests[tests.length -1].mean;
var win = " 🐇 <span class='winner'>Fastest</span>";
let test;
for(test of tests)
test.status.textContent += (test.mean / slowest * 100).toFixed(1) + "%"
if( win )
test.status.innerHTML += win;
test.status.className = "champ";
win = undefined;


test.status.innerHTML += " 🐢 <span class='looser'>Slowest</span>"
test.status.className = "lost";


setTimeout(testing,100);

body 
font-family : arial;
font size : large;
text-align : center;

h4
font-size : small;

.winner
color : green;


.looser
color : red;

.champ
background : #CFC;
font-weight : 700;

transition: all 0.5s ease-out;

.lost
background : #FCC;
transition: all 0.5s ease-out;



<h3>Javascript Array.some V for...of V regExp</h3>
<h4>Click on the page to stop testing.</h4>
<div id="statusElementA"></div>
<div id="statusElementB"></div>
<div id="statusElementC"></div>








share|improve this answer





















  • The regex should not have the global flag, since subsequent calls to .test will be wrong. Documentation
    – Kruga
    Apr 4 at 14:19










  • This is a crazy amount of info! I love it! Thank you so much for helping me understand.
    – Ardz
    Apr 4 at 14:34












up vote
1
down vote










up vote
1
down vote









Performance




I have my code working as needed but am looking for way to improve / optimize it.




If you want to improve the performances there are a few things you can do.



Testing



The first thing is that you can run tests and see how code style and logic can effect performance. Javascript testing is a little tricky. You can not just run the functions. You need to make sure you are not being tricked by the optimiser



I have added a basic Javascript performance tester to the bottom to highlight the following points.



Slow iterators



The Array iteration functions such as Array.some are generally slower than writing a standard for, for of or while loop. The reason is because functions incur a lot of additional overhead each time they are call. They need their own memory, special structures to hold the current scope, and closure values. All this is added to the JavaScript heap and called the function's "context".



On top of that the actual function Array.some has to do some checks to make sure that the arguments you pass are correct and can be used. This all adds to the time to run the function.



For of loops are faster



Using a for...of loop avoids all that overhead and for this example is about 60% faster (on Chrome)



var triggerWords = ['hello there','world', 'hello world', 'how do I turn this on', 'general kenobi'];
for(const word of triggerWords )
if(inputVal.indexOf(word)
$("#showme).show(300);
return; // all done exit the key up event


$("#showme).hide(300);


Native power!



But the problem is still the iteration. Using JavaScript to check each string in turn is never going to utilize a modern CPU's true power. But there is a way to have the search done using pure native code.



RegExp will do the test in a fraction of the time.



Building the regular expression from array of string is expensive, so you would not use this method if the search string (triggerWords) changes each test. But if the the search is the same each time, you can build the regExp at the start and you get around a 1000% performance boost.



// create at start;
var triggerWords = ['hello there','world', 'hello world', 'how do I turn this on', 'general kenobi'];
const reg = new RegExp(triggerWords.join("|"),"gi")

// inside the key event
if(reg.test(inputVal))
$("#showme).show(300);
else
$("#showme).hide(300);



The cost of libraries



The easiest way to get a performance boost is to drop the libraries.



Without jQuery the code looks like.



const wordSearch = /hello there|world|hello world|how do I turn this on|general kenobi/gi;
inputTest.addEventListener("keyup", (event) =>
if( wordSearch.test(inputTest.value.replace(/[^a-z ]/gi,"")) )
showme.classList.remove('hide');
else
showme.classList.add('hide');

);


And add a hide class to the CSS.



 .hide display : none; 


The next snippet shows it all put together, copied from your fiddle (a page needing well over 1Mbyte of javascript to run) to a total of less than 1000bytes for all the code, css, and markup






const wordSearch = /hello there|world|hello world|how do I turn this on|general kenobi/gi;
inputTest.addEventListener("keyup", (event) =>
if( wordSearch.test(inputTest.value.replace(/[^a-z ]/gi,"")) )
showme.classList.remove('hide');
else
showme.classList.add('hide');

);

#showme
padding-top:15px;

.muted
padding-top:15px;
font-size:12px;
color:#ccc;

.hide
display : none;

<p>
Enter a word or phrase to search:
</p>
Search: <input id ="inputTest" type="text" placeholder="Word / Phrase">
<div id="showme" class="hide">
<iframe src="https://giphy.com/embed/Nx0rz3jtxtEre" width="240" height="120" frameBorder="0" class="giphy-embed" allowFullScreen></iframe>
</div>
<div class="muted">Indexed words / phrases:
<ul>
<li>hello there</li>
<li>world</li>
<li>hello</li>
<li>hello world</li>
<li>how do I turn this on</li>
<li>general kenobi</li>
</ul>
</div>





Example performance comparisons.



The snipped tests the 3 search methods Array.some, for..of and regExp



It uses the worst case scenario and runs the tests many 1000's of times. The test order is random to stop the optimizer slewing one method over another, and the result of each search are socked up by a global variable to stop the optimizer from just removing the inner loops completely



Let the test run until the mean times start to stabilize then click the page to compare the performance results.






/*===========================================================================
Set up test data.
One big array with

===========================================================================*/
const rand = (max) => Math.random() * max | 0;
const innerLoopCount = 1000;
var c = "aabbaa";
var b = "skjht kjhlvuh svrtgkj abcdef ghijklmn opqrst uvwxyz1 234567890 ";
var a = ;
for(i = 0; i < 10; i ++) a.push(b.substr(rand(b.length -10), rand(8) + 2)) ;
var reg = new RegExp(a.join("|"),"gi");
document.addEventListener("click",() => stop = true )
var stop = false;

var soak = 0; // this is to prevent optimiser removing test code. It soaks up entropy generated by the functions :P
function testA()
var i = 0, found;
const now = performance.now()
while(i++ < innerLoopCount)
var found = a.some(function(word)
return c.indexOf(word) > -1;
)

soak += found ? 1:0;

return performance.now() - now

function testB()
const now = performance.now()
var i = 0, found;
while(i++ < innerLoopCount)
found = false;
for(const word of a)
if(c.indexOf(word) > -1)
found = true;
break;


soak += found ? 1:0;

return performance.now() - now;

function testC()
const now = performance.now()
var i = 0, found;
while(i++ < innerLoopCount)

found = reg.test(c);
//for(const word of a)
// if(c.indexOf(word) > -1)
// found = true;
// break;
//
//
soak += found ? 1:0;

return performance.now() - now;



const tests = [
count : 0, time : 0, run : testA, status : statusElementA, name : " 'Array.some' : ",
count : 0, time : 0, run : testB, status : statusElementB, name : " 'for...of' : ",
count : 0, time : 0, run : testC, status : statusElementC, name : " 'regExp' : ",
];
function testing()
var testsCount = tests.length;

for(var i = 0;i < 100; i ++) 0];
selTest.time += selTest.run();
selTest.count += 1;

for(const test of tests)
test.mean = test.time / test.count;
test.status.textContent = `$test.name mean $test.mean.toFixed(3)ms over $test.count cycles.`;

if(!stop)

setTimeout(testing,100);
else
tests.sort((a,b) => a.mean - b.mean);
const slowest = tests[tests.length -1].mean;
var win = " 🐇 <span class='winner'>Fastest</span>";
let test;
for(test of tests)
test.status.textContent += (test.mean / slowest * 100).toFixed(1) + "%"
if( win )
test.status.innerHTML += win;
test.status.className = "champ";
win = undefined;


test.status.innerHTML += " 🐢 <span class='looser'>Slowest</span>"
test.status.className = "lost";


setTimeout(testing,100);

body 
font-family : arial;
font size : large;
text-align : center;

h4
font-size : small;

.winner
color : green;


.looser
color : red;

.champ
background : #CFC;
font-weight : 700;

transition: all 0.5s ease-out;

.lost
background : #FCC;
transition: all 0.5s ease-out;



<h3>Javascript Array.some V for...of V regExp</h3>
<h4>Click on the page to stop testing.</h4>
<div id="statusElementA"></div>
<div id="statusElementB"></div>
<div id="statusElementC"></div>








share|improve this answer













Performance




I have my code working as needed but am looking for way to improve / optimize it.




If you want to improve the performances there are a few things you can do.



Testing



The first thing is that you can run tests and see how code style and logic can effect performance. Javascript testing is a little tricky. You can not just run the functions. You need to make sure you are not being tricked by the optimiser



I have added a basic Javascript performance tester to the bottom to highlight the following points.



Slow iterators



The Array iteration functions such as Array.some are generally slower than writing a standard for, for of or while loop. The reason is because functions incur a lot of additional overhead each time they are call. They need their own memory, special structures to hold the current scope, and closure values. All this is added to the JavaScript heap and called the function's "context".



On top of that the actual function Array.some has to do some checks to make sure that the arguments you pass are correct and can be used. This all adds to the time to run the function.



For of loops are faster



Using a for...of loop avoids all that overhead and for this example is about 60% faster (on Chrome)



var triggerWords = ['hello there','world', 'hello world', 'how do I turn this on', 'general kenobi'];
for(const word of triggerWords )
if(inputVal.indexOf(word)
$("#showme).show(300);
return; // all done exit the key up event


$("#showme).hide(300);


Native power!



But the problem is still the iteration. Using JavaScript to check each string in turn is never going to utilize a modern CPU's true power. But there is a way to have the search done using pure native code.



RegExp will do the test in a fraction of the time.



Building the regular expression from array of string is expensive, so you would not use this method if the search string (triggerWords) changes each test. But if the the search is the same each time, you can build the regExp at the start and you get around a 1000% performance boost.



// create at start;
var triggerWords = ['hello there','world', 'hello world', 'how do I turn this on', 'general kenobi'];
const reg = new RegExp(triggerWords.join("|"),"gi")

// inside the key event
if(reg.test(inputVal))
$("#showme).show(300);
else
$("#showme).hide(300);



The cost of libraries



The easiest way to get a performance boost is to drop the libraries.



Without jQuery the code looks like.



const wordSearch = /hello there|world|hello world|how do I turn this on|general kenobi/gi;
inputTest.addEventListener("keyup", (event) =>
if( wordSearch.test(inputTest.value.replace(/[^a-z ]/gi,"")) )
showme.classList.remove('hide');
else
showme.classList.add('hide');

);


And add a hide class to the CSS.



 .hide display : none; 


The next snippet shows it all put together, copied from your fiddle (a page needing well over 1Mbyte of javascript to run) to a total of less than 1000bytes for all the code, css, and markup






const wordSearch = /hello there|world|hello world|how do I turn this on|general kenobi/gi;
inputTest.addEventListener("keyup", (event) =>
if( wordSearch.test(inputTest.value.replace(/[^a-z ]/gi,"")) )
showme.classList.remove('hide');
else
showme.classList.add('hide');

);

#showme
padding-top:15px;

.muted
padding-top:15px;
font-size:12px;
color:#ccc;

.hide
display : none;

<p>
Enter a word or phrase to search:
</p>
Search: <input id ="inputTest" type="text" placeholder="Word / Phrase">
<div id="showme" class="hide">
<iframe src="https://giphy.com/embed/Nx0rz3jtxtEre" width="240" height="120" frameBorder="0" class="giphy-embed" allowFullScreen></iframe>
</div>
<div class="muted">Indexed words / phrases:
<ul>
<li>hello there</li>
<li>world</li>
<li>hello</li>
<li>hello world</li>
<li>how do I turn this on</li>
<li>general kenobi</li>
</ul>
</div>





Example performance comparisons.



The snipped tests the 3 search methods Array.some, for..of and regExp



It uses the worst case scenario and runs the tests many 1000's of times. The test order is random to stop the optimizer slewing one method over another, and the result of each search are socked up by a global variable to stop the optimizer from just removing the inner loops completely



Let the test run until the mean times start to stabilize then click the page to compare the performance results.






/*===========================================================================
Set up test data.
One big array with

===========================================================================*/
const rand = (max) => Math.random() * max | 0;
const innerLoopCount = 1000;
var c = "aabbaa";
var b = "skjht kjhlvuh svrtgkj abcdef ghijklmn opqrst uvwxyz1 234567890 ";
var a = ;
for(i = 0; i < 10; i ++) a.push(b.substr(rand(b.length -10), rand(8) + 2)) ;
var reg = new RegExp(a.join("|"),"gi");
document.addEventListener("click",() => stop = true )
var stop = false;

var soak = 0; // this is to prevent optimiser removing test code. It soaks up entropy generated by the functions :P
function testA()
var i = 0, found;
const now = performance.now()
while(i++ < innerLoopCount)
var found = a.some(function(word)
return c.indexOf(word) > -1;
)

soak += found ? 1:0;

return performance.now() - now

function testB()
const now = performance.now()
var i = 0, found;
while(i++ < innerLoopCount)
found = false;
for(const word of a)
if(c.indexOf(word) > -1)
found = true;
break;


soak += found ? 1:0;

return performance.now() - now;

function testC()
const now = performance.now()
var i = 0, found;
while(i++ < innerLoopCount)

found = reg.test(c);
//for(const word of a)
// if(c.indexOf(word) > -1)
// found = true;
// break;
//
//
soak += found ? 1:0;

return performance.now() - now;



const tests = [
count : 0, time : 0, run : testA, status : statusElementA, name : " 'Array.some' : ",
count : 0, time : 0, run : testB, status : statusElementB, name : " 'for...of' : ",
count : 0, time : 0, run : testC, status : statusElementC, name : " 'regExp' : ",
];
function testing()
var testsCount = tests.length;

for(var i = 0;i < 100; i ++) 0];
selTest.time += selTest.run();
selTest.count += 1;

for(const test of tests)
test.mean = test.time / test.count;
test.status.textContent = `$test.name mean $test.mean.toFixed(3)ms over $test.count cycles.`;

if(!stop)

setTimeout(testing,100);
else
tests.sort((a,b) => a.mean - b.mean);
const slowest = tests[tests.length -1].mean;
var win = " 🐇 <span class='winner'>Fastest</span>";
let test;
for(test of tests)
test.status.textContent += (test.mean / slowest * 100).toFixed(1) + "%"
if( win )
test.status.innerHTML += win;
test.status.className = "champ";
win = undefined;


test.status.innerHTML += " 🐢 <span class='looser'>Slowest</span>"
test.status.className = "lost";


setTimeout(testing,100);

body 
font-family : arial;
font size : large;
text-align : center;

h4
font-size : small;

.winner
color : green;


.looser
color : red;

.champ
background : #CFC;
font-weight : 700;

transition: all 0.5s ease-out;

.lost
background : #FCC;
transition: all 0.5s ease-out;



<h3>Javascript Array.some V for...of V regExp</h3>
<h4>Click on the page to stop testing.</h4>
<div id="statusElementA"></div>
<div id="statusElementB"></div>
<div id="statusElementC"></div>








const wordSearch = /hello there|world|hello world|how do I turn this on|general kenobi/gi;
inputTest.addEventListener("keyup", (event) =>
if( wordSearch.test(inputTest.value.replace(/[^a-z ]/gi,"")) )
showme.classList.remove('hide');
else
showme.classList.add('hide');

);

#showme
padding-top:15px;

.muted
padding-top:15px;
font-size:12px;
color:#ccc;

.hide
display : none;

<p>
Enter a word or phrase to search:
</p>
Search: <input id ="inputTest" type="text" placeholder="Word / Phrase">
<div id="showme" class="hide">
<iframe src="https://giphy.com/embed/Nx0rz3jtxtEre" width="240" height="120" frameBorder="0" class="giphy-embed" allowFullScreen></iframe>
</div>
<div class="muted">Indexed words / phrases:
<ul>
<li>hello there</li>
<li>world</li>
<li>hello</li>
<li>hello world</li>
<li>how do I turn this on</li>
<li>general kenobi</li>
</ul>
</div>





const wordSearch = /hello there|world|hello world|how do I turn this on|general kenobi/gi;
inputTest.addEventListener("keyup", (event) =>
if( wordSearch.test(inputTest.value.replace(/[^a-z ]/gi,"")) )
showme.classList.remove('hide');
else
showme.classList.add('hide');

);

#showme
padding-top:15px;

.muted
padding-top:15px;
font-size:12px;
color:#ccc;

.hide
display : none;

<p>
Enter a word or phrase to search:
</p>
Search: <input id ="inputTest" type="text" placeholder="Word / Phrase">
<div id="showme" class="hide">
<iframe src="https://giphy.com/embed/Nx0rz3jtxtEre" width="240" height="120" frameBorder="0" class="giphy-embed" allowFullScreen></iframe>
</div>
<div class="muted">Indexed words / phrases:
<ul>
<li>hello there</li>
<li>world</li>
<li>hello</li>
<li>hello world</li>
<li>how do I turn this on</li>
<li>general kenobi</li>
</ul>
</div>





/*===========================================================================
Set up test data.
One big array with

===========================================================================*/
const rand = (max) => Math.random() * max | 0;
const innerLoopCount = 1000;
var c = "aabbaa";
var b = "skjht kjhlvuh svrtgkj abcdef ghijklmn opqrst uvwxyz1 234567890 ";
var a = ;
for(i = 0; i < 10; i ++) a.push(b.substr(rand(b.length -10), rand(8) + 2)) ;
var reg = new RegExp(a.join("|"),"gi");
document.addEventListener("click",() => stop = true )
var stop = false;

var soak = 0; // this is to prevent optimiser removing test code. It soaks up entropy generated by the functions :P
function testA()
var i = 0, found;
const now = performance.now()
while(i++ < innerLoopCount)
var found = a.some(function(word)
return c.indexOf(word) > -1;
)

soak += found ? 1:0;

return performance.now() - now

function testB()
const now = performance.now()
var i = 0, found;
while(i++ < innerLoopCount)
found = false;
for(const word of a)
if(c.indexOf(word) > -1)
found = true;
break;


soak += found ? 1:0;

return performance.now() - now;

function testC()
const now = performance.now()
var i = 0, found;
while(i++ < innerLoopCount)

found = reg.test(c);
//for(const word of a)
// if(c.indexOf(word) > -1)
// found = true;
// break;
//
//
soak += found ? 1:0;

return performance.now() - now;



const tests = [
count : 0, time : 0, run : testA, status : statusElementA, name : " 'Array.some' : ",
count : 0, time : 0, run : testB, status : statusElementB, name : " 'for...of' : ",
count : 0, time : 0, run : testC, status : statusElementC, name : " 'regExp' : ",
];
function testing()
var testsCount = tests.length;

for(var i = 0;i < 100; i ++) 0];
selTest.time += selTest.run();
selTest.count += 1;

for(const test of tests)
test.mean = test.time / test.count;
test.status.textContent = `$test.name mean $test.mean.toFixed(3)ms over $test.count cycles.`;

if(!stop)

setTimeout(testing,100);
else
tests.sort((a,b) => a.mean - b.mean);
const slowest = tests[tests.length -1].mean;
var win = " 🐇 <span class='winner'>Fastest</span>";
let test;
for(test of tests)
test.status.textContent += (test.mean / slowest * 100).toFixed(1) + "%"
if( win )
test.status.innerHTML += win;
test.status.className = "champ";
win = undefined;


test.status.innerHTML += " 🐢 <span class='looser'>Slowest</span>"
test.status.className = "lost";


setTimeout(testing,100);

body 
font-family : arial;
font size : large;
text-align : center;

h4
font-size : small;

.winner
color : green;


.looser
color : red;

.champ
background : #CFC;
font-weight : 700;

transition: all 0.5s ease-out;

.lost
background : #FCC;
transition: all 0.5s ease-out;



<h3>Javascript Array.some V for...of V regExp</h3>
<h4>Click on the page to stop testing.</h4>
<div id="statusElementA"></div>
<div id="statusElementB"></div>
<div id="statusElementC"></div>





/*===========================================================================
Set up test data.
One big array with

===========================================================================*/
const rand = (max) => Math.random() * max | 0;
const innerLoopCount = 1000;
var c = "aabbaa";
var b = "skjht kjhlvuh svrtgkj abcdef ghijklmn opqrst uvwxyz1 234567890 ";
var a = ;
for(i = 0; i < 10; i ++) a.push(b.substr(rand(b.length -10), rand(8) + 2)) ;
var reg = new RegExp(a.join("|"),"gi");
document.addEventListener("click",() => stop = true )
var stop = false;

var soak = 0; // this is to prevent optimiser removing test code. It soaks up entropy generated by the functions :P
function testA()
var i = 0, found;
const now = performance.now()
while(i++ < innerLoopCount)
var found = a.some(function(word)
return c.indexOf(word) > -1;
)

soak += found ? 1:0;

return performance.now() - now

function testB()
const now = performance.now()
var i = 0, found;
while(i++ < innerLoopCount)
found = false;
for(const word of a)
if(c.indexOf(word) > -1)
found = true;
break;


soak += found ? 1:0;

return performance.now() - now;

function testC()
const now = performance.now()
var i = 0, found;
while(i++ < innerLoopCount)

found = reg.test(c);
//for(const word of a)
// if(c.indexOf(word) > -1)
// found = true;
// break;
//
//
soak += found ? 1:0;

return performance.now() - now;



const tests = [
count : 0, time : 0, run : testA, status : statusElementA, name : " 'Array.some' : ",
count : 0, time : 0, run : testB, status : statusElementB, name : " 'for...of' : ",
count : 0, time : 0, run : testC, status : statusElementC, name : " 'regExp' : ",
];
function testing()
var testsCount = tests.length;

for(var i = 0;i < 100; i ++) 0];
selTest.time += selTest.run();
selTest.count += 1;

for(const test of tests)
test.mean = test.time / test.count;
test.status.textContent = `$test.name mean $test.mean.toFixed(3)ms over $test.count cycles.`;

if(!stop)

setTimeout(testing,100);
else
tests.sort((a,b) => a.mean - b.mean);
const slowest = tests[tests.length -1].mean;
var win = " 🐇 <span class='winner'>Fastest</span>";
let test;
for(test of tests)
test.status.textContent += (test.mean / slowest * 100).toFixed(1) + "%"
if( win )
test.status.innerHTML += win;
test.status.className = "champ";
win = undefined;


test.status.innerHTML += " 🐢 <span class='looser'>Slowest</span>"
test.status.className = "lost";


setTimeout(testing,100);

body 
font-family : arial;
font size : large;
text-align : center;

h4
font-size : small;

.winner
color : green;


.looser
color : red;

.champ
background : #CFC;
font-weight : 700;

transition: all 0.5s ease-out;

.lost
background : #FCC;
transition: all 0.5s ease-out;



<h3>Javascript Array.some V for...of V regExp</h3>
<h4>Click on the page to stop testing.</h4>
<div id="statusElementA"></div>
<div id="statusElementB"></div>
<div id="statusElementC"></div>






share|improve this answer













share|improve this answer



share|improve this answer











answered Apr 4 at 0:29









Blindman67

5,3611320




5,3611320











  • The regex should not have the global flag, since subsequent calls to .test will be wrong. Documentation
    – Kruga
    Apr 4 at 14:19










  • This is a crazy amount of info! I love it! Thank you so much for helping me understand.
    – Ardz
    Apr 4 at 14:34
















  • The regex should not have the global flag, since subsequent calls to .test will be wrong. Documentation
    – Kruga
    Apr 4 at 14:19










  • This is a crazy amount of info! I love it! Thank you so much for helping me understand.
    – Ardz
    Apr 4 at 14:34















The regex should not have the global flag, since subsequent calls to .test will be wrong. Documentation
– Kruga
Apr 4 at 14:19




The regex should not have the global flag, since subsequent calls to .test will be wrong. Documentation
– Kruga
Apr 4 at 14:19












This is a crazy amount of info! I love it! Thank you so much for helping me understand.
– Ardz
Apr 4 at 14:34




This is a crazy amount of info! I love it! Thank you so much for helping me understand.
– Ardz
Apr 4 at 14:34












 

draft saved


draft discarded


























 


draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f191175%2ftriggering-based-on-words-or-phrases-entered-in-a-text-box%23new-answer', 'question_page');

);

Post as a guest













































































Popular posts from this blog

Chat program with C++ and SFML

Function to Return a JSON Like Objects Using VBA Collections and Arrays

Will my employers contract hold up in court?