Two different styles of functions: does either have an advantage?

In the past few months that I’ve been learning Javascript, I’ve wondered which is the better usage of functions:

Functions that perform actions based on their arguments with no return value:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>const someName = 'John';
function sayHello(name) {
console.log(`Hello, my name is ${name}!`);
}
sayHello(someName);
</code>
<code>const someName = 'John'; function sayHello(name) { console.log(`Hello, my name is ${name}!`); } sayHello(someName); </code>
const someName = 'John';

function sayHello(name) {
  console.log(`Hello, my name is ${name}!`);
}

sayHello(someName);

Or functions that return a value based on their arguments, which can then be used to perform an action:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>const someName = 'John';
function hello(name) {
return `Hello, my name is ${name}!`;
}
console.log(hello(someName));
</code>
<code>const someName = 'John'; function hello(name) { return `Hello, my name is ${name}!`; } console.log(hello(someName)); </code>
const someName = 'John';

function hello(name) {
  return `Hello, my name is ${name}!`;
}

console.log(hello(someName));

Maybe a more practical scenario… (Edited)

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>const myImage = document.getElementById('myImage'); // get image
const numberField = document.getElementById('myField').value; // get input field data
function calculateBrightness(input) { // option 1: return calculated brightness percentage
return `brightness(${input / 2}%)`;
}
function setBrightness(image, value) { // option 2: set image brightness to calculated percentage
image.style.filter = `brightness(${input / 2}%)`;
}
// option 1
let brightness = calculateBrightness(numberField);
myImage.style.filter = brightness;
// option 2
setBrightness(myImage, numberField);
</code>
<code>const myImage = document.getElementById('myImage'); // get image const numberField = document.getElementById('myField').value; // get input field data function calculateBrightness(input) { // option 1: return calculated brightness percentage return `brightness(${input / 2}%)`; } function setBrightness(image, value) { // option 2: set image brightness to calculated percentage image.style.filter = `brightness(${input / 2}%)`; } // option 1 let brightness = calculateBrightness(numberField); myImage.style.filter = brightness; // option 2 setBrightness(myImage, numberField); </code>
const myImage = document.getElementById('myImage'); // get image
const numberField = document.getElementById('myField').value; // get input field data

function calculateBrightness(input) { // option 1: return calculated brightness percentage
  return `brightness(${input / 2}%)`;
}

function setBrightness(image, value) { // option 2: set image brightness to calculated percentage
  image.style.filter = `brightness(${input / 2}%)`;
}

// option 1
let brightness = calculateBrightness(numberField);
myImage.style.filter = brightness;

// option 2
setBrightness(myImage, numberField);

My style is usually in line with the latter examples. To my understanding, the latter functions are also considered “pure” functions since they do not mutate any variables (which are a core principle in functional programming).

My main questions are:

  1. Does either style have any strict advantages, or is it all down to personal preference/use scenario?
  2. Should I be using either style over the other?
  3. Is there a name for the way in which the former examples are structured?

EDIT: Reorganized the second scenario as per Adam B’s suggestion. Earlier answers may be referring to the old code.

The first variant works with side effects: calling the function 10 times will produce 10 lines in the console.

The second version is without side-effects: you can call it 10 times and 10 times you can do something or nothing with its result.

The latter is sometimes called a functional style. Now about preferences, the question is too broad. It can be a matter of taste in many cases. But the choice might be constrained by requirements (e.g. some OOP methods are expected to modify an object, or a logging function is expected to immediately log somthing into a file), and more general project directives.

My personal advice would be to prefer the second form when possible since it facilitates reuse, and side effects are error prone.

2

To my understanding, the latter functions are also considered “pure” functions since they do not mutate any variables (which are a core principle in functional programming).

You’re absolutely right.

Does either style have any strict advantages, or is it all down to personal preference/use scenario?

The advantage of a pure function—it’s easier to test, easier to understand, less risky to invoke.

This being said, all four examples you posted are very simplistic. There is no even need for a function there. The first series can be rewritten like this:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>console.log(`Hello, my name is ${someName}!`);
</code>
<code>console.log(`Hello, my name is ${someName}!`); </code>
console.log(`Hello, my name is ${someName}!`);

And the second one could become:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>const numberField = document.getElementById('myField').value;
document.getElementById('myImage').style.filter = `brightness(${numberField / 2})`;
</code>
<code>const numberField = document.getElementById('myField').value; document.getElementById('myImage').style.filter = `brightness(${numberField / 2})`; </code>
const numberField = document.getElementById('myField').value;
document.getElementById('myImage').style.filter = `brightness(${numberField / 2})`;

Such more compact view makes it much easier to understand what’s happening here. Functions are good to isolate parts of the code which are easier to understand by looking at the name of the function rather as at its body. For instance, a function such as Math.round(x) is clear, and I would rather avoid looking at the actual implementation every time I want to round a number. Same for findNextPrimeNumber(n), or file.saveChanges().

Your case is different. When I see a function called hello, I have no idea what is it doing. I have to look at its implementation, in order to know it. It’s a bit less true for calculateBrightness, but still, I’m wondering what exactly is happening there, and still need to go and see the implementation.

1

Your question is similar to “which is better, strings or numbers”. Neither is better, they serve different purposes. Other languages go so far as to use separate syntax for the two, in order to help categorize what should be happening.

Functions that return values are easier to understand, as their purpose should be implicit in their names, and regardless of how complex the calculation, the result is a single data structure (even in languages that have multiple return, the result can be viewed as a single structure).

Functions that do something, are necessary, but inherently more prone to being difficult to understand as they can’t necessarily be looked at as making a single change.

Instead of trying to always use one or the other, one should instead strive to use them appropriately. Note that the builder pattern is a common use case for a function which does both.

Your first method is easier to use but very inflexible. There’s only one thing it can do with the string. The second method is totally flexible, the caller can do with the string whatever they like, but it’s more work to use.

If a method is used a lot, people tend to start with one way, and when it turns out to be inconvenient, they refactor.

May I suggest a third option that would make it easier to read 6 months from now:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>const image = document.getElementById('myImage'); // get image
const numberField = document.getElementById('myField').value; // get input field data
function calculateBrightness(input) {
return `brightness(${input / 2}%)`; // return calculated data
}
function setBrightness(image, value) {
image.style.filter =value; // set image brightness to calculated data
}
let brightness = calculateBrightness(numberField);
setBrightness(image, brightness);
</code>
<code>const image = document.getElementById('myImage'); // get image const numberField = document.getElementById('myField').value; // get input field data function calculateBrightness(input) { return `brightness(${input / 2}%)`; // return calculated data } function setBrightness(image, value) { image.style.filter =value; // set image brightness to calculated data } let brightness = calculateBrightness(numberField); setBrightness(image, brightness); </code>
const image = document.getElementById('myImage'); // get image
const numberField = document.getElementById('myField').value; // get input field data

function calculateBrightness(input) {
  return `brightness(${input / 2}%)`; // return calculated data
}

function setBrightness(image, value) {
  image.style.filter =value; // set image brightness to calculated data
}

let brightness = calculateBrightness(numberField);
setBrightness(image, brightness);

Although this seems like it adds complexity, it actually decreases the mental effort required to understand the code in several ways. The naming of both functions clarifies what they do.

Furthermore, the names hint at whether your functions are changing the objects passed to them. You wouldn’t expect any side effects from a function named calculate, but the set function hints that the image will be changed.

The logic of the calling code is also improved because each step is quite clear in what it is doing. You’ve made it so each function better adheres to the single responsibility principle.

If possible, I would also move the set brightness code to the image class if able. Like so.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>image.setBrightness(value);
</code>
<code>image.setBrightness(value); </code>
image.setBrightness(value);

3

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật