> All in One 586: September 2020

Ads

Wednesday, September 30, 2020

Clear today!



With a high of F and a low of 38F. Currently, it's 50F and Clear outside.

Current wind speeds: 6 from the Northeast

Pollen: 2

Sunrise: September 30, 2020 at 06:47PM

Sunset: October 1, 2020 at 06:34AM

UV index: 0

Humidity: 47%

via https://ift.tt/2livfew

October 1, 2020 at 10:00AM

Amelia's Farm Fresh Cookies

I told her I'd take her address off the packaging if she'd stop submitting anonymous food safety complaints about my bakery to the health department, but she sent me a note that said NO DEAL along with an extra large batch of cookies.

from xkcd.com https://xkcd.com/2366/
via IFTTT

The new Google TV brings streaming apps, live TV and search into a single interface

Not to be confused with the smart TV platform of the same name (2010-2014, RIP) or the Android TV platform it’s built on top of, Google has just taken the wraps off the new Google TV. The name refers to the interface for the new, aptly titled Chromecast with Google TV, combining streaming services, live TV (via YouTube TV) and various other Google offerings into a single, streamlined UI.

In that sense, the new Google TV is similar to offerings from Apple and Amazon, serving as a kind of one-stop-shop to replace cable TV outright. It works with most of the top streaming offerings, including Disney+, france.tv, HBO Max, Netflix, Rakuten Viki and, of course, YouTube, with NBC’s Peacock coming soon.

Live TV is accessible for those who have a YouTube TV membership in the States. The (admittedly pricey at $65 a month) service brings access to 85 live stations, including the networks, CNN, ESPN and Nickelodeon, available via a Live tab. The company will also be adding additional live TV provider integration down the road.

The real secret sauce here, however, seems to be the underlying search smarts that serve as the foundation for so much of what Google does. Here’s the company discussing the new feature in a blog post:

To build this, we studied the different ways people discover media—from searching for a specific title to browsing by genre—and created an experience that helps you and what to watch. We also made improvements to Google’s Knowledge Graph, which is pa of how we beer understand and organize your media into topics and genres, from movies about space travel to reality shows about cooking. You’ll also see titles that are trending on Google Search, so you can always and something timely and relevant.

Image Credits: Google

Users can search for specific recommendations via voice. They can also use Assistant to get the weather, sports scores and view their security cams via compatible products like Nest straight from the TV set. The fact that the system is built on top of Android TV means that Google TV is compatible with some 6,500 apps at launch, with support for the company’s own streaming gaming offering, Stadia, coming in the first half of next year. When not in use, Ambient mode will display a slideshow of Google Photos.

Google TV is available for  Chromecast with Google TV, which launches today at $50. Users can also access it as part of the new Google TV app — an update to Google Play Movies & TV for Android, which also arrives today.



from Amazon – TechCrunch https://ift.tt/2ScsCrh
via IFTTT

Achieving Vertical Alignment (Thanks, Subgrid!)

Our tools for vertical alignment have gotten a lot better as of late. My early days as a website designer involved laying out 960px wide homepage designs and aligning things horizontally across a page using a 12-column grid. Media queries came along which required a serious mental shift. It solved some big problems, of course, but introduced new ones, like dealing with alignment when elements wrap or are otherwise moved around in the layout. 

Let’s take a look at just one particular scenario: a “bar” with some buttons in it. There are two groups of these buttons, each contained within a <fieldset> with a <legend>

On a large screen, we’re all set:

Two groups of two bright pink buttons set on a dark background.

And here’s a very basic CSS method that accomplishes that layout, and also breaks down onto two “rows” at a mobile breakpoint:

.accessibility-tools fieldset {
  width: 48%;
  float: left;
  margin-right: 1%;
}


/* Mobile */
@media only screen and (max-width: 480px) {
  .accessibility-tools fieldset {
    width: 100%;
  }
}

On a small screen, we end up with this:

The same two groups of two pink buttons, with one group of buttons stacked on top of the other, showing the buttons are uneven in width.

This is the problem: lack of vertical alignment. Let’s say we want to align those buttons into a more pleasing arrangement where the button edges align with each other nicely.

To begin, we could go for fixed-width, pixel-based CSS solutions to force elements to line up nicely at various breakpoints, using magic numbers like this:

/* Mobile */
@media only screen and (max-width: 480px) {
  legend {
    width: 160px;
  }
  button {
    width: 130px;
  }
}
the same two groups of pink buttons but where the buttons all have the same consistent width and line up evenly.

That does the trick.

But… this is not exactly a flexible solution to the problem. Aside from the magic numbers (fixed-pixel values based on specific content), it also relied on the use of media queries which I am trying to move away from when I can. I discussed this in a post called “Stepping away from Sass” on my blog.

As I moved towards some of the more modern features of CSS the need to target specific screen sizes with unique code was removed.

What I need is each button and label to respond to:

  1. the space available
  2. their content 

and!

  1. Other elements around them

Available space

The problem with using media queries is that they don’t take into account the space around the elements that are being realigned — a point perfectly demonstrated in this image from “The Flexbox holy albatross” by Heydon Pickering:

Three browsers side-by-side. The first shows three black rectangles in a single row, the second shows three black rectangles stacked vertically, and the third shows three black rectangles set to the right hand of the screen.

What I really want is for the second <fieldset> to wrap under the first only when they can no longer fit neatly on one row.

Can we get this done with flexbox?

A key selling point for flexbox is its ability to create elements that respond to the space around them. Components can “flex” to fill additional space and shrink to fit into smaller spaces. 

For this situation, the flex-wrap property is set to wrap. This means as soon as both <fieldset> elements no longer fit on one line, they will wrap onto a second line.

.wrapper--accessibility-tools {
  display: flex;
  flex-wrap: wrap;
} 

The flex-wrap property has three available values. The default value is nowrap, leaving items on one line. The wrap value allows elements to flow onto multiple lines. Then there’s wrap-reverse, which allows items to wrap but — wait for it — in reverse (it is weird to see: when elements wrap, they go above the previous row in left-to-right situations).

Using flexbox stops the layout from being quite as rigid, but a min-width value is still needed to remove the vertical alignment problem. So: close but no cigar.

Can grid help us? 

CSS Grid is the very first CSS module created specifically to solve the ongoing layout problems faced by web designers and developers. It is not a direct replacement for flexbox; rather the two modules usually work pretty well together.

Like flexbox, grid can be used to allow each <fieldset> to occupy as much or as little space as they need. Getting right to it, we can leverage the auto-fill and auto-fit keywords (within a repeat() function) to allow grid items to flow onto multiple lines without the need for media queries. The difference is a bit subtle, but well-explained in “Auto-Sizing Columns in CSS Grid: auto-fill vs auto-fit” by Sara Soueidan. Let’s use auto-fit:

.wrapper--accessibility-tools {
  display: grid;
  grid-template-columns: repeat(auto-fit, 450px);
  grid-gap: 10px;
}

Like the flexbox example, I still need to set an absolute value for the width of the label to align the <fieldset> elements as they stack.

Another approach with grid

CSS Grid also allows elements to respond based on their content using flexible grid tracks. In addition to other length values like percentages, relative units, or pixels, CSS Grid accepts a Fractional Unit (fr), where 1fr will take up one part of the available space, 2fr will take up two parts of the available space, and so on. Let’s set up two equal columns here:

.wrapper--accessibility-tools {
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-gap: 10px;
}

There’s also a minmax() function which creates grid tracks that flex to the available space, but also don’t shrink narrower than a specified size.

.wrapper--accessibility-tools {
  display: grid;
  grid-template-columns: minmax(auto, max-content) minmax(auto, max-content);
  grid-gap: 10px;
}

Both of these demos work, and are free from any absolute values or device specific CSS. The results are far from ideal though, each grid now responds at different points. Maybe not a huge problem, but certainly not great.

This happens because when adding display: grid to a container, only the direct children of that container become grid items. This means the intrinsic sizing units we used only relate to elements in the same grid. 

Using subgrid

To really achieve my goal, I need the buttons and labels to react to elements in sibling grid containers. CSS Grid Level 2 includes the subgrid feature. Although we have always been able to nest grids, the elements within each grid container have been independent. With subgrid, we get to set up nested (child) grids that use parent grids tracks.

This makes a number patterns that were previously difficult much easier, in particular the “card” pattern which seems to be the most popular example to show the benefits of subgrid. Without subgrid, each card is defined as an independent grid, meaning track sizing in the first card cannot respond to a change of height in the second. Pulling from an example Rachel Andrew used, here’s a simple group of cards:

Showing three columns of cards where each card has a headers with a dark blue background and white text, content with a white background, and a footer with a dark blue background. The cards are uneven because some of them have more content that others.
Credit: Rachel Andrew

Subgrid allows the cards to use the rows defined in the parent grid, meaning they can react to content in surrounding cards.

The same three columns of cards, but with each card perfectly aligned with the others.
Credit: Rachel Andrew

Each card in this example still spans three row tracks, but those rows are now defined on the parent grid, allowing each card to occupy the same amount of vertical space.

For the example we’ve been working with, we do not need to use rows. Instead, we need to size columns based on content from sibling grids. First, let’s set the parent grid to contain the two <fieldset> elements. This is similar to the code we previously look at in the auto-fit demo.

.wrapper--accessibility-tools {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  grid-gap: 10px;
}

Then we position each subgrid onto the parent grid.

.sub-grid {
  display: grid;
  grid-column: span 3;
  grid-template-columns: subgrid;
  align-items: center;
}
Showing the two groups of bright pink buttons with both groups on the same row and all the buttons have a consistent width.

All of the labels and buttons are now aligned to the tracks of their parent grid, keeping them consistent. They will each have an equal width based on the space that is available. If there is not enough space for each nested grid on one line, the second will wrap onto a new line.

The two groups of buttons vertically stacked and the buttons are all consistently aligned with the same width.

This time, the two nested grid items align perfectly. The grid is also flexible if we introduce a longer title on a one of the buttons, the other elements will respond accordingly.

Browser compatibility

Support for subgrid is not great at the time of writing. It is only supported in Firefox 71+, although there are positive signals from other browsers. CSS feature queries can be used to provide alternative styling to Chrome and Edge.

This browser support data is from Caniuse, which has more detail. A number indicates that browser supports the feature at that version and up.

Desktop

Chrome Firefox IE Edge Safari
No 71 No No No

Mobile / Tablet

Android Chrome Android Firefox Android iOS Safari
No 79 No No

Note that I am using an extra wrapper around the fieldsets in these demos. This is to combat a bug with form elements and grid and flexbox.

<fieldset class="accessibility-tools__colour-theme">
  <div class="wrapper"></div>
</fieldset>

The layout CSS is applied to the wrapper with the fieldset being set to display: contents.

.accessibility-tools fieldset {
  display: contents;
  border: 0;
} 

Other writing on the subject


The post Achieving Vertical Alignment (Thanks, Subgrid!) appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.



from CSS-Tricks https://ift.tt/34g2NMR
via IFTTT

POW

As a connoisseur of web trickery, this is a must share:

POW stands for Packaged Offline/online Webpage. It turns out the png format includes ways to save metadata alongside the image file. A powfile has a metadata entry that contains a zip file that contains a full website.

So a PNG file can contain and entire website with multiple resources. Wild. The concept is open-source.

Direct Link to ArticlePermalink


The post POW appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.



from CSS-Tricks https://hi.pow.tools/
via IFTTT

Tuesday, September 29, 2020

Clear today!



With a high of F and a low of 47F. Currently, it's 54F and Clear outside.

Current wind speeds: 7 from the Southwest

Pollen: 2

Sunrise: September 29, 2020 at 06:46PM

Sunset: September 30, 2020 at 06:36AM

UV index: 0

Humidity: 31%

via https://ift.tt/2livfew

September 30, 2020 at 10:01AM

Daily Crunch: Amazon lets you pay with your palm

Amazon unveils a new biometric ID technology, the Biden campaign takes aim at Facebook and iRobot’s co-founder joins a robotic gardening startup. This is your Daily Crunch for September 29, 2020.

The big story: Amazon lets you pay with your palm

The company announced a new biometric device for Amazon Go stores. Called Amazon One, the first time you use it, you insert your credit card and scan your palm; after that, you can just hold your palm over the device when entering the store and Amazon can automatically charge you for the items you purchase.

If you’re worried about privacy and security, Amazon said the images are encrypted and stored securely in the cloud, and it also argued that palms are more private than other forms of biometric identification, since you can’t determine someone’s identity just by looking at their palm.

The technology is being tested in two Seattle-area Amazon Go stores. The company suggested that the technology could eventually be used by third parties, for example at stadiums and office buildings.

The tech giants

Ringing alarm bells, Biden campaign calls Facebook ‘foremost propagator’ of voting disinformation — In a new letter to Mark Zuckerberg on the eve of the first presidential debate, the Biden campaign slammed Facebook for its failure to act on false claims about voting in the U.S. election.

Serious injuries at Amazon fulfillment centers topped 14,000, despite the company’s safety claims — More than 14,000 serious injuries (requiring days off or job restrictions) were reported in fulfillment centers in 2019, according to a story in Reveal.

Pivoting during a pandemic — Facebook’s vice president of Messenger discusses how his team has responded to the new normal.

Startups, funding and venture capital

Starlink puts towns devastated by wildfires online for disaster relief workers — A couple small towns in Washington have received Starlink connections to help locals and emergency workers.

iRobot cofounder Helen Greiner named CEO of robotic gardening startup, Tertill — Launched as a 2017 Kickstarter, the product is essentially a solar-powered robotic weed whacker designed to live in the user’s garden and do routine maintenance.

Online course platform Thinkific raises $22 million — Thinkific is different from businesses such as MasterClass and Skillshare because it doesn’t create, distribute or monetize online classes itself.

Advice and analysis from Extra Crunch

Duolingo CEO explains language app’s surge in bookings — Luis von Ahn tells TechCrunch that Duolingo has hit 42 million monthly active users, up from 30 million in December 2019.

Healthcare entrepreneurs should prepare for an upcoming VC/PE bubble — Patientco CEO Bird Blitch has a warning for entrepreneurs.

9 VCs in Madrid and Barcelona discuss the COVID-19 era and look to the future — Part one of a two-part survey that polled 18 active investors in the region.

(Reminder: Extra Crunch is our subscription membership program, which aims to democratize information about startups. You can sign up here.)

Everything else

Disney+ adds a co-watching feature called GroupWatch — Disney’s experience has some advantages (like the fact that it works on internet-connected TVs), but it lacks one of the hallmarks of co-watching, namely a chat that runs alongside the video.

Polaris and Zero Motorcycles reach deal to bring electric off-roaders to market — Polaris is a name synonymous with powersports.

The Daily Crunch is TechCrunch’s roundup of our biggest and most important stories. If you’d like to get this delivered to your inbox every day at around 3pm Pacific, you can subscribe here.



from Amazon – TechCrunch https://ift.tt/3jk6E1y
via IFTTT

Amazon launches a virtual tours and experience platform, Amazon Explore

Amazon today is launching a new service called Amazon Explore that allows customers to book live, virtual experiences led by local experts. The experiences may be focused on creativity, learning DIY skills, taking virtual tours of far-off places or cultural landmarks, or, in some cases, shopping local boutiques from around the world.

For example, you could book a virtual wine tasting experiences in Argentina, learn how to make smoked fish tacos in Mexico, take a virtual tour of Kyoto’s Nanzenji Temple, tour a 500-year old mansion in Peru, learn about coffee creation in Costa Rica, learn how to make sushi from a home kitchen in Tokyo, and more.

Image Credits: Amazon, screenshot via TechCrunch

Though the tours and experiences offer the ability to virtually travel the globe, the ability to sign up for an Amazon Explore session is currently offered on an invite-only basis for customers in the U.S. only.

The virtual experiences themselves will be guided by local experts who are trained and supported by Amazon, the company says. While there are other ways to virtually tour the world — like watching YouTube videos or perhaps taking guided tours via Google Earth — the Amazon Explore experience is different because it’s a one-on-one session between the host and the viewer, enabled by one-way video and two-way audio for real-time communication. This is meant to give the viewer more of the feeling of really “being there,” compared with experiences where you more passively watch the video on the screen.

Image Credits: Amazon, screenshot via TechCrunch

The sessions themselves range 30 to 60 minutes in length and can be canceled or rescheduled with up to 24 hours’ notice. When it’s time to begin your tour, you’ll just sign into your Amazon account online then click in to Your Session page from the “Your Orders” section to get started.

The sessions will require you have a laptop or desktop, as they’re not mobile-friendly at this time. You’ll also need to have a Chrome, Edge or Safari web browser, functional microphone (the built-in one is fine), and a set of headphones or speakers, as well as an internet connection of 5 mbps or higher.

During the session, you can ask questions or further direct the experience by asking the host to spend more time on one aspect of the experience or skipping another. You can also use the camera icon at the bottom of the livestream to take photos.

Image Credits: Amazon, screenshot via TechCrunch

Some, but not all, experiences are also shopping-enabled. In these cases, customers are able to visit local stores and markets, browse items and ask questions of the shop owner as if they were there in person. They can then choose to make a purchase and receive the items they bought as if they had been shopping on Amazon.com directly. When they make a purchase, the payments are handled within Amazon’s secure payment system using the payment method associated with the customer’s account. It then will reimburse the host for the item purchased, accordingly.

In these shopping-enabled experiences, Amazon is somewhat tapping into the livestream shopping trend, but instead of having an influencer talk about and demo a product — as is often the case on Amazon Live, for example — you can actually ask the shop owner questions or have them zoom into the product or turn it over and around for a better look.

Image Credits: Amazon, screenshot via TechCrunch

Though Amazon has built live-streaming tools for its Live platform, the company says the Amazon Explore experience uses unique technology, and it’s not leveraging

Amazon says the new platform enables more opportunities for small business owners looking to generate additional income, including shop owners, local guides, chefs, stylists, artists and artisans, for example. Many of these businesses have been impacted by the pandemic, of course, which may prompt their participation.

Pricing for the sessions is variable. At launch, there’s a virtual styling session being offered for just $10, for example. Meanwhile, a virtual tour of NYC’s Central Park is going for $150. Amazon says the hosts set their own prices and hours, without having to abide by any set minimum or maximum price. However, the company declined to detail any revenue sharing agreements.

At launch, many of the experiences on the site offered are being offered by local tour operators, though any business who has a tour idea is invited to apply. Others who could host experiences include historians, artists, musicians, master craftsmen, chefs, personal shoppers, or anyone with a skill or adventure to share, says Amazon.

There are currently 86 total experiences available across 16 countries with the plan to grow the selection in time.

The feature is now being offered in public beta to users in the U.S. on an invite-only basis.



from Amazon – TechCrunch https://ift.tt/2GoNMQA
via IFTTT

Huboo, the ‘full stack’ fulfilment provider, picks up £14M Series A

Huboo, the U.K.-headquartered startup that offers an end-to-end fulfilment service for online retailers of all sizes, has raised £14 million in Series A funding.

The round is led by Stride.VC, with participation from Hearst Ventures. Existing investors, including Episode 1, Maersk Growth, Ada Ventures and True Capital all followed on, bringing Huboo’s funding to £18 million to date.

Launched in November 2017 by Martin Bysh and Paul Dodd after the pair had run a number of e-commerce experiments, Huboo aims to solve the fulfilment pain point that most online stores face. Using what it calls a “micro-warehousing” and a vertical software model, the full-stack service promises to store your stock, and then “pick, pack and deliver it” automatically as customer orders are placed.

The Huboo dashboard provides stock control, order tracking and billing information. It is also integrated with third-party sales channels and marketplaces, such as Amazon, eBay and Shopify. This enables Huboo to directly receive and process its customers’ orders in real time.

The idea is that by “democratising” fulfilment, online shops can focus on the parts of the business where most value is added, such as customer service and choosing which products to develop and/or sell.

“The vast majority of independent retailers are currently moving online,” says Huboo CEO Martin Bysh. “The pandemic has provided the catalyst for a mass shift into multi-channel commerce over the next five years”.

In addition, he says the direct-to-consumer (D2C) “revolution” is rapidly gaining pace, “with a new breed of agile young D2C businesses bypassing conventional retail channels to engage directly with consumers”. At the same time, retail fulfilment is becoming more complex as customers continue to demand faster delivery times.

“The composition of supply chains is changing due to the pandemic, with retailers forced to pay more attention to where they’re sourcing their products and how to build more robust supply chains,” adds Bysh.

To that end, Huboo will use the new funding to support what its CEO describes as three strategic priorities: software development, U.K. expansion and establishing an on-the-ground European presence as Brexit hardens.

This will see Huboo increase its software development team ten-fold in the next year to further expand the capabilities of its fulfilment software platform. To support client growth, the startup will also be opening a third U.K. warehouse in October 2020, with a fourth warehouse planned to open in January 2021.



from Amazon – TechCrunch https://ift.tt/3kZaRZ8
via IFTTT

Serious injuries at Amazon fulfillment centers topped 14,000, despite the company’s safety claims

As Amazon‘s biggest shopping day of the year approaches, a new report reveals that the company’s investments in automation and safety have not stemmed surging numbers of serious injuries in the company’s warehouses and fulfillment centers.

Even as Amazon spends tens of millions on new robotics and technologies to automate its warehouses, workers are still paying the price with more than 14,000 serious injuries — requiring days off or job restrictions — reported in fulfillment centers in 2019, according to a report from Reveal.

Overall, the company saw 7.7 serious injuries per 100 employees, a number that’s 33% higher than it was four years ago and double the most recent industry standard, despite significant investments and claims that safety is improving at its facilities, the report said.

A document dump from the Center for Investigative Reporting given to Reveal, internal safety reports and weekly injury numbers from Amazon’s network of national fulfillment centers shows that Amazon has misled the public about its safety record. And that the company’s biggest shopping days — during Prime week and the long holiday season — are the most dangerous for its workers.

In a statement, Amazon called Reveal’s report “misinformed” and quibbled over the terminology, while claiming that “we continue to see improvements in injury prevention and reduction” through a variety of programs, though documents in the report suggest otherwise.

Bulletins sent out every month reveal a grim tally of injuries and safety problems, problems that the company was well aware of. Updates marked “Privileged & Confidential” and reportedly obtained by Reveal indicate that the company has failed to hit safety targets. Despite its intentions to reduce injury rates by 20% in 2018, rates rose. In 2019, when the company decided to try and lower its injury rates by a more modest 5%, the number of injuries still went up.

This isn’t the first time that Amazon has had its woeful worker safety record revealed by Reveal. Last year, the company had the covers pulled off of its alleged work with Indiana state officials to cover up a workplace safety violation that resulted in a man’s death.

And the injury rates are the highest at some of the factories that are closest to the company’s international headquarters, the Reveal report showed. Roughly an hour away from Amazon’s Seattle headquarters, in the town of Dupont, Washington, is one of Amazon’s most dangerous facilities, according to Reveal. The BFI3 warehouse saw 22 serious injuries for every 100 of the company’s workers at the warehouse.

Workers in these factories are required to hit certain production quotas that increase every year, despite investments in automation designed to reduce worker stress, according to company statements. A computer system, which tracks how many items employees scan every hour, is used to determine who needs to be flagged for not hitting targets. Those that fall too far behind are fired, according to Reveal. And the robots that were supposed to make their jobs easier, instead demanded that they increase the speed of their packing as much as fourfold.

“We vastly underestimated the effects it was going to have on our associates,” a former safety manager told Reveal. “We realized early on there was an issue. It was just – you’re already moving that way at light speed, so how do you take a step back and readjust?”

Even while the toll the robots were taking became clear to warehouse managers and supervisors, Amazon’s top executives, like Jeff Wilke, continued to tout the company’s automation investments.

What Amazon’s own data showed, according to Reveal, was that the company knew the rate of serious injuries was higher at warehouses with robots than at the ones staffed by humans.

And despite Amazon’s claims to the contrary, risks appeared to increase for workers during Amazon’s highest volume periods. Prime Day in 2019 and the days surrounding it were the worst week for injuries at the company, with nearly 400 serious injuries recorded, according to Reveal’s reporting.

Amazon is also working to obscure how many of its workers get seriously injured enough to lose time at work, because the company is putting them on other “light duty” assignments, according to the Reveal study. Amazon representatives have previously said that the company does not employ this practice, but the evidence cited in the report suggest otherwise.

Injured workers who can’t perform warehouse jobs are given other tasks like tagging photos to train the company’s machine learning software. Others perform temp work for Amazon’s partners in the non-profit world, according to the Reveal report. Reassigning injured workers rather than putting them on leave is not necessarily bad, but it can be used, as it appears to have been by Amazon, to create the appearance of lower injury rates.

These historical conditions and the company’s unwillingness to reduce its bottom line interests in the name of worker health and safety can be seen culminating in the company’s response to the COVID-19 pandemic.

As Americans turned to the everything store for getting everything delivered as they sheltered in place, hundreds of workers at Amazon plants were sickened by the virus. And several died.

Ultimately Amazon invested $800 million in safety measures by the end of the first six months of the year — and three month’s into the steady march of the virus across the country. The movement from Amazon’s executive team only came after workers organized to protest their conditions.

Amazon’s thanks to these organizers? Firing one of the organizers and two other employees who supported the efforts.

Meanwhile, Jeff Bezos has made $60 billion from the surge in Amazon’s stock price.



from Amazon – TechCrunch https://ift.tt/33dTOMT
via IFTTT

Amazon introduces the Amazon One, a way to pay with your palm when entering stores

In the middle of a pandemic when customers are often wearing plastic gloves to stores alongside their face masks, Amazon’s physical retail team is introducing a new biometric device that will allow shoppers to pay at Amazon Go stores using their palm. The company on Tuesday introduced its purportedly “contactless” Amazon One, a scanner of sorts where you’ll first insert your credit card, then hover your palm over the device to associate your palm signature with your payment mechanism. Once your card is on file, you’ll be able to enter the store in the future just by holding your palm above the Amazon One device for a second or so.

While you’re not actually supposed to press your palm down on the device itself, it’s a new technology that will require user education — and that could be a problem, at least in the short-term.

Today, consumers are familiar with the idea of pressing down a finger to unlock an iPhone with TouchID, for example, or using a thumbprint to open a secure lock. It’s likely that many will assume you are to also mash your palm down on Amazon One’s flat surface, too.

At any other time, that wouldn’t be much of a concern. But given that the device is being introduced in the U.S. which is still dealing with the COVID-19 health crisis, now may not be the best time to put another potential touchpoint at a store’s entry.

Amazon, of course, stresses that the device is “contactless” which is something customers will appreciate. But unless store staff stands at the entry wiping the device regularly, it will likely be touched a lot as customers get up to speed on how exactly the thing works. Eventually, the Amazon One may achieve the goal of being “contactless.” But in the meantime, the device should be staffed, wiped and demonstrated to everyone who walks in.

Amazon says the new device uses computer vision technology in real-time to create the unique palm signature — a choice the company made because it believes palm recognition is more private that some other means of biometric authentication. That is, you can’t determine someone’s identity just by looking at the image of their palm, Amazon says. That may be true, but given that the palm signature is associated with a payment card, it’s more important that the data is secured rather than how recognizable the palm image is.

Amazon also says the images are encrypted and sent to a secure area in the cloud where customers’ palm signatures are created. There aren’t specific details about this process being provided at this time.

Amazon’s historical use of biometric products has also been controversial, however, having sold biometric facial recognition services to law enforcement in the U.S. Its facial recognition technology is also the subject of a data privacy lawsuit. Its Ring camera company was discovered to be working in partnership with police, raising civil rights complaints. And recently, it launched indoor drones for home security, in a new potential threat to homeowner privacy. In terms of user data privacy, Amazon hasn’t been careful either — for example, by continuing to store Alexa voice data even when users deleted audio files. 

There is room, then, to question Amazon’s plans to create a database of customer database of biometric data.

Amazon says its new device doesn’t require you to have Amazon.com account to enter the store — just a palm and phone number — but customers can associate their account to see their usage history on the Amazon website. They can also add a second palm print, if they choose.

The Amazon One is being trialed at two Seattle-area stores, including the original Amazon Go store at 7th & Blanchard and the store in South Lake Union at 300 Boren Ave. North. It won’t replace the other ways to enter the stores, however. Customers can still enter using the Amazon Go app, Amazon app, or with associate assistance if they want to pay in cash.

The Amazon One doesn’t have to be used only for entry to retail stores, the company notes. It envisions the device being used by third-parties including stadiums and office buildings, as well as other non-Amazon retailers.

Amazon says discussions are underway with some interested parties, but it has nothing to announce at this time. It’s unclear to what extent a third-party retailer would trust Amazon to host its customer transaction data, however, given Amazon’s history in using third-party data in an anti-competitive fashion.



from Amazon – TechCrunch https://ift.tt/3jdfK09
via IFTTT

Some New Icon Sets

I’ve bookmarked some icon sets lately, partly because I can never find a nice set when I need to. I figured I’d even go the extra mile here and blog them so I can definitely find them later. Aside from being nice, cohesive, and practical sets of icons, I find it interesting that literally all of them:

  • are SVG, and thus easily resizeable
  • are built with rather efficient <path> elements
  • are stroked instead of filled (at least optionally)
  • have a click-to-copy SVG feature on their site
  • are free and open source

Good job, all! Seems like people are coming around to the idea of an SVG icon system where you just… put the SVG in the HTML.

Tabler Icons

Teenyicons

Heroicons

hola svg

This one is from Mariana Beldi who recently shared how hand-drawing SVG can be so much more efficient than using an illustration tool.


The post Some New Icon Sets appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.



from CSS-Tricks https://ift.tt/2G1WLY9
via IFTTT

Make Your Own Dev Tool

Amber Wilson on making bookmarklets to help yo-self. She shows off one that injects an accessibility script — I like this approach, as it means you don’t have to maintain the bookmarklet, just the script it links to). Another example runs some code contained right in the link. The result is literally a bookmark in your browser you can click to do something that is useful to you on any site.

Well, I say “any” site, but what I mean is “sites that don’t have a Content Security Policy (CSP)” which is capable of totally blocking inline scripts (and that’s probably the best thing a CSP can do). That’s wonderful for security, but completely stops bookmarklets. The answer is browser extensions. The story with those is getting better as browsers converge on a standard format.

Browser extensions are much harder to write. Someone should make a browser extension that allows you to create arbitrary bookmarklet-ish snippets to run. I found a few attempts at this in a quick search, but nothing that looks particularly nice. Another thought: DevTools has snippets.

Direct Link to ArticlePermalink


The post Make Your Own Dev Tool appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.



from CSS-Tricks https://ift.tt/324t0N6
via IFTTT

Monday, September 28, 2020

Mostly Clear today!



With a high of F and a low of 38F. Currently, it's 41F and Clear outside.

Current wind speeds: 6 from the West

Pollen: 2

Sunrise: September 28, 2020 at 06:45PM

Sunset: September 29, 2020 at 06:37AM

UV index: 0

Humidity: 36%

via https://ift.tt/2livfew

September 29, 2020 at 10:01AM

Messaging Systems

SMS is just the worst, but I'm having trouble convincing people to adopt my preferred system, TLS IRC with a local server and a patched DOSBox gateway running in my mobile browser.

from xkcd.com https://xkcd.com/2365/
via IFTTT

Amazon launches a $4.99-per-month ‘personal shopper’ service for men’s fashion

Amazon is introducing a personal shopping service for men’s fashion. The service, now available to Prime members, is an expansion of the existing Personal Shopper by Prime Wardrobe, a $4.99 per month Stitch Fix rival, originally aimed at women. With Personal Shopper by Prime Wardrobe, an Amazon stylist selects an assortment of fashion items that match a customer’s style and fit preferences. These are then shipped to the customer on a monthly basis for home try-on. Whatever the customer doesn’t want to keep can be returned using the resealable package and the prepaid shipping label provided.

At launch, the new men’s personal shopping service will include brands like Scotch & Soda, Original Penguin, Adidas, Lacoste, Carhartt, Levi’s, Amazon Essentials, Goodthreads and more — a mix of both Amazon’s own in-house brands and others. In total, Amazon says Personal Shopper by Prime Wardrobe will offer hundreds of thousands of men’s styles across more than a thousand different brands.

The service itself is similar in many ways to Stitch Fix, as it also starts customers with a style quiz to personalize their monthly fashion selections. Also like competitive fashion subscription services, customers can reach out to their stylist with specific requests — like if they need a professional outfit for a job interview, for example, or some other occasion where they may want something outside their usual interests.

But unlike Stitch Fix, which charges a $20 “stylist fee” which is later credited toward any items you choose to keep, Amazon’s personal shopping service is a flat $4.99 per month. Another difference is that the Personal Shopper service will alert you ahead of your shipment to review their picks. You then choose the up to eight items you want to receive, instead of waiting for the surprise of opening your box.

Image Credits: Amazon

Before today, Amazon had offered men’s fashion in its try-before-you-buy Prime Wardrobe product selection. But that service simply allows Amazon Prime members to request certain fashion items for home try-on, instead of paying for them upfront then returning what doesn’t work. To date, Prime Wardrobe’s biggest drawback has been that many of the fashion items found on Amazon aren’t eligible for home try-on, particularly many of those from the most in-demand brands.

However, Amazon claims it doesn’t stuff Prime Wardrobe with only its own brands. The company says less than 1% of its total selection of brands within Prime Wardrobe are Amazon-owned. (Of course, that percentage may be higher in the boxes customers receive from their personal shopper, at times.)

Amazon also says millions of customers have used the home try-on option provided by Prime Wardrobe and   “hundreds of thousands” of customers have created fashion profiles within Personal Shopper by Prime Wardrobe since its 2019 launch.

However, only “tens of thousands” of customers today use the Personal Shopper service on a monthly basis.

That means Prime Wardrobe is no real threat to Stitch Fix at this time, if making a comparison purely based on number of paying customers.

StitchFix has had longer to perfect its model and refine its insights, which has allowed it to grow its active client base to 3.5 million. That figure is up 9% year-over-year, as of the company’s latest earnings reported earlier this month. More recently, Stitch Fix benefited from the pandemic — after it got through its initial backlogged orders — as customers sought to change their style from businesswear to activewear.

Men’s activewear had been particularly in demand, which is perhaps a trend Amazon had also seen ahead of the launch of its new service.

While home try-on via Prime Wardrobe is available today in the U.S., U.K., Germany, Austria and Japan, the Personal Shopper by Prime Wardrobe subscription is currently available in the U.S. only. It’s also only available on mobile devices.



from Amazon – TechCrunch https://ift.tt/30fASLE
via IFTTT

This is how police request customer data from Amazon

Anyone can access portions of a web portal used by law enforcement to request customer data from Amazon, even though the portal is supposed to require a verified email address and password.

Amazon’s law enforcement request portal allows police and federal agents to submit formal requests for customer data along with a legal order, like a subpoena, a search warrant, or a court order. The portal is publicly accessible from the internet, but law enforcement must register an account with the site in order to allow Amazon to “authenticate” the requesting officer’s credentials before they can make requests.

Only time-sensitive emergency requests can be submitted without an account, but this requires the user to “declare and acknowledge” that they are an authorized law enforcement officer before they can submit a request.

The portal does not display customer data or allow access to existing law enforcement requests. But parts of the website still load without needing to log in, including its dashboard and the “standard” request form used by law enforcement to request customer data.

The portal provides a rare glimpse into how Amazon handles law enforcement requests.

This form allows law enforcement to request customer data using a wide variety of data points, including Amazon order numbers, serial numbers of Amazon Echo and Fire devices, credit card details and bank account numbers, gift cards, delivery and shipping numbers, and even the Social Security number of delivery drivers.

It also allows law enforcement to obtain records related to Amazon Web Services accounts by submitting domain names or IP addresses related to the request.

Assuming this was a bug, we sent Amazon several emails prior to publication but did not hear back.

Amazon is not the only tech company with a portal for law enforcement requests. Many of the bigger tech companies with millions or even billions of users around the world, like Google and Twitter, have built portals to allow law enforcement to request customer and user data.

Motherboard reported a similar issue earlier this month that allowed anyone with an email address to access law enforcement portals set up by Facebook and WhatsApp.



from Amazon – TechCrunch https://ift.tt/3mT4ic5
via IFTTT

The Flavors of Object-Oriented Programming (in JavaScript)

In my research, I’ve found there are four approaches to Object-Oriented Programming in JavaScript:

Which methods should I use? Which one is “the best” way? Here I’ll present my findings along with information that may help you decide which is right for you.

To make that decision, we’re not just going to look at the different flavors but compare conceptual aspects between them:

What is Object-Oriented Programming?

Object-Oriented Programming is a way of writing code that allows you to create different objects from a common object. The common object is usually called a blueprint while the created objects are called instances.

Each instance has properties that are not shared with other instances. For example, if you have a Human blueprint, you can create human instances with different names.

The second aspect of Object-Oriented Programming is about structuring code when you have multiple levels of blueprints. This is commonly called Inheritance or subclassing.

The third aspect of Object Oriented Programming is about encapsulation where you hide certain pieces of information within the object so they’re not accessible.

If you need more than this brief intro, here’s an article that introduces this aspect of Object-Oriented Programming if you need help with it.

Let’s begin with the basics — an introduction to the four flavors of Object-Oriented Programming.

The four flavors of Object-Oriented Programming

There are four ways to write Object-Oriented Programming in JavaScript. They are:

Using Constructor functions

Constructors are functions that contain a this keyword.

function Human (firstName, lastName) {
  this.firstName = firstName
  this.lastName = lastName
}

this lets you store (and access) unique values created for each instance. You can create an instance with the new keyword.

const chris = new Human('Chris', 'Coyier')
console.log(chris.firstName) // Chris
console.log(chris.lastName) // Coyier

const zell = new Human('Zell', 'Liew')
console.log(zell.firstName) // Zell
console.log(zell.lastName) // Liew

Class syntax

Classes are said to be the “syntactic sugar” of Constructor functions. As in, Classes are an easier way of writing Constructor functions.

There’s serious contention about whether Classes are bad (like this and this). We’re not going to dive into those arguments here. Instead, we’re just going to look at how to write code with Classes and decide whether Classes are better than constructors based on the code we write.

Classes can be written with the following syntax:

class Human {
  constructor(firstName, lastName) {
    this.firstName = firstName
    this.lastName = lastName
  }
}

Notice the constructor function contains the same code as the Constructor syntax above? We need to do this since we want to initialize values into this. (We can skip constructor if we don’t need to initialize values. More on this later under Inheritance).

At first glance, classes seem to be inferior to constructors — there’s more code to write! Hold your horses and don’t form a conclusion at this point. We have a lot more to cover. Classes begin to shine later.

As before, you can create an instance with the new keyword.

const chris = new Human('Chris', 'Coyier')

console.log(chris.firstName) // Chris
console.log(chris.lastName) // Coyier

Objects Linking to Other Objects (OLOO)

OLOO was coined and popularized by Kyle Simpson. In OLOO, you define the blueprint as a normal object. You then use a method (often named init, but that isn’t required in the way constructor is to a Class) to initialize the instance.

const Human = {
  init () {
    this.firstName = firstName
    this.lastName = lastName
  }
}

You use Object.create to create an instance. After creating the instance, you need to run your init function.

const chris = Object.create(Human)
chris.init('Chris', 'Coyier')

console.log(chris.firstName) // Chris
console.log(chris.lastName) // Coyier

You can chain init after Object.create if you returned this inside init.

const Human = {
  init () {
    // ...
    return this 
  }
}

const chris = Object.create(Human).init('Chris', 'Coyier')
console.log(chris.firstName) // Chris
console.log(chris.lastName) // Coyier

Factory functions

Factory functions are functions that return an object. You can return any object. You can even return a Class instance or OLOO instance — and it’ll still be a valid Factory function.

Here’s the simplest way to create Factory functions:

function Human (firstName, lastName) {
  return {
    firstName,
    lastName
  }
}

You don’t need new to create instances with Factory functions. You simply call the function.

const chris = Human('Chris', 'Coyier')

console.log(chris.firstName) // Chris
console.log(chris.lastName) // Coyier

Now that we’ve seen these four OOP setup possibilities, let’s look at how you declare properties and methods on each of them so we can get a little better understanding of working with them before getting to the bigger comparisons we’re trying to make.


Declaring properties and methods

Methods are functions declared as an object’s property.

const someObject = {
  someMethod () { /* ... */ }
}

In Object-Oriented Programming, there are two ways to declare properties and methods:

  1. Directly on the instance
  2. In the Prototype

Let’s learn to do both.

Declaring properties and methods with Constructors

If you want to declare a property directly on an instance, you can write the property inside the constructor function. Make sure to set it as the property for this.

function Human (firstName, lastName) {
  // Declares properties
  this.firstName = firstName
  this.lastname = lastName

  // Declares methods
  this.sayHello = function () {
    console.log(`Hello, I'm ${firstName}`)
  }
}

const chris = new Human('Chris', 'Coyier')
console.log(chris)

Methods are commonly declared on the Prototype because Prototype allows instances to use the same method. It’s a smaller “code footprint.”

To declare properties on the Prototype, you need to use the prototype property.

function Human (firstName, lastName) {
  this.firstName = firstName
  this.lastname = lastName
}

// Declaring method on a prototype
Human.prototype.sayHello = function () {
  console.log(`Hello, I'm ${this.firstName}`)
}

It can be clunky if you want to declare multiple methods in a Prototype.

// Declaring methods on a prototype
Human.prototype.method1 = function () { /*...*/ }
Human.prototype.method2 = function () { /*...*/ }
Human.prototype.method3 = function () { /*...*/ }

You can make things easier by using merging functions like Object.assign.

Object.assign(Human.prototype, {
  method1 () { /*...*/ },
  method2 () { /*...*/ },
  method3 () { /*...*/ }
})

Object.assign does not support the merging of Getter and Setter functions. You need another tool. Here’s why. And here’s a tool I created to merge objects with Getters and Setters.

Declaring properties and methods with Classes

You can declare properties for each instance inside the constructor function.

class Human {
  constructor (firstName, lastName) {
    this.firstName = firstName
      this.lastname = lastName

      this.sayHello = function () {
        console.log(`Hello, I'm ${firstName}`)
      }
  }
}

It’s easier to declare methods on the prototype. You write the method after constructor like a normal function.

class Human (firstName, lastName) {
  constructor (firstName, lastName) { /* ... */ }

  sayHello () {
    console.log(`Hello, I'm ${this.firstName}`)
  }
}

It’s easier to declare multiple methods on Classes compared to Constructors. You don’t need the Object.assign syntax. You just write more functions.

Note: there’s no , between method declarations in a Class.

class Human (firstName, lastName) {
  constructor (firstName, lastName) { /* ... */ }

  method1 () { /*...*/ }
  method2 () { /*...*/ }
  method3 () { /*...*/ }
}

Declaring properties and methods with OLOO

You use the same process for declaring properties and methods on an instance. You assign them as a property of this.

const Human = {
  init (firstName, lastName) {
    this.firstName = firstName
    this.lastName = lastName
    this.sayHello = function () {
      console.log(`Hello, I'm ${firstName}`)
    }

    return this
  }
}

const chris = Object.create(Human).init('Chris', 'Coyier')
console.log(chris)

To declare methods in the prototype, you write the method like a normal object.

const Human = {
  init () { /*...*/ },
  sayHello () {
    console.log(`Hello, I'm ${this.firstName}`)
  }
}

Declaring properties and methods with Factory functions

You can declare properties and methods directly by including them in the returned object.

function Human (firstName, lastName) {
  return {
    firstName,
    lastName, 
    sayHello () {
      console.log(`Hello, I'm ${firstName}`)
    }
  }
}

You cannot declare methods on the Prototype when you use Factory functions. If you really want methods on the prototype, you need to return a Constructor, Class, or OLOO instance. (Don’t do this since it doesn’t make any sense.)

// Do not do this
function createHuman (...args) {
  return new Human(...args)
}

Where to declare properties and methods

Should you declare properties and methods directly on the instance? Or should you use prototype as much as you can?

Many people take pride that JavaScript is a “Prototypal Language” (which means it uses prototypes). From this statement, you may make the assumption that using “Prototypes” is better.

The real answer is: It doesn’t matter.

If you declare properties and methods on instances, each instance will take up slightly more memory. If you declare methods on Prototypes, the memory used by each instance will decrease, but not much. This difference is insignificant with computer processing power what it is today. Instead, you want to look at how easy it is to write code — and whether it is possible to use Prototypes in the first place.

For example, if you use Classes or OLOO, you’ll be better off using Prototypes since the code is easier to write. If you use Factory functions, you cannot use Prototypes. You can only create properties and methods directly on the instance.

I wrote a separate article on understanding JavaScript Prototypes if you’re interested in finding out more.

Preliminary verdict

We can make a few notes from the code we wrote above. These opinions are my own!

  1. Classes are better than Constructors because its easier to write multiple methods on Classes.
  2. OLOO is weird because of the Object.create part. I gave OLOO a run for a while, but I always forget to write Object.create. It’s weird enough for me not to use it.
  3. Classes and Factry Fufnctions are easiest to use. The problem is that Factory functions don’t support Prototypes. But like I said, this doesn’t really matter in production.

We’re down to two. Should we choose Classes or Factory functions then? Let’s compare them!


Classes vs. Factory functions — Inheritance

To continue the discussion on Classes and Factory functions, we need to understand three more concepts that are tied closely to Object-Oriented Programming.

  1. Inheritance
  2. Encapsulation
  3. this

Let’s start with Inheritance.

What is Inheritance?

Inheritance is a loaded word. Many people in the industry use Inheritance incorrectly, in my opinion. The word “inheritance” is used when you receive things from somewhere. For example:

  • If you get an inheritance from your parents, it means you get money and assets from them.
  • If you inherit genes from your parents, it means you get your genes from them.
  • If you inherit a process from your teacher, it means you get that process from them.

Fairly straightforward.

In JavaScript, Inheritance can mean the same thing: where you get properties and methods from the parent blueprint.

This means all instances actually inherit from their blueprints. They inherit properties and methods in two ways:

  1. by creating a property or method directly upon creating the instance
  2. via the Prototype chain

We discussed how to do both methods in the previous article so refer back to it if you need help seeing these processes in code.

There’s a second meaning for Inheritance in JavaScript — where you create a derivative blueprint from the parent blueprint. This process is more accurately called Subclassing, but people sometimes will call this Inheritance as well.

Understanding Subclassing

Subclassing is about creating a derivative blueprint from a common blueprint. You can use any Object-Oriented Programming flavor to create the Subclass.

We’ll talk about this with the Class syntax first because it’s easier to understand.

Subclassing with Class

When you create a Subclass, you use the extends keyword.

class Child extends Parent {
  // ... Stuff goes here
}

For example, let’s say we want to create a Developer class from a Human class.

// Human Class
class Human {
  constructor (firstName, lastName) {
    this.firstName = firstName
    this.lastName = lastName
  }

  sayHello () {
    console.log(`Hello, I'm ${this.firstName}`)
  }
}

The Developer class will extend Human like this:

class Developer extends Human {
  constructor(firstName, lastName) {
    super(firstName, lastName)
  }

    // Add other methods
}

Note: super calls the Human (also called the “parent”) Class. It initiates the constructor from Human. If you don’t need extra initiation code, you can omit constructor entirely.

class Developer extends Human {
  // Add other methods
}

Let’s say a Developer can code. We can add the code method directly to Developer.

class Developer extends Human {
  code (thing) {
    console.log(`${this.firstName} coded ${thing}`)
  }
}

Here’s an example of an instance of Developer:

const chris = new Developer('Chris', 'Coyier')
console.log(chris)
Instance of a Developer class.

Subclassing with Factory functions

There are four steps to creating Subclasses with Factory functions:

  1. Create a new Factory function
  2. Create an instance of the Parent blueprint
  3. Create a new copy of this instance
  4. Add properties and methods to this new copy

The process looks like this:

function Subclass (...args) {
  const instance = ParentClass(...args)
  return Object.assign({}, instance, {
    // Properties and methods go here
  })
}

We’ll use the same example — creating a Developer Subclass — to illustrate this process. Here’s the Human factory function:

function Human (firstName, lastName) {
  return {
    firstName,
    lastName,
    sayHello () {
      console.log(`Hello, I'm ${firstName}`)
    }
  }
}

We can create Developer like this:

function Developer (firstName, lastName) {
  const human = Human(firstName, lastName)
  return Object.assign({}, human, {
    // Properties and methods go here
  })
}

Then we add the code method like this:

function Developer (firstName, lastName) {
  const human = Human(firstName, lastName)
  return Object.assign({}, human, {
    code (thing) {
      console.log(`${this.firstName} coded ${thing}`)
    }
  })
}

Here’s an example of a Developer instance :

const chris = Developer('Chris', 'Coyier')
console.log(chris)
Example of a Developer instance with Factory functions.

Note: You cannot use Object.assign if you use Getters and Setters. You’ll need another tool, like mix. I explain why in this article.

Overwriting the Parent’s method

Sometimes you need to overwrite the Parent’s method inside the Subclass. You can do this by:

  1. Creating a method with the same name
  2. Calling the Parent’s method (optional)
  3. Changing whatever you need in the Subclass’s method

The process looks like this with Classes:

class Developer extends Human {
  sayHello () {
    // Calls the parent method
    super.sayHello() 

    // Additional stuff to run
    console.log(`I'm a developer.`)
  }
}

const chris = new Developer('Chris', 'Coyier')
chris.sayHello()
Overwriting a parent's method.

The process looks like this with Factory functions:

function Developer (firstName, lastName) {
  const human = Human(firstName, lastName)

  return Object.assign({}, human, {
      sayHello () {
        // Calls the parent method
        human.sayHello() 

        // Additional stuff to run
        console.log(`I'm a developer.`)
      }
  })
}

const chris = new Developer('Chris', 'Coyier')
chris.sayHello()
Overwriting a parent's method.

Inheritance vs. Composition

No talk about Inheritance ever concludes without the mention of Composition. Experts like Eric Elliot often suggests we should favor Composition over Inheritance.

“Favor object composition over class inheritance” the Gang of Four, “Design Patterns: Elements of Reusable Object Oriented Software”

“In computer science, a composite data type or compound data type is any data type which can be constructed in a program using the programming language’s primitive data types and other composite types. […] The act of constructing a composite type is known as composition.” ~ Wikipedia

So let’s give Composition a deeper look and understand what it is.

Understanding Composition

Composition is the act of combining two things into one. It’s about merging things together. The most common (and simplest) way of merging objects is with Object.assign.

const one = { one: 'one' }
const two = { two: 'two' }
const combined = Object.assign({}, one, two)

The use of Composition can be better explained with an example. Let’s say we already have two Subclasses, a Designer and Developer. Designers can design, while developers can code. Both designers and developers inherit from the Human class.

Here’s the code so far:

class Human {
  constructor(firstName, lastName) {
    this.firstName = firstName
    this.lastName = lastName
  }

  sayHello () {
    console.log(`Hello, I'm ${this.firstName}`)
  }
}

class Designer extends Human {
  design (thing) {
    console.log(`${this.firstName} designed ${thing}`)
  }
}

class Developer extends Designer {
  code (thing) {
    console.log(`${this.firstName} coded ${thing}`)
  }
}

Now let’s say you want to create a third Subclass. This Subclass is a mix of a Designer and a Developer they — can design and code. Let’s call it DesignerDeveloper (or DeveloperDesigner, whichever you fancy).

How would you create the third Subclass?

We cannot extend Designer and Developer classes at the same time. This is impossible because we cannot decide which properties come first. This is often called The Diamond Problem.

Diamond problem.

The Diamond Problem can be easily solved if we do something like Object.assign – where we prioritize one object over the other. If we use the Object.assign approach, we may be able to extend classes like this. But this is not supported in JavaScript.

// Doesn't work
class DesignerDeveloper extends Developer, Designer {
  // ...
}

So we need to rely on Composition.

Composition says: Instead of trying to create DesignerDeveloper via Subclassing, let’s create a new object that stores common features. We can then include these features whenever necessary.

In practice, it can look like this:

const skills = {
  code (thing) { /* ... */ },
  design (thing) { /* ... */ },
  sayHello () { /* ... */ }
}

We can then skip Human altogether and create three different classes based on their skills.

Here’s the code for DesignerDeveloper:

class DesignerDeveloper {
  constructor (firstName, lastName) {
    this.firstName = firstName
    this.lastName = lastName

    Object.assign(this, {
      code: skills.code,
      design: skills.design,
      sayHello: skills.sayHello
    })
  }
}

const chris = new DesignerDeveloper('Chris', 'Coyier')
console.log(chris)
Composing methods into a class

You can do the same with Developer and Designer.

class Designer {
  constructor (firstName, lastName) {
    this.firstName = firstName
    this.lastName = lastName 

    Object.assign(this, {
      design: skills.design,
      sayHello: skills.sayHello
    }) 
  }
}

class Developer {
  constructor (firstName, lastName) {
    this.firstName = firstName
    this.lastName = lastName 

    Object.assign(this, {
      code: skills.code,
      sayHello: skills.sayHello
    }) 
  }
}

Did you notice we’re creating methods directly on the instance? This is just one option. We can still put methods into the Prototype, but I think the code looks clunky. (It’s as if we’re writing Constructor functions all over again.)

class DesignerDeveloper {
  constructor (firstName, lastName) {
    this.firstName = firstName
    this.lastName = lastName
  }
}

Object.assign(DesignerDeveloper.prototype, {
  code: skills.code,
  design: skills.design,
  sayHello: skills.sayHello
})
Composition via Classes by putting methods into the Prototype.

Feel free to use whatever code structure you’re attracted to. The results are kinda the same anyway.

Composition with Factory Functions

Composition with Factory functions is essentially adding the shared methods into the returned object.

function DesignerDeveloper (firstName, lastName) {
  return {
    firstName,
    lastName,    
    code: skills.code,
    design: skills.design,
    sayHello: skills.sayHello
  }
}
Composing methods into a factory function

Inheritance and Composition at the same time

Nobody says we can’t use Inheritance and Composition at the same time. We can!

Using the example we’ve ironed out so far, Designer, Developer, and DesignerDeveloper Humans are still humans. They can extend the Human object.

Here’s an example where we use both inheritance and composition with the class syntax.

class Human {
  constructor (firstName, lastName) {
    this.firstName = firstName
    this.lastName = lastName
  }

  sayHello () {
    console.log(`Hello, I'm ${this.firstName}`)
  }
}

class DesignerDeveloper extends Human {}
Object.assign(DesignerDeveloper.prototype, {
  code: skills.code,
  design: skills.design
})
Subclassing and Composition at the same time.

And here’s the same thing with Factory functions:

function Human (firstName, lastName) {
  return {
    firstName,
    lastName,
    sayHello () { 
      console.log(`Hello, I'm ${this.firstName}`)
    }
  }
}

function DesignerDeveloper (firstName, lastName) {
  const human = Human(firstName, lastName)
  return Object.assign({}, human, {
    code: skills.code,
    design: skills.design
  }
}
Subclassing and Composition in Factory functions

Subclassing in the real world

One final point about Subclassing vs. Composition. Even though experts have pointed out that Composition is more flexible (and hence more useful), Subclassing still has its merits. Many things we use today are built with the Subclassing strategy.

For example: The click event we know and love is a MouseEvent. MouseEvent is a Subclass of a UIEvent, which in turn is a Subclass of Event.

MouseEvent is a subclass of UIEvent.

Another example: HTML Elements are Subclasses of Nodes. That’s why they can use all properties and methods of Nodes.

HTMLElement is a subclass of Node.

Preliminary verdict

Classes and Factory functions can both use Inheritance and Composition. Composition seems to be cleaner in Factory functions though, but that’s not a big win over Classes.

We’ll examine Classes and Factory Functions more in detail next.


Classes vs. Factory functions — Encapsulation

We’v looked at the four different Object-Oriented Programming flavors so far. Two of them — Classes and Factory functions — are easier to use compared to the rest.

But the questions remain: Which should you use? And why?

To continue the discussion on Classes and Factory functions, we need to understand three concepts that are tied closely to Object-Oriented Programming:

  1. Inheritance
  2. Encapsulation
  3. this

We just talked about Inheritance. Now let’s talk about Encapsulation.

Encapsulation

Encapsulation is a big word, but it has a simple meaning. Encapsulation is the act of enclosing one thing inside another thing so the thing inside doesn’t leak out. Think about storing water inside a bottle. The bottle prevents water from leaking out.

In JavaScript, we’re interested in enclosing variables (which can include functions) so these variables don’t leak out into the external scope. This means you need to understand scope to understand encapsulation. We’ll go through an explanation, but you can also use this article to beef up your knowledge regarding scopes.

Simple Encapsulation

The simplest form of Encapsulation is a block scope.

{
  // Variables declared here won't leak out
}

When you’re in the block, you can access variables that are declared outside the block.

const food = 'Hamburger'

{
  console.log(food)
}
Logs food from inside the blog. Result: Hamburger.

But when you’re outside the block, you cannot access variables that are declared inside the block.

{
  const food = 'Hamburger'
}

console.log(food)
Logs food from outside the blog. Results: Error.

Note: Variables declared with var don’t respect block scope. This is why I recommend you use let or const to declare variables.

Encapsulating with functions

Functions behave like block scopes. When you declare a variable inside a function, they cannot leak out of that function. This works for all variables, even those declared with var.

function sayFood () {
  const food = 'Hamburger'
}

sayFood()
console.log(food)
Logs food from outside the function. Results: Error.

Likewise, when you’re inside the function, you can access variables that are declared outside of that function.

const food = 'Hamburger'

function sayFood () {
  console.log(food)
}


sayFood()
Logs food from inside the function. Result: Hamburger.

Functions can return a value. This returned value can be used later, outside the function.

function sayFood () {
  return 'Hamburger'
}

console.log(sayFood())
Logs return value from function. Result: Hamburger.

Closures

Closures are an advanced form of Encapsulation. They’re simply functions wrapped in functions.

// Here's a closure
function outsideFunction () {
  function insideFunction () { /* ...*/ }
}

Variables declared in outsideFunction can be used in insideFunction.

function outsideFunction () {
  const food = 'Hamburger'
  console.log('Called outside')

  return function insideFunction () {
    console.log('Called inside')
    console.log(food)
  }
}

// Calls `outsideFunction`, which returns `insideFunction`
// Stores `insideFunction` as variable `fn`
const fn = outsideFunction() 

// Calls `insideFunction`
fn()
Closure logs.

Encapsulation and Object-Oriented Programming

When you build objects, you want to make some properties publicly available (so people can use them). But you also want to keep some properties private (so others can’t break your implementation).

Let’s work through this with an example to make things clearer. Let’s say we have a Car blueprint. When we produce new cars, we fill each car up with 50 liters of fuel.

class Car {
  constructor () {
    this.fuel = 50
  }
}

Here we exposed the fuel property. Users can use fuel to get the amount of fuel left in their cars.

const car = new Car()
console.log(car.fuel) // 50

Users can also use the fuel property to set any amount of fuel.

const car = new Car()
car.fuel = 3000
console.log(car.fuel) // 3000

Let’s add a condition and say that each car has a maximum capacity of 100 liters. With this condition, we don’t want to let users set the fuel property freely because they may break the car.

There are two ways to do prevent users from setting fuel:

  1. Private by convention
  2. Real Private Members

Private by convention

In JavaScript, there’s a practice of prepending underscores to a variable name. This denotes the variable is private and should not be used.

class Car {
  constructor () {
    // Denotes that `_fuel` is private. Don't use it!
    this._fuel = 50
  }
}

We often create methods to get and set this “private” _fuel variable.

class Car {
  constructor () { 
    // Denotes that `_fuel` is private. Don't use it!
    this._fuel = 50
  }

  getFuel () {
    return this._fuel
  }

  setFuel (value) {
    this._fuel = value
    // Caps fuel at 100 liters
    if (value > 100) this._fuel = 100
  }
}

Users should use the getFuel and setFuel methods to get and set fuel.

const car = new Car() 
console.log(car.getFuel()) // 50 

car.setFuel(3000)
console.log(car.getFuel()) // 100 

But _fuel is not actually private. It is still a public variable. You can still access it, you can still use it, and you can still abuse it (even if the abusing part is an accident).

const car = new Car() 
console.log(car.getFuel()) // 50 

car._fuel = 3000
console.log(car.getFuel()) // 3000

We need to use real private variables if we want to completely prevent users from accessing them.

Real Private Members

Members here refer to variables, functions, and methods. It’s a collective term.

Private Members with Classes

Classes let you create private members by prepending # to the variable.

class Car {
  constructor () {
    this.#fuel = 50
  }
}

Unfortunately, you can’t use # directly inside a constructor function.

Error when declaring <code>#</code> directly in constructor function.

You need to declare the private variable outside the constructor first.

class Car {
  // Declares private variable
  #fuel 
  constructor () {
    // Use private variable
    this.#fuel = 50
  }
}

In this case, we can use a shorthand and declare#fuel upfront since we set fuel to 50.

class Car {
  #fuel = 50
}

You cannot access #fuel outside Car. You’ll get an error.

const car = new Car()
console.log(car.#fuel)
Cannot access #fuel.

You need methods (like getFuel or setFuel) to use the #fuel variable.

class Car {
  #fuel = 50

  getFuel () {
    return this.#fuel
  }

  setFuel (value) {
    this.#fuel = value
    if (value > 100) this.#fuel = 100
  }
}

const car = new Car()
console.log(car.getFuel()) // 50

car.setFuel(3000)
console.log(car.getFuel()) // 100

Note: I prefer Getters and Setters instead of getFuel and setFuel. The syntax is easier to read.

class Car {
  #fuel = 50

  get fuel () {
    return this.#fuel
  }

  set fuel (value) {
    this.#fuel = value
    if (value > 100) this.#fuel = 100
  }
}

const car = new Car()
console.log(car.fuel) // 50

car.fuel = 3000
console.log(car.fuel) // 100

Private Members with Factory functions

Factory functions create Private Members automatically. You just need to declare a variable like normal. Users will not be able to get that variable anywhere else. This is because variables are function-scoped and hence encapsulated by default.

function Car () {
  const fuel = 50 
}

const car = new Car() 
console.log(car.fuel) // undefined 
console.log(fuel) // Error: `fuel` is not defined

We can create getter and setter functions to use this private fuel variable.

function Car () {
  const fuel = 50 

  return {
    get fuel () { 
      return fuel 
    },

    set fuel (value) {
      fuel = value 
      if (value > 100) fuel = 100
    }
  }
}

const car = new Car()
console.log(car.fuel) // 50

car.fuel = 3000
console.log(car.fuel) // 100

That’s it! Simple and easy!

Verdict for Encapsulation

Encapsulation with Factory functions are simpler and easier to understand. They rely on the scopes which are a big part of the JavaScript language.

Encapsulation with Classes, on the other hand, requires prepending # to the private variable. This can make things clunky.

We’ll look at the final concept — this to complete the comparison between Classes and Factory functions — in the next section.


Classes vs. Factory Functions — The this variable

this (ha!) is one of the main arguments against using Classes for Object-Oriented Programming. Why? Because this value changes depending on how it is used. It can be confusing for many developers (both new and experienced).

But the concept of this is relatively simple in reality. There are only six contexts in which you can use this. If you master these six contexts, you’ll have no problems using this.

The six contexts are:

  1. In a global context
  2. Inan object construction
  3. In an object property / method
  4. In a simple function
  5. In an arrow function
  6. In an event listener

I covered these six contexts in detail. Give it a read if you need help understanding this.

Note: Don’t shy away from learning to use this. It’s an important concept you need to understand if you intend on mastering JavaScript.

Come back to this article after you’ve solidified your knowledge on this. We’ll have a deeper discussion about using this in Classes and Factory functions.

Back yet? Good. Let’s go!

Using this in Classes

this refers to the instance when used in a Class. (It uses the “In an object property / method” context.) This is why you can set properties and methods on the instance inside the constructor function.

class Human {
  constructor (firstName, lastName) {
    this.firstName = firstName
    this.lastName = lastName
    console.log(this)
  }
}

const chris = new Human('Chris', 'Coyier')
<code>this</code> points to the instance

Using this in Constructor functions

If you use this inside a function and new to create an instance, this will refer to the instance. This is how a Constructor function is created.

function Human (firstName, lastName) {
  this.firstName = firstName 
  this.lastName = lastName
  console.log(this)  
}

const chris = new Human('Chris', 'Coyier')
<code>this</code> points to the instance.

I mentioned Constructor functions because you can use this inside Factory functions. But this points to Window (or undefined if you use ES6 Modules, or a bundler like webpack).

// NOT a Constructor function because we did not create instances with the `new` keyword
function Human (firstName, lastName) {
  this.firstName = firstName 
  this.lastName = lastName
  console.log(this)  
}

const chris = Human('Chris', 'Coyier')
<code>this</code> points to Window.

Essentially, when you create a Factory function, you should not use this as if it’s a Constructor function. This is one small hiccup people experience with this. I wanted to highlight the problem and make it clear.

Using this in a Factory function

The correct way to use this in a Factory function is to use it “in an object property / method” context.

function Human (firstName, lastName) {
  return {
    firstName,
    lastName,
    sayThis () {
      console.log(this)
    }
  }
}

const chris = Human('Chris', 'Coyier')
chris.sayThis()
<code>this</code> points to the instance.

Even though you can use this in Factory functions, you don’t need to use them. You can create a variable that points to the instance. Once you do this, you can use the variable instead of this. Here’s an example at work.

function Human (firstName, lastName) {
  const human = {
    firstName,
    lastName,
    sayHello() {
      console.log(`Hi, I'm ${human.firstName}`)
    }
  }

  return human
}

const chris = Human('Chris', 'Coyier')
chris.sayHello()

human.firstName is clearer than this.firstName because human definitely points back to the instance. You know when you see the code.

If you’re used to JavaScript, you may also notice there’s no need to even write human.firstName in the first place! Just firstName is enough because firstName is in the lexical scope. (Read this article if you need help with scopes.)

function Human (firstName, lastName) {
  const human = {
    firstName,
    lastName,
    sayHello() {
      console.log(`Hi, I'm ${firstName}`)
    }
  }

  return human
}

const chris = Human('Chris', 'Coyier')
chris.sayHello()
Runs <code>chris.sayHello</code>

What we covered so far is simple. It’s not easy to decide whether this is actually needed until we create a sufficiently complicated example. So let’s do that.

Detailed example

Here’s the setup. Let’s say we have a Human blueprint. This Human ha firstName and lastName properties, and a sayHello method.

We have a Developer blueprint that’s derived from Human. Developers can code, so they’ll have a code method. Developers also want to proclaim they’re developers, so we need to overwrite sayHello and add I'm a Developer to the console.

We’ll create this example with Classes and Factory functions. (We’ll make an example with this and an example without this for Factory functions).

The example with Classes

First, we have a Human blueprint. This Human has a firstName and lastName properties, as well as a sayHello method.

class Human {
  constructor (firstName, lastName) {
    this.firstName = firstName
    this.lastname = lastName 
  }

  sayHello () {
    console.log(`Hello, I'm ${this.firstName}`)
  }
}

We have a Developer blueprint that’s derived from Human. Developers can code, so they’ll have a code method.

class Developer extends Human {
  code (thing) {
    console.log(`${this.firstName} coded ${thing}`)
  }
}

Developers also want to proclaim that they’re developers. We need to overwrite sayHello and add I'm a Developer to the console. We do this by calling Human‘s sayHello method. We can do this using super.

class Developer extends Human {
  code (thing) {
    console.log(`${this.firstName} coded ${thing}`)
  }

  sayHello () {
    super.sayHello()
    console.log(`I'm a developer`)
  }
}

The example with Factory functions (with this)

Again, first, we have a Human blueprint. This Human has firstName and lastName properties, as well as a sayHello method.

function Human () {
  return {
    firstName,
    lastName,
    sayHello () {
      console.log(`Hello, I'm ${this.firstName}`)
    }
  }
}

Next, we have a Developer blueprint that’s derived from Human. Developers can code, so they’ll have a code method.

function Developer (firstName, lastName) {
  const human = Human(firstName, lastName)
  return Object.assign({}, human, {
    code (thing) {
      console.log(`${this.firstName} coded ${thing}`)
    }
  })
}

Developers also want to proclaim they’re developers. We need to overwrite sayHello and add I'm a Developer to the console.
We do this by calling Human‘s sayHello method. We can do this using the human instance.

function Developer (firstName, lastName) {
  const human = Human(firstName, lastName)
  return Object.assign({}, human, {
    code (thing) {
      console.log(`${this.firstName} coded ${thing}`)
    },

    sayHello () {
      human.sayHello()
      console.log('I\'m a developer')
    }
  })
}

The example with Factory functions (without this)

Here’s the full code using Factory functions (with this):

function Human (firstName, lastName) {
  return {
    firstName,
    lastName,
    sayHello () {
      console.log(`Hello, I'm ${this.firstName}`)
    }
  }
}

function Developer (firstName, lastName) {
  const human = Human(firstName, lastName)
  return Object.assign({}, human, {
    code (thing) {
      console.log(`${this.firstName} coded ${thing}`)
    },

    sayHello () {
      human.sayHello()
      console.log('I\'m a developer')
    }
  })
}

Did you notice firstName is available within the lexical scope in both Human and Developer? This means we can omit this and use firstName directly in both blueprints.

function Human (firstName, lastName) {
  return {
    // ...
    sayHello () {
      console.log(`Hello, I'm ${firstName}`)
    }
  }
}

function Developer (firstName, lastName) {
  // ...
  return Object.assign({}, human, {
    code (thing) {
      console.log(`${firstName} coded ${thing}`)
    },

    sayHello () { /* ... */ }
  })
}

See that? This means you can safely omit this from your code when you use Factory functions.

Verdict for this

In simple terms, Classes require this while Factory functions don’t. I prefer Factory functions here because:

  1. The context of this can change (which can be confusing)
  2. The code written with factory functions is shorter and cleaner (since we can use encapsulated variables without writing this.#variable).

Next up is the last section where we build a simple component together with both Classes and Factory functions. You get to see how they differ and how to use event listeners with each flavolr.

Classes vs Factory functions — Event listeners

Most Object-Oriented Programming articles show you examples without event listeners. Those examples can be easier to understand, but they don’t reflect the work we do as frontend developers. The work we do requires event listeners — for a simple reason — because we need to build things that rely on user input.

Since event listeners change the context of this, they can make Classes troublesome to deal with. At the same time, they make Factory functions more appealing.

But that’s not really the case.

The change in this doesn’t matter if you know how to handle this in both Classes and Factory functions. Few articles cover this topic so I thought it would be good to complete this article with a simple component using Object-Oriented Programming flavors.

Building a counter

We’re going to build a simple counter in this article. We’ll use everything you learned in this article — including private variables.

Let’s say the counter contains two things:

  1. The count itself
  2. A button to increase the count

Here’s the simplest possible HTML for the counter:

<div class="counter">
  <p>Count: <span>0</span>
  <button>Increase Count</button>
</div>

Building the Counter with Classes

To make things simple, we’ll ask users to find and pass the counter’s HTML into a Counter class.

class Counter () {
  constructor (counter) {
    // Do stuff 
  } 
}

// Usage 
const counter = new Counter(document.querySelector('.counter'))

We need to get two elements in the Counter class:

  1. The <span> that contains the count – we need to update this element when the count increases
  2. The <button> – we need to add an event listener to this element class
Counter () {
  constructor (counter) {
    this.countElement = counter.querySelector('span')
    this.buttonElement = counter.querySelector('button')
  }
}

We’ll initialize a count variable and set it to what the countElement shows. We’ll use a private #count variable since the count shouldn’t be exposed elsewhere.

class Counter () {
  #count
  constructor (counter) {
    // ...

    this.#count = parseInt(countElement.textContent)
  } 
}

When a user clicks the <button>, we want to increase #count. We can do this with another method. We’ll name this method increaseCount.

class Counter () {
  #count
  constructor (counter) { /* ... */ }

  increaseCount () {
    this.#count = this.#count + 1
  }
}

Next, we need to update the DOM with the new #count. Let’s create a method called updateCount to do this. We will call updateCount from increaseCount:

class Counter () {
  #count
  constructor (counter) { /* ... */ }

  increaseCount () {
    this.#count = this.#count + 1
    this.updateCount()
  }

  updateCount () {
    this.countElement.textContent = this.#count
  }
}

We’re ready to add the event listener now.

Adding the event listener

We will add the event listener to the this.buttonElement. Unfortunately, we cannot use increaseCount as the callback straightaway. You’ll get an error if you try it.

class Counter () {
  // ...

  constructor (counter) {
    // ...
    this.buttonElement.addEventListener('click', this.increaseCount)
  }

  // Methods
}
Error accessing #count because this doesn't point to the instance

You get an error because this points to buttonElement. (This is the event listener context.) You’ll see the buttonElement if you logged this into the console.

this points to the button element

We need to change the value of this back to the instance for increaseCount in order for things to work. There are two ways to do it:

  1. Use bind
  2. Use arrow functions

Most people use the first method (but the second one is easier).

Adding the event listener with bind

bind returns a new function. It lets you change this to the first argument that’s passed. People normally create event listeners by calling bind(this).

class Counter () {
  // ...

  constructor (counter) {
    // ...
    this.buttonElement.addEventListener('click', this.increaseCount.bind(this))
  }

  // ...
}

This works, but it’s not very nice to read. It’s also not beginner-friendly because bind is seen as an advanced JavaScript function.

Arrow functions

The second way is to use arrow functions. Arrow functions work because it preserves the this value to the lexical context.

Most people write methods inside the arrow function callback, like this:

class Counter () {
  // ...

  constructor (counter) {
    // ...
    this.buttonElement.addEventListener('click', _ => {
      this.increaseCount()
    })
  }

  // Methods
}

This works, but it is a long way around. There’s actually a shortcut.

You can create increaseCount with arrow functions. If you do this, the this value for increaseCount will be bound to the instance’s value straightaway.

So here’s the code you need:

class Counter () {
  // ...

  constructor (counter) {
    // ...
    this.buttonElement.addEventListener('click', this.increaseCount)
  }

  increaseCount = () => {
    this.#count = this.#count + 1
    this.updateCounter()
  }

  // ...
}

The code

Here’s a complete version of the Class-based code (using arrow functions).

Creating the Counter with Factory functions

We’ll do the same thing here. We’ll get users to pass the Counter’s HTML into the Counter factory.

function Counter (counter) {
  // ...
}

const counter = Counter(document.querySelector('.counter'))

We need to get two elements from counter — the <span> and the <button>. We can use normal variables (without this) here because they are private variables already. We won’t expose them.

function Counter (counter) {
  const countElement = counter.querySelector('span')
  const buttonElement = counter.querySelector('button')
}

We will initialize a count variable to the value that’s present in the HTML.

function Counter (counter) {
  const countElement = counter.querySelector('span')
  const buttonElement = counter.querySelector('button')

  let count = parseInt(countElement.textContext)
}

We will increase this count variable with an increaseCount method. You can choose to use a normal function here, but I like to create a method to keep things neat and tidy.

function Counter (counter) {
  // ... 
  const counter = {
    increaseCount () {
      count = count + 1
    }
  }
}

Finally, we will update the count with an updateCount method. We will also call updateCount from increaseCount.

function Counter (counter) {
  // ... 
  const counter = {
    increaseCount () {
      count = count + 1
      counter.updateCount()
    }

    updateCount () {
      increaseCount()
    }
  }
}

Notice I used counter.updateCount instead of this.updateCount? I like this because counter is clearer compared to this.I also do this because beginners can also make a mistake with this inside Factory functions (which I’ll cover later).

Adding event listeners

We can add event listeners to the buttonElement. When we do this, we can use counter.increaseCount as the callback straight away.

We can do this because we didn’t use this, so it doesn’t matter even if event listeners change the this value.

function Counter (counterElement) {
  // Variables 

  // Methods
  const counter = { /* ... */ }

  // Event Listeners
  buttonElement.addEventListener('click', counter.increaseCount)
}

The this gotcha

You can use this in Factory functions. But you need to use this in a method context.

In the following example, if you call counter.increaseCount, JavaScript will also call counter.updateCount. This works because this points to the counter variable.

function Counter (counterElement) {
  // Variables 

  // Methods
  const counter = {
    increaseCount() {
      count = count + 1
      this.updateCount()
    }
  }

  // Event Listeners
  buttonElement.addEventListener('click', counter.increaseCount)
}

Unfortunately, the event listener wouldn’t work because the this value was changed. You’ll need the same treatment as Classes — with bind or arrow functions to — get the event listener working again.

And this leads me to the second gotcha.

Second this gotcha

If you use the Factory function syntax, you cannot create methods with arrow functions. This is because the methods are created in a simple function context.

function Counter (counterElement) {
  // ...
  const counter = {
    // Do not do this. 
    // Doesn't work because `this` is `Window`
    increaseCount: () => {
      count = count + 1
      this.updateCount()
    }
  }
  // ...
}

So, I highly suggest skipping this entirely if you use Factory functions. It’s much easier that way.

The code

Verdict for event listeners

Event listeners change the value of this, so we must be very careful about using the this value. If you use Classes, I recommend creating event listeners callbacks with arrow functions so you don’t have to use bind.

If you use Factory functions, I recommend skipping this entirely because it may confuse you. That’s it!


Conclusion

We talked about the four flavors of Object-Oriented Programming. They are:

  1. Constructor functions
  2. Classes
  3. OLOO
  4. Factory functions

First, we concluded that Classes and Factory functions are easier to use from a code-related point of view.

Second, we compared how to use Subclasses with Classes and Factory functions. Here, we see creating Subclasses is easier with Classes, but Composition is easier with Factory functions.

Third, we compared Encapsulation with Classes and Factory functions. Here, we see Encapsulation with Factory functions is natural — like JavaScript — while encapsulation with Classes requires you to add a # before variables.

Fourth, we compared the usage of this in Classes and Factory functions. I feel Factory functions win here because this can be ambiguous. Writing this.#privateVariable also creates longer code compared to using privateVariable itself.

Finally, in this article, we built a simple Counter with both Classes and Factory functions. You learned how to add event listeners to both Object-Oriented Programming programming flavors. Here, both flavors work. You just need to be careful whether you use this or not.

That’s it!

I hope this shines some light on Object-Oriented Programming in JavaScript for you. If you liked this article, you may like my JavaScript course, Learn JavaScript, where I explain (almost) everything you need to know about JavaScript in a format as clear and succinct as this.

If you have any questions on JavaScript or front-end development in general, feel free to reach out to me. I’ll see how I can help!


The post The Flavors of Object-Oriented Programming (in JavaScript) appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.



from CSS-Tricks https://ift.tt/2HE14t0
via IFTTT

Mostly Clear today!

With a high of F and a low of 15F. Currently, it's 14F and Clear outside. Current wind speeds: 13 from the Southwest Pollen: 0 S...