In college, I did a bunch of Project Euler problems (in Java) to practice for tests and interviews. A few weeks ago, I thought it would be fun to attempt some of them in JavaScript.
Past me had saved my solutions to GitHub, and I just now looked at them for the first time in years. And wow. Talk about embarrassing.
Or, to frame it more positively, Iâve actually gotten better at coding after graduating!
For example, hereâs the first problem:
Find the sum of all the multiples of 3 or 5 below 1000.
Pretty simple, right?
function sumOfAllMultiples() { var sum = 0; for (var i = 0; i < 1000; i++) { if (i % 3 === 0 || i % 5 === 0) { sum += i; } } return sum; }
I checked out my old solution, expecting more or less the same thing but in Java. Cue facepalm.
public class Problem1 { public static void main(String [] args) { int sum3 = 0; int sum5 = 0; int sum15 = 0; for (int i = 3; i < 1000; i += 3) { sum3 += i; } for (int i = 5; i < 1000; i += 5) { sum5 += i; } for (int i = 15; i < 1000; i += 15) { sum15 += i; } System.out.print(sum3 + sum5 - sum15); } }
Yeah, I donât know.
It gets better (or worse) when I look at my old solution to the second problem:
By considering the terms in the Fibonacci sequence whose values do not exceed four million, find the sum of the even-valued terms.
public class Problem2 { public static void main(String[] args) { int sum = 0; for (int index = 1; fibonacci(index) < 4000000; index++) { if (fibonacci(index) % 2 == 0) { sum += fibonacci(index); } } System.out.print(sum); } // Find the nth Fibonacci term. public static int fibonacci(int n) { if (n == 1) return 1; if (n == 2) return 2; return (fibonacci(n - 1) + (fibonacci(n - 2))); } }
I used a recursive solution to find the nth Fibonacci number, which isnât too surprising since Iâm pretty sure I had just learned about recursion at that time. But then I called that recursive method three times in that for loop?
Hereâs my iterative JavaScript solution:
function evenFib() { var MAX = 4000000, first = 1, second = 2, sum = 2, temp; while (first + second < MAX) { temp = first; first = second; second += temp; if (second % 2 === 0) { sum += second; } } return sum; }
Anya is live and ready to show you everything. Watch her strip, dance, and perform exclusive shows just for you. Interact in real-time and make your fantasies come true.
â Live Streamingâ Interactive Chatâ Private Showsâ HD Qualityâ Free Actions
Free to watch ⢠No registration required ⢠HD streaming
Clarity, a conference about style guides and design systems, was held in San Francisco on March 31 and April 1. I decided to go as soon as I saw the impressive speaker list, and now I can say Iâm really glad I went.
Videos of the talks will be available in six months, but thatâs kind of a long time so Iâm posting all my notes here.
The conference was held at the Alamo Drafthouse in the Mission. The chairs were super comfortable and the food was excellent.
Swag overview: postcards, pins, stickers, notebooks, a pencil, and a bag.
The entire conference was put together by Jina. (Thank you, Jina!) The emcee was Chris Coyier of CSS-Tricks and CodePen. Susan was the official sketchnote artist and you can see her work here.
Now onto the fun stuff! Hereâs a list of links to each talk, because otherwise this post would be massive.
Day One
The Thing Is Design Systems. The Time Is Now. (Brad Frost)
Building empowering style guides with practical research (Isaak Hayes & Donna Chan)
Beyond the Toolkit: Spreading a System Across People & Products (Nathan Curtis)
Code Patterns for Pattern-Making (Miriam Suzanne)
Crawl, Walk, Run â the Evolution of a Design System (Stephanie Rewis & Brandon Ferrua)
Being Human, Being Slack (Anna Pickard)
Day Two
Communicating Animation (Rachel Nabors)
Baking Accessibility In (Cordelia McGee-Tubb)
Living Systems: Brand in the context of peoples lives. (Jeremy Perez-Cruz)
Deconstructing Web Systems; or, A Pattern Language for Web Development (Claudina Sarahe)
Turning the ship: Living design systems in the federal government (Maya Benari)
Keynote: Designing for Earthlings and Astronauts (Richard Danne)
Keynote: âDesigning for Earthlings and Astronautsâ by Richard Danne
Richard Danne is an accomplished designer who worked on a graphics standards manual for NASA in the 1970s. According to Jina, he basically invented style guides. There was a Kickstarter for a reissue of this manual (go watch the video there), and you can still buy a copy here.
No notes for this one, just some high quality (not really) pictures that I took!
âTurning the ship: Living design systems in the federal governmentâ by Maya Benari
Note: Iâve been following 18F (where Maya is a designer and front-end developer) ever since they came out with the U.S. Web Design Standards. Maya touched on a lot of things in this post.
$86 billion a year is spent on federal IT projects
94% are over budget/behind schedule
40% are scrapped and never see the light of day
Why?
Silos
Waterfall
Bureaucracy
Outdated regulations
They looked to GOV.UK for inspiration
âBe consistent, not uniformâ (GOV.UK design principles)
18F pitched the style guide idea and got 4 months to make an MVP
First they talked to people who work for USDS
Flexible design
A consistent look and feel with common design elements will feel familiar, trustworthy, and secure
What components are important?
Brought in various departments and did an inventory of websites
They tested typography pairings on actual government websites
Settled on a font, but noted that itâs not required, so agencies can retain their brand identity if they want
3 ways to use the standards
Our design and our code
Our design and different code
Different design and our code
Flexible code
Just HTML, CSS, and JS
Sass preprocessor + Bourbon and Neat
Component-based design
Modified BEM syntax
For a healthy open source communityâŚ
Respond to GitHub issues within 24 hours
Respond to pull requests within 48 hours
You donât have to have the answers, just acknowledge them
âDeconstructing Web Systems; or, A Pattern Language for Web Developmentâ by Claudina Sarahe
Note: Claudinaâs talk was inspired by Christopher Alexanderâs A Pattern Language.
What is a pattern language?
A method of describing good design practices within a field of expertise
Patterns are not dogma; they can change and adapt
Anatomy of a pattern
Name
Context
Problem
Solution(s)
Related patterns
Example
Name: naming
Context: a way to identify
Problem: we need to identify things so everyone knows what weâre talking about
Solution: work with stakeholders to establish a name
Related patterns: documentation
Why do we need a pattern language for front-end development?
The web is a complex system with moving parts
A pattern language for front-end web systems (four types)
I. Global patterns
Community guidelines
Temporary autonomous zones (meetups/conferences)
Independent disciplines
Web guidelines (W3C)
Open borders
Accessibility
II. Process patterns
Purpose
Planning/management
Code reviews
Cross functional teams
Single origin of truth
Documentation
Naming
Design systems
III. Workspace patterns
Editors
CLI
Syntax highlighting
Shortcuts
git/GitHub
Version and dependency management
Configuration/settings
IV. Project patterns
Build tools
Bundling dependencies
Directory structure
Linters
Composable
HTML templating
CSS methodologies
JS
Content strategy
Shareable data
Identifiers
At Casper, they created something called Ando that uses many of these patterns
Open borders = working with people across different disciplines
Problem: provide a way for everyone to work on the same codebase and contribute their skills
Solution: use a system that has minimal dependencies
Static, no DB, no migrations, back to basics
Related: cross functional teams, build tools
Documentation = a way to record decisions
Problem: code is not self-documenting. Decisions need to be captured. Captured decisions need to be easily referenced by people who did not write the doc
Solution: use community-vetted code documentation solutions. Pick a place to store documentation
SassDoc
JSDoc
HTML templating = a way to create sound structures, a way to componentize
Problem: HTML is verbose and at scale it becomes difficult to maintain
Anya is live and ready to show you everything. Watch her strip, dance, and perform exclusive shows just for you. Interact in real-time and make your fantasies come true.
â Live Streamingâ Interactive Chatâ Private Showsâ HD Qualityâ Free Actions
Free to watch ⢠No registration required ⢠HD streaming
âLiving Systems: Brand in the context of peoples lives.â by Jeremy Perez-Cruz
Note: Jeremyâs talk was more abstract, so it was difficult to take notes. If youâre interested in branding and brand systems, I would recommend watching this talk when the video comes out.
What is brand?
A productâs attributes
Intangible
A personâs gut feeling about a product or organization
Gut = emotional
Magical
Someone who develops a brand system = psychologist, designer, magician
âExperience is the brand and experiences live in peopleâ
âBaking Accessibility Inâ by Cordelia McGee-Tubb
Note: Cordeliaâs hand drawn slides were delightful!
Whatâs accessibility?
Making products, services, and spaces that everyone can use and enjoy, regardless of their abilities
Creating flexible systems that consider the experiences of people with disabilities from the very start, not just through tacked-on accommodations
The metaphor: doing accessibility afterwards is like making muffins, sticking blueberries into the muffins after theyâve been baked, and calling them blueberry muffins
Common accessible code techniques
Use semantic HTML
Use h1 for headings, not a span that is styled to look like a heading
This is for screen readers!
Use the button tag for buttons!
Input fields: use visible, explicit labels
Current trend is to put the label inside the input field as a placeholder
This is bad because of low contrast, and once you start typing it goes away
Also need to associate label with form field using for
Give ALL images alt text
If the image is redundant (example: home icon next to home label), use empty alt text or aria-hidden=âtrueâ for SVGs
decorative images: use discretion, often empty alt tags
ARIA = accessible rich internet applications = communicate elementâs role, state, and properties to assistive technology
âCrawl, Walk, Run â the Evolution of a Design Systemâ by Stephanie Rewis & Brandon Ferrua
Note: Stephanie and Brandon are developers at Salesforce. The new Salesforce Lightning Design System was referenced a million times at Clarity, so be sure to take a look.
Salesforce Lightning Design System is a complete overhaul of the UI
Next generation of living style guides
Learning to crawl
Design audit and inventory of all components in designerâs comps
Standardized values became design tokens and were abstracted
Font sizes, color, etc.
theo: a tool to turn tokens stored in JSON to Sass or whatever
Break components down to their smallest patterns and objects
Clarity and understandability in class names
BEM
Keep specificity low
Naming is hard!
Learning to walk
Enterprise apps have unique traits
They demand content and data-rich interfaces
Lack vertical rhythm
Heading levels may vary and our components should be agnostic
So they equalized all headings to a base font size of 1rem
Then made utility classes to get the heading styles they needed
Baked accessibility in
Semantics matter
ARIA roles
rem unit sizing
Play well with others
Namespacing! They put slds in front of every class
Learning to run
How do we lower the bar for adoption? Very important for a company as large as Salesforce
How do we maintain consistency across a massive organization?
How do we keep our design system agnostic? Internal and external developers
One thing they knewâŚminimize dependencies
You donât know what you donât know
What makes up your ecosystem?
Who are your customers?
Try to understand your potential footprints
Did not include JavaScript
At Salesforce, developers use React, Angular, jQuery, etc. so leaving out JS makes it easier for any stack to use the design system
Design team has to support 3 versions simultaneously
Production release, previous production release, future release
As a developer
How to keep track of changes?
When is right time to deprecate?
As a consumer
How do I know what is deprecated?
What kind of guidance do I get?
How long do I have to upgrade?
Solution: sass-deprecate
@include deprecate('3.0.0', 'some stuff here')
Donât be afraid to deprecate! Or youâll end up with code bloat
Anya is live and ready to show you everything. Watch her strip, dance, and perform exclusive shows just for you. Interact in real-time and make your fantasies come true.
â Live Streamingâ Interactive Chatâ Private Showsâ HD Qualityâ Free Actions
Free to watch ⢠No registration required ⢠HD streaming
âCode Patterns for Pattern-Makingâ by Miriam Suzanne
Note: my notes for this one were super messy (I blame lunch)âŚbut luckily Miriam posted her slides here! Now prepare for a word dump.
Style guides â> maintainable patterns
Style guides will be different depending on what kind of team youâre on
Quality architecture = patterns in code
Documentation isnât enough
Patterns combine languages (HTML/CSS/JS)
Maintenance must be integrated
Process, toolkit, visibility, simplicity
Basics of web architecture
Separation of concerns (data, logic, structure, presentation)
Specificity is your guide (prefer the shallow end)
Donât repeat yourself but donât stretch for patterns
âThese elements share a border styleâ is not enough for a pattern but âthese elements share a purpose that is represented by a border styleâ is good
Naming conventions consistent across entire team
Use separate JS hooks like js-something instead of a random CSS class
No right answer but no answer at all is wrong
In Sass: extends works well when representing is-a relationships
Look up ITCSS
Sass maps are cool!
Better than using variables when defining a color palette, for example
âBeyond the Toolkit: Spreading a System Across People & Productsâ by Nathan Curtis
Note: Nathan is the author of a book on modular web design. The lego metaphor in this book was referenced by at least one other speaker at this conference.
Color, type, and iconography set the tone for your design
Space, motion, imagery, logo, and writing tone are also part of the design language
How do you start creating a design system for your organization?
The Component Cut-Up Workshop, similar to Bradâs interface inventory
Picking Parts, Products & People, another activity
Put design concepts on a wall with a before and after to see themes emerge
Once you know what components and parts to work onâŚ
Framing a Design Systemâs Roadmap
Take what we could do and decide on what we will do by when
When you get asked to create a design system for a large organization (sorry for the question marks; I either didnât write it down correctly or forgot to clarify it for myself)
Choose flagships thatâll commit to you too
Choose between 3 and 5 (?)
Use their launch dates or make your own
Whatâs your get (?)
Avoid distractions
Like the home page: build one-offs because itâs always going to be changing and controlled by people you canât argue with
Not everything needs to go into the system
Hook system access via code theyâll use first
Radiate influence from web apps
Where the important metrics are
Demo value across the journey
More helpful articles
Stitching Prototypes
Team Models for Scaling a Design System
The Salesforce Team Model for Scaling a Design System
Also a video: Leah Buley: The Modern UX Organization
When making decisions, use The Sliding Scale of Giving a Fuck
âA design system isnât a project. Itâs a product, serving products.â
âThe Thing Is Design Systems. The Time Is Now.â by Brad Frost
Note: I read Bradâs post on atomic design awhile back, when I was just starting my current project. We are actually using atomic design in said project, so it was pretty cool to hear him speak on the topic in person.
Started off with real-life examples from Getty Images, Canon, eBay, and United Airlines: all of these websites have very incongruent experiences depending on what page/section/locale you are in
For example, United has 13 different button styles on one page
We now have more products/services to build and more devices/screen sizes/languages/etc. to consider than ever
Six flavors of style guides (with links to examples)
Brand identity
Design language
Voice and tone
Writing
Code
Pattern libraries
Checkout styleguides.io for more
Potential issues of Bootstrap-like frameworks
One size fits all
Lookalike
Bloat
Compatibility
Quote from Dave Rupert: âResponsive deliverables should look a lot like fully-functioning Twitter Bootstrap-style systems custom tailored for your clientsâ needsâ (more context here)
Benefits of pattern libraries
Promotes UI consistency and cohesion = more conversions and $$$
Users are already familiar with the experience (what a button looks like) so they can get through the process faster
Faster production = more features faster
Shared vocabulary = more time collaborating, less in meetings
Easier to test = more responsive, performant, accessible experiences
Useful reference = an essential resource and hub for best practices
Future-friendly foundation = modify, extend, improve upon over time
How to convince your boss/client (âmake them cryâ)
Interface inventory = an exercise where you go through every web page and find every type of button, form input, icon, block, etc.
Should point out inconsistencies
Also establishes scope of work
Groundwork for future pattern library
Atomic design
Atoms
Buttons, labels, input fields
Molecules
Button + label + input field = search molecule
Organisms
Search molecule + nav molecule = header organism
Templates
Combine organisms to make a content skeleton
Pages
Put real content into a template
You should also test variations here
Establish direction
Style tiles, element collages â> get an idea of what client wants
Developer plays role of prep chef â> do upfront work by starting on the pattern library (code from day one of the project)
Check out Pattern Lab
Build up fidelity
Danger: as soon as pattern library stops reflecting the website, it becomes obsolete and fades away
Now for some clarity on the difference between a style guide and a design system
âA style guide is an artifact of the design process. A design system is a living, funded product with a roadmap and backlog, serving the ecosystemâ
A great looking style guide reflects an organizationâs commitment to making a great design system
Maintainable design system = the holy grail
Lonely Planet
Yelp
U.S. Web Design Standards
When youâre finished changing, youâre finished
this has always been a confusing JavaScript keyword to me. Thanks to the You Donât Know JavaScript series by Kyle Simpson, itâs become slightly less confusing.
This post will mostly be notes I took from the second chapter of the third book in the series, this & Object Prototypes.
(My only major gripe was that all the code examples used foo, bar, and baz. I feel that meaningless functions make it hard to understand how you would use this in real life code. Hence, I tried to come up with my own examples using more meaningful functions, but unsurprisingly, it was rather difficult.)
First, the author makes the point that this has nothing to do with scope:
To be clear, this does not, in any way, refer to a functionâs lexical scope.
So what does this have to do with?
this is not an author-time binding but a runtime binding. It is contextual based on the conditions of the functionâs invocation. this binding has nothing to do with where a function is declared, but has instead everything to do with the manner in which the function is called.
You have to examine the call-site and the call-stack and consult the following four rules to figure out what this refers to.
Rule One: Default Binding
most common case
standalone function invocation
default catch-all rule
applies when a function is called with a plain, undecorated function reference
var counter = 0; function incrementCounter() { this.counter++; } incrementCounter(); console.log(counter); // 1 - got incremented
Note: if the function is in strict mode, the global object is not eligible for the default binding, so this.counter in the above code would throw an error.
Rule Two: Implicit Binding
consider whether the call-site has a context object (i.e., owning/containing object)
var counter = 0; function incrementCounter() { this.counter++; } var object = { counter: 10, incrementCounter: incrementCounter, }; object.incrementCounter(); console.log(counter); // 0 - did not get incremented console.log(object.counter); // 11 - got incremented
But wait! Thereâs more. In some situations, the implicit binding can be lost.
var counter = 0; function incrementCounter() { this.counter++; } var object = { counter: 10, incrementCounter: incrementCounter, }; var copyOfIncrementCounter = object.incrementCounter; copyOfIncrementCounter(); console.log(counter); // 1 - got incremented console.log(object.counter); // 10 - did not get incremented
Here, copyOfIncrementCounter looks like itâs a reference to object.incrementCounter, but itâs actually a reference to the global incrementCounter. So we fall back to the default binding rule and the global counter variable gets incremented.
Another example of this situation:
var counter = 0; function incrementCounter() { this.counter++; } var object = { counter: 10, incrementCounter: incrementCounter }; function doSomething(callback) { callback(); } doSomething(object.incrementCounter); console.log(counter); // 1 - got incremented console.log(object.counter); // 10 - did not get incremented
Why?
Parameter passing is just an implicit assignment, and since weâre passing a function, itâs an implicit reference assignment, so the end result is the same as the previous snippet.
Rule Three: Explicit Binding
force a function call to use a particular object as this
use call and apply, which are available to all functions
call and apply are methods that take an object to use for this as their first argument
call and apply are identical with respect to this; we wonât worry about their differences for now
var counter = 0; function incrementCounter() { this.counter++; } var object = { counter: 10 }; incrementCounter.call(object); console.log(counter); // 0 - did not get incremented console.log(object.counter); // 11 - got incremented
Note that if a primitive is passed instead of an object, it gets wrapped in its object-form (String, Boolean, or Number). This is called boxing.
Unfortunately, explicit binding alone still doesnât offer any solution to the issue mentioned previously, of a function âlosingâ its intended this bindingâŚ
âŚbut hard binding, a variation pattern around explicit binding, will work.
var counter = 0; function incrementCounter() { this.counter++; } var object = { counter: 10 }; var incrementCounterWrapper = function() { incrementCounter.call(object); } incrementCounterWrapper(); console.log(counter); // 0 - did not get incremented console.log(object.counter); // 11 - got incremented incrementCounterWrapper.call(window); // will it use the global counter? nope! console.log(counter); // 0 - did not get incremented console.log(object.counter); // 12 - got incremented
Whatâs happening here is incrementCounterWrapper internally calls incrementCounter with object as this. No matter how incrementCounterWrapper is called, it will always manually invoke incrementCounter with object.
Since hard binding is such a common pattern, itâs provided with a built-in utility as of ES5, Function.prototype.bind
bind(..) returns a new function that is hardcoded to call the original function with the this context set as you specified.
var counter = 0; function incrementCounter() { this.counter++; } var object = { counter: 10 }; var incrementCounterWrapper = incrementCounter.bind(object); incrementCounterWrapper(); console.log(counter); // 0 - did not get incremented console.log(object.counter); // 11 - got incremented
Rule Four: new Binding
Ah, the new keyword. Another confusing one that I often see but am never sure when to use myself.
JavaScript has a new operator, and the code pattern to use it looks basically identical to what we see in those class-oriented languages; most developers assume that JavaScriptâs mechanism is doing something similar. However, there really is no connection to class-oriented functionality implied by new usage in JS.
Okay, what else?
First, letâs re-define what a âconstructorâ in JavaScript is. In JS, constructors are just functions that happen to be called with the new operator in front of them. They are not attached to classes, nor are they instantiating a class. They are not even special types of functions. Theyâre just regular functions that are, in essence, hijacked by the use of new in their invocation.
How is new relevant to this, then?
Well, when a function is invoked with new, a brand new object is created. That object is set as the this binding for that function call. And that function call will return the new object (unless the function returns its own alternate object).
var counter = 0; function incrementCounter(counter) { this.counter = counter; this.counter++; } var newIncrementCounter = new incrementCounter(10); console.log(counter); // 0 - did not get incremented console.log(newIncrementCounter.counter); // 11 - got incremented
Rule Precedence
new binding
explicit binding
implicit binding
default binding
More detailed:
Is the function called with new (new binding)? If so, this is the newly constructed object.
var bar = new foo()
Is the function called with call or apply (explicit binding), even hidden inside a bind hard binding? If so, this is the explicitly specified object.
var bar = foo.call( obj2 )
Is the function called with a context (implicit binding), otherwise known as an owning or containing object? If so, this is that context object.
var bar = obj1.foo()
Otherwise, default the this (default binding). If in strict mode, pick undefined, otherwise pick the global object.
var bar = foo()
For a discussion on why this is the case, read the original material here.
(And just read the whole thing while youâre at it.)
Anya is live and ready to show you everything. Watch her strip, dance, and perform exclusive shows just for you. Interact in real-time and make your fantasies come true.
â Live Streamingâ Interactive Chatâ Private Showsâ HD Qualityâ Free Actions
Free to watch ⢠No registration required ⢠HD streaming
I was looking up JavaScript closures this morning and came across this terrific Stack Overflow answer (the first one with all the examples).
But, one of the examples (#5) confused me so I decided to take a closer look at it. Hereâs the code, taken directly from SO with a little bit of formatting:
function buildList(list) { var result = []; for (var i = 0; i < list.length; i++) { var item = 'item' + i; result.push(function() { alert(item + ' ' + list[i]) }); } return result; } function testList() { var fnlist = buildList([1,2,3]); // Using j only to help prevent confusion -- could use i. for (var j = 0; j < fnlist.length; j++) { fnlist[j](); } }
When I ran the code in the console, calling testList(), I got 'item2 undefined' in an alert three times. But according to the explanation, I should have seen 'item3 undefined'.
Note that when you run the example, 'item3 undefined' is alerted three times! This is because just like previous examples, there is only one closure for the local variables for buildList. When the anonymous functions are called on the line fnlist[j](); they all use the same single closure, and they use the current value for i and item within that one closure (where i has a value of 3 because the loop had completed, and item has a value of 'item3').
Unless thereâs something wrong with my browser, I donât think thatâs completely correct. Letâs look at the buildList function in depth.
function buildList(list) {
Passing in a variable called list to the function.
var result = [];
Just initiating an empty array.
for (var i = 0; i < list.length; i++) {
Here we have a standard for loop. But in JavaScript, you have to remember that the variable i gets hoisted to the top of the current scope (which in this case is the scope of the buildList function). So once this loop is done, weâll still have access to i.
var item = 'item' + i;
Creating a string using the word âitemâ and the current value of i. I think this is where my confusion is coming from. More on that later.
Hereâs where the fun closure stuff happens. Weâre creating new functions and pushing them onto the result array. These functions are special because they have access to the enclosing functionâs variables, like list and i. And they will still have access after buildList is done runningâthe variables are saved in a closure.
} return result; }
The array of functions is returned.
Calling buildList([1, 2, 3]) and then each of the functions in result always yields 'item2 undefined'. The undefined part makes sense, because at the end of the for loop, i increments one last time to 3. So i = 3 at the point in time when we call the functions in result. Since the input array [1, 2, 3] only has three elements, trying to access the fourth element at index 3 results in undefined.
As for why Iâm seeing 'item2' and not 'item3', I think thatâs because the item string is set in this line:
var item = 'item' + i;
Since the last time the code inside the loop is run is when i = 2, the item string is set to 'item2', not 'item' + i. In other words, the i is evaluated at that point in time, and not later, when i = 3.
I hope this is correct! I would comment on the SO answer, but I donât have that privilege yet.