모바일 웹에서 뒤로가기 버튼 선택시 history.pushstate 사용해서 뒤로가기 이벤트 확인하기
모바일 웹에서 뒤로가기 버튼을 처리하려면 JavaScript를 사용하여 history.pushState를 활용할 수 있습니다. popstate 이벤트를 사용하여 뒤로가기 버튼의 클릭을 감지할 수 있습니다. 아래는 간단한 예제 코드입니다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>뒤로가기 이벤트 확인</title>
</head>
<body>
<h1>뒤로가기 이벤트 확인</h1>
<script>
// 현재 상태 저장
history.pushState({ page: 1 }, "Title 1", "?page=1");
// 뒤로가기 이벤트 처리
window.addEventListener('popstate', function(event) {
// event.state에는 현재 상태의 데이터가 들어있습니다.
if (event.state) {
alert('뒤로가기 버튼이 눌렸습니다. 페이지 상태: ' + JSON.stringify(event.state));
} else {
// 더 이상 뒤로 갈 수 없을 때, 예를 들어 초기 페이지에서 뒤로가기 버튼을 눌렀을 때 처리할 내용을 여기에 추가할 수 있습니다.
alert('뒤로 갈 수 없습니다.');
}
});
// 새로운 상태 추가 및 주소 변경
function changeState() {
const newState = { page: 2 };
history.pushState(newState, "Title 2", "?page=2");
}
</script>
<!-- 버튼을 클릭하여 상태를 변경하고 뒤로가기 이벤트를 확인할 수 있습니다. -->
<button onclick="changeState()">새로운 상태로 이동</button>
</body>
</html>
1.마우스의 휠 버튼을 사용하는 경우 2.키보드의 커서키를 사용하는 방법 3.스크롤 바 위에 마우스를 올려 드래그하여 이동하는 방법
이처럼 세가지 방법이 가장 보편적입니다. 이 중에서 오늘은 스크롤을 사용한 이동시 이를 블락하는 방법을 알아보겠습니다. 먼저 스크롤을 막는 것이 왜? 그리고 언제 필요할까요?
# 스크롤의 이동을 막는 것이 필요한 경우 언제 스크롤을 사용한 페이지 이동을 막아야할까요? 먼저 중요한 콘텐츠 화면 영역에서 빠른 스크롤 이동에 의하여 의도한 콘텐츠를 다 못보여주는 경우도 생각해볼 수 있습니다. 이런 경우는 예를 들면... 페이지 스크롤에 따라 화면이 동적으로 변하는 웹사이트의 경우가 이에 해당합니다. 동적으로 변하는 웹사이트를 보여주기 위해 사용자의 스크롤 이동을 강제하는 것이 필요할 수 있습니다.
또 다른 이유로 스크롤이 화면에 고정되야 하는 경우입니다. 햄버거 버튼을 누른 뒤거나 아니면 모달 형식의 팝업창을 띄운 경우가 좋은 예 입니다.
# 스크롤을 고정하는 방법 예제 소스보기 아래의 소스 코드를 봐주세요. 이코드는 스크립트와 CSS를 사용하여 사용자의 페이지 이동을 강제적으로 막고 있습니다. 우선 스크롤이 생기지 않게 하기 위하여 html과 body 태그에 overflow 속성을 사용하였고 그 값으로 hidden을 주었습니다.
또한 해당하는 요소의 브라우저 기본 이벤트를 피하기 위해 아래의 이벤트 함수를 사용합니다. preventDefault()는 이벤트 내장함수의 실행을 막아 의도한 동작만을 방문자에게 보여줍니다. 또한 발생 가능한 아벤트 버블링을 피하기 위해 stopPropagation()을 추가하였습니다. 해당 자바스크립트는 아래와 같이 사용합니다. event.preventDefault(); event.stopPropagation();
아래 코드를 직접 실행해 보면서 익혀보시기 바랍니다. 코드는 제이쿼리(jQuery)를 사용하여 만든 예제소스입니다. $('html, body').css({'overflow': 'hidden', 'height': '100%'}); $('#element').on('scroll touchmove mousewheel', function(event) { event.preventDefault(); event.stopPropagation(); return false; });
위 코드는 스크롤과 터치이동, 마우스휠의 이벤트 발생시 동작하지 않도록 제거합니다. 각각 scrolll, touchmove, mousewheel 이벤트 코드가 추가되어 있습니다.
# 스크롤 이동을 다시 허용하기 만약 다시 스크롤을 허용해야한다면? 이 경우 기존의 마우스 스크롤이벤트의 핸들러를 제거해야하므로 해제방법이 필요할 것입니다. 이때는 등록된 이벤트를 해제하여 주는 off() 메소드를 사용하여 가능합니다. 아래 코드의 예제를 봐주세요. $('#element').off('scroll touchmove mousewheel');
JavaScript는 웹 개발을 위한 가장 널리 사용되고 강력한 프로그래밍 언어 중 하나입니다. 이를 통해 동적 및 대화형 웹 페이지를 만들고, DOM을 조작하고, 서버와 통신하는 등의 작업을 수행할 수 있습니다. 그러나 JavaScript는 작업하기가 어렵고 좌절스러울 수도 있습니다. 특히 다른 언어에 익숙한 초보자나 개발자에게는 더욱 그렇습니다. 깨끗하고 효율적이며 유지 관리가 가능한 코드를 작성하기 위해 알아야 할 많은 단점, 함정 및 모범 사례가 있습니다.
이번 포스팅에서는 프론트엔드 개발자로서 기술과 생산성을 향상시키는 데 도움이 될 꼭 알아야 할 JavaScript 팁 10가지를 공유하겠습니다. 이 팁에서는 변수, 함수, 문자열, 배열, 개체, 비동기 작업, 모듈, 클래스, 약속 및 콘솔 메서드와 같은 JavaScript의 가장 중요하고 유용한 기능과 개념 중 일부를 다룹니다. 이를 효과적으로 사용하고 일반적인 실수나 오류를 방지하는 방법을 배우게 됩니다. 이 게시물을 마치면 JavaScript에 대해 더 잘 이해하고 더 읽기 쉽고 성능이 뛰어나며 디버그 가능한 코드를 작성하는 방법을 알게 될 것입니다.
그럼 시작해 보겠습니다! 프런트엔드 개발자가 꼭 알아야 할 10가지 JavaScript 팁은 다음과 같습니다.
Tip 1: Use const and let instead of var One of the most common and confusing issues in JavaScript is the declaration and scope of variables. In the past, JavaScript only had one way to declare variables: using the var keyword. However, var has some drawbacks and limitations that can lead to bugs and errors. For example, var variables are function-scoped, meaning they are accessible within the function where they are declared, but not outside. This can cause problems when you have nested functions or loops that use the same variable name. Also, var variables are hoisted, meaning they are moved to the top of their scope before the code is executed. This can cause problems when you try to access a variable before it is declared or initialized.
To avoid these issues, ES6 introduced two new ways to declare variables: using the const and let keywords. Const and let variables are block-scoped, meaning they are accessible within the block where they are declared, but not outside. This can prevent accidental overwriting or leakage of variables. Also, const and let variables are not hoisted, meaning they are only available after they are declared and initialized. This can prevent accessing undefined or uninitialized variables.
Another difference between const and let is that const variables cannot be reassigned after they are declared. This means that once you assign a value to a const variable, you cannot change it later. This can prevent accidental or intentional modification of variables that should remain constant. Let variables, on the other hand, can be reassigned after they are declared. This means that you can change the value of a let variable as many times as you want.
Here is an example of using const and let to declare variables:
// Using var var name = "John"; var age = 25; var hobbies = ["reading", "gaming", "coding"];
function sayHello() { var name = "Jane"; // This will overwrite the global name variable console.log("Hello, " + name); // Hello, Jane }
sayHello(); console.log(name); // Jane
// Using const and let const name = "John"; // This will create a constant name variable let age = 25; // This will create a let age variable const hobbies = ["reading", "gaming", "coding"]; // This will create a constant hobbies array
function sayHello() { let name = "Jane"; // This will create a local name variable console.log("Hello, " + name); // Hello, Jane }
sayHello(); console.log(name); // John
// You can change the value of a let variable age = 26; console.log(age); // 26
// You cannot change the value of a const variable name = "Jack"; // TypeError: Assignment to constant variable. hobbies.push("music"); // You can modify the elements of a const array, but not reassign it console.log(hobbies); // ["reading", "gaming", "coding", "music"] As you can see, using const and let can make your code more readable, performant and debuggable. It can also help you avoid common errors and bugs that can occur with var variables. Therefore, you should always use const and let instead of var when declaring variables in JavaScript.
Tip 2: Use arrow functions for concise and clean syntax Another common and important feature of JavaScript is functions. Functions are blocks of code that can be defined and executed to perform a specific task or operation. Functions can also accept parameters and return values. However, functions can also be verbose and complex to write and use, especially when dealing with the this keyword or binding issues.
To simplify and improve the syntax and functionality of functions, ES6 introduced arrow functions. Arrow functions are a shorter and more expressive way to write functions in JavaScript. Arrow functions use the => symbol to separate the parameters and the body of the function. Arrow functions can also omit the parentheses around the parameters if there is only one parameter, and the curly braces and return keyword around the body if there is only one expression.
Here is an example of using arrow functions to write shorter and more expressive code:
// Using regular functions function add(a, b) { return a + b; }
// Using arrow functions const add = (a, b) => a + b; const greet = name => "Hello, " + name; const square = x => x * x;
console.log(add(2, 3)); // 5 console.log(greet("John")); // Hello, John console.log(square(4)); // 16 As you can see, using arrow functions can make your code more concise and clean. It can also help you avoid some of the pitfalls and confusion that can occur with regular functions. For example, arrow functions do not have their own this keyword, meaning they inherit the this value from their enclosing scope. This can prevent issues with losing or changing the context of this when using callbacks or methods. Arrow functions also do not have their own arguments object, meaning they rely on the named parameters or the rest operator to access the arguments passed to them. This can prevent issues with accessing or modifying the arguments object in nested or strict mode functions.
Therefore, you should always use arrow functions instead of regular functions when writing concise and clean code in JavaScript.
Tip 3: Use template literals for dynamic and multi-line strings One of the most common and useful data types in JavaScript is strings. Strings are sequences of characters that can be used to store and manipulate text, such as names, messages, URLs, etc. However, strings can also be tricky and tedious to work with, especially when you need to create dynamic or multi-line strings. For example, you need to use the + operator or the concat method to concatenate strings and variables, and you need to use the \n character or the backslash () to create new lines or escape characters.
To simplify and improve the creation and manipulation of strings, ES6 introduced template literals. Template literals are a new way to write strings in JavaScript that use the backtick (`) character instead of the single (‘) or double (“) quotes. Template literals allow embedding expressions and variables inside strings using the ${} syntax. Template literals also allow creating multi-line strings without using any special characters or escaping.
Here is an example of using template literals to create dynamic and multi-line strings with ease:
// Using regular strings var name = "John"; var age = 25; var message = "Hello, " + name + ".\nYou are " + age + " years old."; console.log(message); // Hello, John. // You are 25 years old.
// Using template literals const name = "John"; const age = 25; const message = `Hello, ${name}. You are ${age} years old.`; console.log(message); // Hello, John. // You are 25 years old. As you can see, using template literals can make your code more readable, interpolation and escaping. It can also help you avoid some of the errors and bugs that can occur with regular strings. For example, template literals do not require any quotation marks around the embedded expressions or variables, meaning they can handle any data type or value without causing syntax errors. Template literals also do not require any special characters or escaping for creating new lines or other characters, meaning they can handle any format or layout without causing display issues.
Therefore, you should always use template literals instead of regular strings when creating dynamic or multi-line strings in JavaScript.
Tip 4: Use destructuring assignment for extracting values from objects and arrays Another common and useful data type in JavaScript is objects and arrays. Objects and arrays are collections of values that can be used to store and manipulate data, such as properties, methods, elements, etc. However, objects and arrays can also be complex and cumbersome to work with, especially when you need to extract or assign values from them. For example, you need to use the dot (.) or the bracket ([]) notation to access or modify the properties or elements of objects or arrays, and you need to use multiple variables or statements to extract or assign multiple values from them.
To simplify and improve the extraction and assignment of values from objects and arrays, ES6 introduced destructuring assignment. Destructuring assignment is a new way to write assignments in JavaScript that use the {} or [] syntax to unpack values from objects or arrays into variables. Destructuring assignment can also use the = symbol to provide default values or the … symbol to collect the remaining values into a new variable.
Here is an example of using destructuring assignment to simplify code and avoid repetition:
// Using regular assignments var person = { name: "John", age: 25, hobbies: ["reading", "gaming", "coding"] };
var name = person.name; var age = person.age; var hobbies = person.hobbies;
// Using destructuring assignment const person = { name: "John", age: 25, hobbies: ["reading", "gaming", "coding"] };
const { name, age, hobbies } = person;
console.log(name); // John console.log(age); // 25 console.log(hobbies); // ["reading", "gaming", "coding"] As you can see, using destructuring assignment can make your code more readable, performant and convenient. It can also help you avoid some of the errors and bugs that can occur with regular assignments. For example, destructuring assignment can handle nested or complex objects or arrays without causing syntax errors. Destructuring assignment can also handle missing or undefined values without causing reference errors.
Therefore, you should always use destructuring assignment instead of regular assignments when extracting or assigning values from objects or arrays in JavaScript.
Tip 5: Use spread and rest operators for manipulating arrays and objects Another common and important feature of JavaScript is the ability to manipulate arrays and objects. Arrays and objects are collections of values that can be used to store and manipulate data, such as properties, methods, elements, etc. However, arrays and objects can also be difficult and tedious to manipulate, especially when you need to copy, merge or split them. For example, you need to use the slice, concat or splice methods to copy, merge or split arrays, and you need to use the Object.assign or Object.keys methods to copy or merge objects.
To simplify and improve the manipulation of arrays and objects, ES6 introduced the spread and rest operators. The spread operator (…) allows expanding or spreading the values of an array or an object into individual values. The rest operator (…) allows collecting or gathering the remaining values of an array or an object into a new variable.
Here is an example of using the spread and rest operators to manipulate arrays and objects with ease:
// Using regular methods var arr1 = [1, 2, 3]; var arr2 = [4, 5, 6];
// Copying an array var arr3 = arr1.slice(); console.log(arr3); // [1, 2, 3]
// Merging two arrays var arr4 = arr1.concat(arr2); console.log(arr4); // [1, 2, 3, 4, 5, 6]
// Splitting an array var arr5 = arr4.splice(0, 3); console.log(arr5); // [1, 2, 3] console.log(arr4); // [4, 5, 6]
var obj1 = { name: "John", age: 25 }; var obj2 = { hobbies: ["reading", "gaming", "coding"] };
// Copying an object var obj3 = Object.assign({}, obj1); console.log(obj3); // { name: "John", age: 25 }
// Merging two objects const obj4 = {...obj1,...obj2}; console.log(obj4); // { name: "John", age: 25,hobbies: ["reading", "gaming", "coding"] } As you can see, using the spread and rest operators can make your code more readable flexibility and immutability. It can also help you avoid some of the errors and bugs that can occur with regular methods. For example, the spread operator can handle nested or complex arrays or objects without causing syntax errors. The rest operator can handle missing or undefined values without causing reference errors.
Therefore, you should always use the spread and rest operators instead of regular methods when manipulating arrays or objects in JavaScript.
Tip 6: Use async/await for handling asynchronous operations Another common and important feature of JavaScript is the ability to handle asynchronous operations. Asynchronous operations are tasks or functions that can run in the background without blocking the main thread of execution. Asynchronous operations can be used to perform tasks such as fetching data from a server, reading or writing files, setting timers, etc. However, asynchronous operations can also be challenging and complex to handle, especially when dealing with callbacks, promises or errors.
To simplify and improve the handling of asynchronous operations, ES8 introduced async/await. Async/await is a new way to write asynchronous code in JavaScript that uses the async and await keywords. The async keyword allows defining an asynchronous function that returns a promise. The await keyword allows pausing the execution of an asynchronous function until a promise is resolved or rejected.
Here is an example of using async/await to handle asynchronous operations with ease:
// Using callbacks function fetchData(url, callback) { // Simulate fetching data from a server setTimeout(() => { const data = "Some data from " + url; callback(null, data); }, 1000); }
function processData(data, callback) { // Simulate processing data setTimeout(() => { const result = "Processed " + data; callback(null, result); }, 1000); }
function displayData(data, callback) { // Simulate displaying data setTimeout(() => { console.log(data); callback(null, "Done"); }, 1000); }
// Using async/await async function fetchData(url) { // Simulate fetching data from a server return new Promise(resolve => { setTimeout(() => { const data = "Some data from " + url; resolve(data); }, 1000); }); }
async function processData(data) { // Simulate processing data return new Promise(resolve => { setTimeout(() => { const result = "Processed " + data; resolve(result); }, 1000); }); }
async function displayData(data) { // Simulate displaying data return new Promise(resolve => { setTimeout(() => { console.log(data); resolve("Done"); }, 1000); }); }
main(); As you can see, using async/await can make your code more readable error handling and simplicity. It can also help you avoid some of the pitfalls and confusion that can occur with callbacks or promises. For example, async/await can handle nested or sequential asynchronous operations without causing callback hell or promise chaining. Async/await can also handle errors or rejections using the try/catch blocks or the .catch() method.
Therefore, you should always use async/await instead of callbacks or promises when handling asynchronous operations in JavaScript.
Tip 7: Use modules for organizing and reusing code Another common and important feature of JavaScript is the ability to organize and reuse code. Code organization and reuse can help you write code that is more readable, maintainable and modular. However, code organization and reuse can also be difficult and tedious to achieve, especially when dealing with multiple files or dependencies.
To simplify and improve the organization and reuse of code, ES6 introduced modules. Modules are a new way to write code in JavaScript that use the import and export keywords. Modules allow dividing code into separate files that can be imported and exported as needed. Modules can also use the default or named syntax to specify what values or features are exported or imported.
Here is an example of using modules to organize and reuse code with ease:
// math.js file // Exporting a default value export default function add(a, b) { return a + b; }
// Exporting named values export function subtract(a, b) { return a - b; }
export function multiply(a, b) { return a * b; }
export function divide(a, b) { return a / b; }
// app.js file // Importing a default value import add from "./math.js";
console.log(add(2, 3)); // 5
// Importing named values import { subtract, multiply, divide } from "./math.js";
// Importing all values as an object import * as math from "./math.js";
console.log(math.add(2, 3)); // 5 console.log(math.subtract(5, 2)); // 3 console.log(math.multiply(2, 3)); // 6 console.log(math.divide(6, 2)); // 3 As you can see, using modules can make your code more readable maintainability and modularity. It can also help you avoid some of the errors and bugs that can occur with regular scripts or dependencies. For example, modules can handle scope or naming conflicts without causing syntax errors. Modules can also handle loading or caching issues without causing performance or memory issues.
Therefore, you should always use modules instead of regular scripts or dependencies when organizing and reusing code in JavaScript.
Tip 8: Use classes for creating objects with shared properties and methods Another common and useful data type in JavaScript is objects. Objects are collections of values that can be used to store and manipulate data, such as properties, methods, etc. However, objects can also be complex and cumbersome to create and use, especially when you need to create multiple objects with a common structure and behavior.
To simplify and improve the creation and use of objects, ES6 introduced classes. Classes are a new way to write objects in JavaScript that use the class keyword. Classes allow defining a constructor, properties and methods for an object. Classes can also use the extends or super keywords to implement inheritance or polymorphism.
Here is an example of using classes to create objects with shared properties and methods with ease:
// Using regular objects function Person(name, age) { this.name = name; this.age = age; }
Person.prototype.greet = function () { console.log("Hello, I am " + this.name + " and I am " + this.age + " years old."); };
Student.prototype.study = function () { console.log("I am studying " + this.course + "."); };
var john = new Person("John", 25); var jane = new Student("Jane", 22, "Computer Science");
john.greet(); // Hello, I am John and I am 25 years old. jane.greet(); // Hello, I am Jane and I am 22 years old. jane.study(); // I am studying Computer Science.
// Using classes class Person { constructor(name, age) { this.name = name; this.age = age; }
greet() { console.log(`Hello, I am ${this.name} and I am ${this.age} years old.`); } }
class Student extends Person { constructor(name, age, course) { super(name, age); this.course = course; }
study() { console.log(`I am studying ${this.course}.`); } }
const john = new Person("John", 25); const jane = new Student("Jane", 22, "Computer Science");
john.greet(); // Hello, I am John and I am 25 years old. jane.greet(); // Hello, I am Jane and I am 22 years old. jane.study(); // I am studying Computer Science. As you can see, using classes can make your code more readable encapsulation and inheritance. It can also help you avoid some of the errors and bugs that can occur with regular objects. For example, classes can handle constructor or prototype issues without causing syntax errors. Classes can also handle inheritance or polymorphism issues without causing reference errors.
Therefore, you should always use classes instead of regular objects when creating objects with shared properties and methods in JavaScript.
Tip 9: Use promises for handling asynchronous operations Another common and important feature of JavaScript is the ability to handle asynchronous operations. Asynchronous operations are tasks or functions that can run in the background without blocking the main thread of execution. Asynchronous operations can be used to perform tasks such as fetching data from a server, reading or writing files, setting timers, etc. However, asynchronous operations can also be challenging and complex to handle, especially when dealing with callbacks or errors.
To simplify and improve the handling of asynchronous operations, ES6 introduced promises. Promises are a new way to write asynchronous code in JavaScript that use the Promise object. Promises represent the eventual completion or failure of an asynchronous operation. Promises can also use the then or catch methods to handle the resolution or rejection of an asynchronous operation.
Here is an example of using promises to handle asynchronous operations with ease:
// Using callbacks function fetchData(url, callback) { // Simulate fetching data from a server setTimeout(() => { const data = "Some data from " + url; callback(null, data); }, 1000); }
function processData(data, callback) { // Simulate processing data setTimeout(() => { const result = "Processed " + data; callback(null, result); }, 1000); }
function displayData(data, callback) { // Simulate displaying data setTimeout(() => { console.log(data); callback(null, "Done"); }, 1000); }
// Using promises function fetchData(url) { // Simulate fetching data from a server return new Promise((resolve, reject) => { setTimeout(() => { const data = "Some data from " + url; resolve(data); }, 1000); }); }
function processData(data) { // Simulate processing data return new Promise((resolve, reject) => { setTimeout(() => { const result = "Processed " + data; resolve(result); }, 1000); }); }
function displayData(data) { // Simulate displaying data return new Promise((resolve, reject) => { setTimeout(() => { console.log(data); resolve("Done"); }, 1000); }); }
// Using promises to handle asynchronous operations fetchData("https://example.com") .then(data1 => processData(data1)) .then(data2 => displayData(data2)) .then(data3 => console.log(data3)) // Done .catch(error => console.error(error)); As you can see, using promises can make your code more readable error handling and simplicity. It can also help you avoid some of the pitfalls and confusion that can occur with callbacks or errors. For example, promises can handle nested or sequential asynchronous operations without causing callback hell or pyramid of doom. Promises can also handle errors or rejections using the catch method or the reject function.
Therefore, you should always use promises instead of callbacks or errors when handling asynchronous operations in JavaScript.
Tip 10: Use console methods for debugging and testing code Another common and important feature of JavaScript is the ability to debug and test code. Debugging and testing code can help you find and fix errors or bugs in your code, as well as improve its performance or functionality. However, debugging and testing code can also be difficult and tedious to do, especially when dealing with complex or large code.
To simplify and improve the debugging and testing of code, JavaScript provides various console methods. Console methods are built-in functions that can be used to log, inspect or test values in the browser console. Console methods can also use various parameters or options to customize the output or behavior of the console.
Here is an example of using console methods to debug and test code with ease:
// Using console.table console.table(["apple", "banana", "orange"]); // Displays a table with index and value columns console.table({ name: "John", age: 25 }); // Displays a table with key and value columns
// Using console.assert console.assert(2 > 3, "2 is not greater than 3"); // Assertion failed: 2 is not greater than 3 console.assert(3 > 2, "3 is greater than 2"); // No output
// Using console.time and console.timeEnd console.time("Loop"); // Starts a timer with the label Loop for (let i = 0; i < 1000000; i++) { // Do something } console.timeEnd("Loop"); // Ends the timer and logs the elapsed time // Loop: 3.456 ms
// Using console.group and console.groupEnd console.group("Animals"); // Starts a group with the label Animals console.log("Cat"); console.log("Dog"); console.log("Bird"); console.groupEnd(); // Ends the group // Animals: // Cat // Dog // Bird As you can see, using console methods can make your code more readable performance and troubleshooting. It can also help you avoid some of the errors and bugs that can occur with regular logging or testing. For example, console methods can handle different data types or values without causing syntax errors. Console methods can also handle formatting or grouping issues without causing display issues.
Therefore, you should always use console methods instead of regular logging or testing when debugging and testing code in JavaScript.
1. <head></head> 사이에 script 코드를 삽입. <script type="text/javascript"> document.oncontextmenu = function(){return false;} </script>
2. <body> 아래에 html 코드를 삽입. <body oncontextmenu="return false" onselectstart="return false" ondragstart="return false" onkeydown="return false">
3. 명칭 oncontextmenu = "return false" : 우클릭 방지 onseletstart = "return false" : 마우스 드래그 방지 ondragstart = "return false" : 이미지 복사 드래그 방지 onkeydown = "return false" : 키보드 단축키 복사 방지
Window 및 Worker 인터페이스에서 제공되는 setInterval() 메서드는 각 호출 사이에 고정된 시간 지연으로 함수를 반복적으로 호출하거나 코드 스니펫을 실행합니다.
이 메서드는 간격(interval)을 고유하게 식별할 수 있는 interval ID를 반환하므로 나중에 clearInterval() (en-US) 함수를 호출하여 제거할 수 있습니다.
myArray = ["zero", "one", "two"];
myArray.myMethod = function (sProperty) {
alert(arguments.length > 0 ? this[sProperty] : this);
};
myArray.myMethod(); // "zero,one,two"가 출력됩니다
myArray.myMethod(1); // "one"가 출력됩니다
setTimeout(myArray.myMethod, 1000); // 1초 후 "[object Window]"가 출력됩니다
setTimeout(myArray.myMethod, 1500, "1"); // 1,5초 후에 "undefined"가 출력됩니다
// myArray.myMethod 내에서 this의 값을 변경하려는 동안
// setTimeout 내부에서 this의 값을 변경하기 때문에
// .call과 함께 'this'객체를 전달하는 것은 동작하지 않습니다
// 사실 setTimeout 코드는 this가 window 객체가 될 것으로 예상하기 때문에 오류가 발생합니다
setTimeout.call(myArray, myArray.myMethod, 2000); // error: "NS_ERROR_XPC_BAD_OP_ON_WN_PROTO: Illegal operation on WrappedNative prototype object"
setTimeout.call(myArray, myArray.myMethod, 2500, 2); // 위와 동일한 에러가 발생합니다
가로로 길게 늘어진 코드를 읽는 걸 좋아하는 개발자는 없습니다. 코드의 가로 길이가 길어진다면 여러 줄로 나눠 작성하는 게 좋습니다.
예시:
// 백틱(`)을 사용하면 문자열을 여러 줄로 쉽게 나눌 수 있습니다.
let str = `
ECMA International's TC39 is a group of JavaScript developers,
implementers, academics, and more, collaborating with the community
to maintain and evolve the definition of JavaScript.
`;
if문이라면 아래와 같이 작성할 수 있을겁니다.
if (
id === 123 &&
moonPhase === 'Waning Gibbous' &&
zodiacSign === 'Libra'
) {
letTheSorceryBegin();
}
최대 가로 길이는 팀원들과 합의해 정하는게 좋습니다. 대개 80자나 120자로 제한하는 게 일반적입니다.
구문 끝에 세미콜론을 적는 게 완전히 선택사항인 언어가 몇몇 있는데 이런 언어들에선 세미콜론을 잘 쓰지 않습니다. 그러나 자바스크립트에선 줄 바꿈이 세미콜론으로 해석되지 않는 몇몇 상황이 있기 때문에 세미콜론을 생략하고 코딩하는 습관을 들이면 에러를 발생시키는 코드를 만들 수 있습니다. 자세한 사례는코드 구조챕터에서 살펴보세요.
경험이 많은 자바스크립트 개발자라면StandardJS에서 제시하는 스타일 가이드처럼 세미콜론 없이 코드를 작성할 수도 있습니다. 초보 개발자라면 에러를 만들 확률을 줄이기 위해서라도 세미콜론을 사용하는 게 좋습니다.
반복문을 사용할 때 중첩문의 깊이가 깊어지면continue지시자를 쓰는 게 좋은 대안이 될 수도 있습니다.
if문으로 조건을 처리하는 예시를 통해 이를 살펴봅시다.
for (let i = 0; i < 10; i++) {
if (cond) {
... // <- 중첩 레벨이 하나 더 늘어났습니다.
}
}
위 코드는continue를 써서 아래와 같이 바꿀 수 있습니다.
for (let i = 0; i < 10; i++) {
if (!cond) continue;
... // <- 추가 중첩 레벨이 추가되지 않습니다.
}
if/else와return문을 조합하면 위 예시와 유사하게 중첩 레벨을 줄여 코드의 가독성을 높일 수 있습니다.
아래 두 예시는 동일하게 동작합니다.
예시 1:
function pow(x, n) {
if (n < 0) {
alert("'n'은 음수가 될 수 없습니다.");
} else {
let result = 1;
for (let i = 0; i < n; i++) {
result *= x;
}
return result;
}
}
예시 2:
function pow(x, n) {
if (n < 0) {
alert("'n'은 음수가 될 수 없습니다.");
return;
}
let result = 1;
for (let i = 0; i < n; i++) {
result *= x;
}
return result;
}
n < 0인 '특별한 상황’을 앞에 두고, 그 안에return문을 추가해주었더니 가독성이 훨씬 좋아졌습니다. 특별한 상황인지를 확인하고 조건을 통과하면 추가 중첩 없이 ‘주요’ 코드 흐름으로 넘어가게 코드를 짰기 때문입니다.
‘헬퍼’ 함수 여러 개를 만들어 사용하고 있다면 아래와 같은 방법을 사용해 코드 구조를 정돈할 수 있습니다.
헬퍼 함수를 사용하는 코드위에서 헬퍼 함수를 모아 선언하기
// 함수 선언
function createElement() {
...
}
function setHandler(elem) {
...
}
function walkAround() {
...
}
// 헬퍼 함수를 사용하는 코드
let elem = createElement();
setHandler(elem);
walkAround();
코드를 먼저, 함수는 그 다음에 선언하기
// 헬퍼 함수를 사용하는 코드
let elem = createElement();
setHandler(elem);
walkAround();
// --- 헬퍼 함수 ---
function createElement() {
...
}
function setHandler(elem) {
...
}
function walkAround() {
...
}
혼합: 코드 바로 위에서 필요한 헬퍼 함수 그때그때 선언하기
대개는 두 번째 방법으로 코드를 정돈하는 걸 선호합니다.
사람들은 이 코드가 '무엇을 하는지’를 생각하며 코드를 읽기 때문에 코드가 먼저 나오는 것이 자연스럽기 때문입니다. 이름만 보고도 헬퍼 함수의 역할을 쉽게 유추할 수 있게 헬퍼 함수 이름을 명명했다면 함수 본문을 읽을 필요도 없습니다.
이 챕터에서 소개해 드린 문법 규칙과 스타일 가이드 관련 참고자료들은 코드 가독성을 높이기 위해 만들어졌습니다.
‘더 좋은’ 코드를 만들려면 "가독성이 좋고 이해하기 쉬운 코드를 만들려면 무엇을 해야 할까?"라는 질문과 "에러를 피하려면 어떤 일을 해야 할까?"라는 질문을 스스로에게 던져야 합니다. 어떤 코딩 스타일을 따를지 결정할 때와 이에 대한 논쟁을 할 땐 이런 질문을 기반으로 해야 하죠.
유명 스타일 가이드를 읽다 보면 코드 스타일에 관한 경향과 모범 사례에 대한 최신 정보를 유지할 수 있습니다.
function pow(x,n)
{
let result=1;
for(let i=0;i<n;i++) {result*=x;}
return result;
}
let x=prompt("x?",''), n=prompt("n?",'')
if (n<=0)
{
alert(`Power ${n} is not supported, please enter an integer number greater than zero`);
}
else
{
alert(pow(x,n))
}
nullish 병합 연산자(nullish coalescing operator)??를 사용하면 짧은 문법으로 여러 피연산자 중 그 값이 ‘확정되어있는’ 변수를 찾을 수 있습니다.
a ?? b의 평가 결과는 다음과 같습니다.
a가null도 아니고undefined도 아니면a
그 외의 경우는b
nullish 병합 연산자??없이x = a ?? b와 동일한 동작을 하는 코드를 작성하면 다음과 같습니다.
x = (a !== null && a !== undefined) ? a : b;
비교 연산자와 논리 연산자만으로 nullish 병합 연산자와 같은 기능을 하는 코드를 작성하니 코드 길이가 길어지네요.
또 다른 예시를 살펴봅시다.firstName,lastName,nickName이란 변수에 사용자 이름이나 별명을 저장하는데, 사용자가 아무런 정보도 입력하지 않는 케이스도 허용한다고 해보겠습니다.
화면엔 세 변수 중 실제 값이 있는 변수의 값을 출력하는데, 세 변수 모두 값이 없다면 '익명의 사용자’가 출력되도록 해보죠.
이럴 때 nullish 병합 연산자??를 사용하면 값이 정해진 변수를 간편하게 찾아낼 수 있습니다.
let firstName = null;
let lastName = null;
let nickName = "바이올렛";
// null이나 undefined가 아닌 첫 번째 피연산자
alert(firstName ?? lastName ?? nickName ?? "익명의 사용자"); // 바이올렛