What Is the Cost of '$(This)'

What is the cost of '$(this)'?

In the jQuery tag info this warning appears:

The jQuery function $() is expensive. Calling it repeatedly is extremely inefficient.

Well... that is true only for string selectors, which get parsed with regex to find out what they are:

quickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/

Then if the string is a selector (other than id), jQuery traverses the DOM to find a match with its expensive find function:

} else if ( !context || context.jquery ) {
return ( context || rootjQuery ).find( selector );
}

So yes it's expensive, but that is only true for selectors!

If we pass a DOMElement, the only action jQuery does is saving the DOMElement parameter as the context of the newly created jQuery object and setting the length of the context to 1:

// Handle $(DOMElement)
if ( selector.nodeType ) {
this.context = this[0] = selector; // Selector here is a DOMElement
this.length = 1;
return this;
}

I did some tests with jsPerf, and I found that indeed caching the jQuery object has only a little effect:

Bar chart, described below

In Chrome it's only 7% slower. (In IE it's a little bit more significant: 12%.)

Update variable to show total cost

You cannot perform math on string. In the switch case, you were setting like cost = "$10.00". You were then doing cost *= 0.8 which would result in NaN, since you were multiplying a string.

You can set cost to a Number, perform all operations and add "$" and ".00" after it.

It will be costElement.value and not just costElement = ... (also, it was out of if condition, which resulted in costElement being undefined.)

(Note: I have changed input[type="submit"] to input[type="button"] in HTML for demo purposes, to prevent submission.)

'use strict';

function calculate() {

//declares a variable named 'cost' to store the total cost:
var cost;

// lookup the type and years input elements with DOM getElementById()
var type = document.getElementById("type");
var years = document.getElementById("years");

// Convert the year to a number()), i'm not sure if this is working or not
if (years && years.value) {
years = parseInt(years.value, 10);
}

// Check for valid data:
if (type && type.value && years && (years > 0)) {

// Add a switch statement to determine the base cost using the value of "type"
switch (type.value) {
case 'basic':
cost = 10;
break;
case 'premium':
cost = 15;
break;
case 'gold':
cost = 20;
break;
case 'platinum':
cost = 25;
break;
}

// Update cost by multiplying number of years
cost = cost * years;
// Discount multiple years
if (years > 1) {
cost *= 0.80; // 80%
}
cost = "$" + cost + ".00";
let costElement = document.getElementById('cost');

//update the value property of 'costElement' to the calculated cost
costElement.value = cost; //You can also use type.value + cost
}
// Return false to prevent submission:
return false;
}

function init() {
document.getElementById('submit').onclick = calculate; //replace with document.getElementById('theForm').onsubmit = calculate;
}
window.onload = init;
<!doctype html>
<html lang="en">

<head>
<meta charset="utf-8">
<title>Membership Form</title>
<link rel="stylesheet" href="css/form.css">
</head>

<body>
<form action="" method="post" id="theForm">
<script src="js/membership.js"></script>
<fieldset>
<legend>Create Your Membership</legend>
<p>Complete this form to calculate your membership. There's a 20% discount if you enroll for more than one year!</p>
<div><label for="type">Type</label>
<select name="type" id="type" required>
<option value="basic">Basic - $10.00</option>
<option value="premium">Premium - $15.00</option>
<option value="gold">Gold - $20.00</option>
<option value="platinum">Platinum - $25.00</option>
</select>
</div>
<div><label for="years">Years</label><input type="number" name="years" id="years" min="1" required></div>
<div><label for="cost">Cost</label><input type="text" name="cost" id="cost" disabled></div>
<input type="button" value="Calculate" id="submit">

</fieldset>

</form>

</body>

</html>

Update the value property of 'costElement' to the calculated cost

I'm not sure what you're trying to accomplish with this line:

var years = document.getElementById('years');

...followed by this line?

var years = parseInt("1996");

First of all, why is this a calendar year instead of a number of years (surely you aren't pricing a membership that will last for nearly two millennia)?

Anyway, this line simply sticks the value "1996" into the variable years, it does not update the element with an id of years to 1996. Same problem here:

var costElement = type + years;

The variable costElement has already be declared, and this line replaces its previous value (which in the element in the HTML document) with type + years. And type + years doesn't make a lot of sense, since you want to multiply, not add.

Then you got this mysterious bit:

        // Discount multiple years:
if (years > 1) {
cost *= .20; // 20%
}

cost has never been defined, so what's cost becoming 20% of? Besides, I'm pretty sure you want to take 20% off the final price, not make the final price 20% of the original cost -- because that would be an 80% discount!

This should be more like:

        var cost = 1;
// Discount multiple years:
if (years > 1) {
cost = 0.80; // 20% off
}

Further, you need some way to turn the value ('basic', 'premium', etc.) into a numeric value for calculation. You could just add to your switch statement for that, but you already have text, and stripping off the leading $ will do to get a number, so you can do this:

var price = parseFloat(text.substr(1));

Now you can get the total cost like this (notice you don't need to, and shouldn't, put var in front again):

cost *= price * years;

Then, with some appropriate formatting, you can display value this way:

costElement.value = '$' + cost.toFixed(2);

I don't know if that fixes everything, and there are also better ways to display a value than using a disabled input field (like setting the innerText property of a <span>), but hopefully this can get you on the right track.

Cost of calling a function or not in Javascript

It Just Doesn't Matter (although the first method avoids some work so it should faster, but by an amount which is probably less than statistical noise).

What really matters is which method best represents the logic. Rule of thumb is that every statement in a function should be on about the same level of abstraction. Is the conditional expression more or less abstract than the function call?



Related Topics



Leave a reply



Submit