2023년 7월 11일 화요일

매우 유용한 자바 스크립트 트릭

1. JS 파일을 동적으로 로드

일부 특수 시나리오, 특히 일부 라이브러리 및 프레임워크 개발에서 JS 파일을 동적으로 로드하고 실행하는 경우가 있습니다. 다음은 Promise를 사용한 간단한 캡슐화입니다.

function loadJS(files, done) {
// Get the head tag
const head = document. getElementsByTagName('head')[0];
Promise.all(files.map(file => {
return new Promise(resolve => {
// create script tag and add to head
const s = document.createElement('script');
s.type = "text/javascript";
s.async = true;
s.src = file;
// Listen to the load event, resolve if the loading is complete
s. addEventListener('load', (e) => resolve(), false);
head.appendChild(s);
});
})).then(done); // everything is done, execute the user's callback event
}
loadJS(["test1.js", "test2.js"], () => {
// user's callback logic
});There are two core points in the code above. One is to use Promise to process asynchronous logic, but to use script tags to load and execute js.


2. 템플릿 엔진 구현

다음 예제에서는 동적 템플릿 렌더링 엔진을 구현하는 데 코드를 거의 사용하지 않습니다. 일반 동적 변수의 대체를 지원할 뿐만 아니라 for 루프, if 판단 등을 포함한 동적 JS 구문 논리도 지원합니다.

// This is a dynamic template that contains js code
var template =
'My avorite sports:' +
'<%if(this.showSports) {%>' +
'<% for(var index in this.sports) { %>' +
'<a><%this.sports[index]%></a>' +
'<%}%>' +
'<%} else {%>' +
'<p>none</p>' +
'<%}%>';
// This is the function string we're going to concatenate
const code = `with(obj) {
var r=[];
r.push("My avorite sports:");
if(this. showSports) {
for(var index in this. sports) {
r. push("<a>");
r.push(this.sports[index]);
r. push("</a>");
}
} else {
r.push("<span>none</span>");
}
return r.join("");
}`

// dynamically rendered data
const options = {
sports: ["swimming", "basketball", "football"],
showSports: true
}
// Build a feasible function and pass in parameters to change the direction of this when the function is executed
result = new Function("obj", code).apply(options, [options]);
console. log(result);


3. reduce를 사용하여 데이터 구조 변환

때때로 프론트엔드는 프론트엔드의 비즈니스 로직에 적응하기 위해 백엔드의 데이터를 변환하거나 구성 요소의 데이터 형식을 변환한 다음 처리를 위해 백엔드로 전달해야 하며 reduce는 매우 강력한 도구입니다.

const arr = [
{ classId: "1", name: "Jack", age: 16 },
{ classId: "1", name: "Jon", age: 15 },
{ classId: "2", name: "Jenny", age: 16 },
{ classId: "3", name: "Jim", age: 15 },
{ classId: "2", name: "Zoe", age: 16 }
];
groupArrayByKey(arr, "classId");
function groupArrayByKey(arr = [], key) {
return arr.reduce((t, v) => (!t[v[key]] && (t[v[key]] = []), t[v[key]].push(v), t), {})
}


4. 기본값 추가

메서드에서 사용자가 매개 변수를 전달해야 하는 경우가 있습니다. 일반적으로 두 가지 방법으로 대처할 수 있습니다. 사용자가 전달하지 않으면 일반적으로 기본값을 제공하거나 사용자가 매개 변수를 전달해야하며 전달되지 않으면 오류가 발생합니다.

function double() {
return value *2
}
// If not passed, give a default value of 0
function double(value = 0) {
return value * 2
}
// The user must pass a parameter, and an error will be thrown if no parameter is passed
const required = () => {
throw new Error("This function requires one parameter.")
}
function double(value = required()) {
return value * 2
}
double(3) // 6
double() // throw Error

listen 메소드는 NodeJS 네이티브 http 서비스를 생성하고 포트를 수신하고, 서비스의 콜백 함수에 컨텍스트를 생성한 후 사용자가 등록한 콜백 함수를 호출하고 생성된 컨텍스트를 전달하는 데 사용됩니다. 이전에 createContext와 handleRequest의 구현을 살펴보자.


5. 함수는 한 번만 실행됩니다.

경우에 따라 특정 함수를 한 번만 실행할 수 있거나 바인딩된 메서드를 한 번만 실행할 수 있는 특별한 시나리오가 있습니다.

export function once (fn) {
// Use the closure to determine whether the function has been executed
let called = false
return function () {
if (! called) {
called = true
fn. apply(this, arguments)
}
}
}


6. Realize Curring

JavaScript에서 커리는 여러 인수를 취하는 함수를 하나의 인수 만 취하는 일련의 함수로 변환하는 프로세스입니다. 이를 통해 함수를 보다 유연하게 사용할 수 있고, 코드 중복을 줄이며, 코드 가독성을 높일 수 있습니다.

function curry(fn) {
return function curried(...args) {
if (args.length >= fn.length) {
return fn.apply(this, args);
} else {
return function(...args2) {
return curried.apply(this, args.concat(args2));
};
}
};
}
function add(x, y) {
return x + y;
}
const curriedAdd = curry(add);
console.log(curriedAdd(1)(2)); // output 3
console.log(curriedAdd(1, 2)); // output 3

currying을 통해 유효성 검사, 캐싱 등과 같은 몇 가지 일반적인 기능을 모듈화할 수 있습니다. 이렇게 하면 코드의 유지 관리 용이성과 가독성이 향상되고 오류 가능성이 줄어듭니다.


7. 싱글톤 모드 구현

JavaScript의 싱글톤 모드는 일반적으로 사용되는 디자인 모드입니다. 클래스에 인스턴스가 하나만 있는지 확인하고 인스턴스에 대한 전역 액세스 지점을 제공할 수 있습니다. JS에는 쇼핑 카트, 캐시 개체, 전역 상태 관리 등과 같은 광범위한 응용 시나리오가 있습니다.

let cache;
class A {
// ...
}
function getInstance() {
if (cache) return cache;
return cache = new A();
}
const x = getInstance();
const y = getInstance();
console.log(x === y); // true


8. CommonJs 사양 구현

CommonJS 사양의 핵심 아이디어는 각 파일을 모듈로 취급하고, 각 모듈에는 자체 범위가 있으며, 그 안의 변수, 함수 및 객체는 비공개이며 외부에서 액세스할 수 없습니다. 모듈의 데이터에 액세스하려면 export and require를 수행해야 합니다.

// id: full file name
const path = require('path');
const fs = require('fs');
function Module(id){
// Used to uniquely identify the module
this.id = id;
// Properties and methods used to export modules
this.exports = {};
}
function myRequire(filePath) {
// Directly call the static method of Module to load the file
return Module._load(filePath);
}
Module._cache = {};
Module._load = function(filePath) {
// First address the absolute path of the file through the filePath passed in by the user
// Because in CommnJS, the unique identifier of the module is the absolute path of the file
const realPath = Module._resoleveFilename(filePath);
// Cache priority, if it exists in the cache, it will directly return the exports property of the module
let cacheModule = Module._cache[realPath];
if(cacheModule) return cacheModule. exports;
// If it is loaded for the first time, a new module is required, and the parameter is the absolute path of the file
let module = new Module(realPath);
// Call the load method of the module to compile the module
module.load(realPath);
return module. exports;
}
// The node file is not discussed yet
Module._extensions = {
// Process the js file
".js": handleJS,
// process the json file
".json": handleJSON
}
function handleJSON(module) {
// If it is a json file, read it directly with fs.readFileSync,
// Then use JSON.parse to convert and return directly
const json = fs.readFileSync(module.id, 'utf-8')
module.exports = JSON.parse(json)
}
function handleJS(module) {
const js = fs. readFileSync(module. id, 'utf-8')
let fn = new Function('exports', 'myRequire', 'module', '__filename', '__dirname', js)
let exports = module. exports;
// The assembled function can be executed directly
fn.call(exports, exports, myRequire, module, module.id, path.dirname(module.id))
}
Module._resolveFilename = function (filePath) {
// Splice the absolute path, and then search it, if it exists, it will return
let absPath = path. resolve(__dirname, filePath);
let exists = fs.existsSync(absPath);
if (exists) return absPath;
// If it does not exist, try splicing .js, .json, .node in sequence
let keys = Object.keys(Module._extensions);
for (let i = 0; i < keys. length; i++) {
let currentPath = absPath + keys[i];
if (fs.existsSync(currentPath)) return currentPath;
}
};
Module.prototype.load = function(realPath) {
// Get the file extension and hand it over to the corresponding method for processing
let extname = path.extname(realPath)
Module._extensions[extname](this)
}

위의 내용은 CommonJs 사양의 간단한 구현입니다. 코어는 범위의 격리를 해결하고 Myrequire 메서드를 제공하여 메서드와 속성을 로드합니다.


9. 재귀적으로 개체 속성 가져오기

가장 널리 사용되는 디자인 패턴을 선택한다면 관찰자 패턴을 선택합니다. 내가 만난 가장 알고리즘적인 사고를 선택한다면 그것은 재귀 일 것입니다. 재귀는 원래 문제를 동일한 구조를 가진 구조로 나눕니다. 하위 문제를 해결 한 다음 이러한 하위 문제를 차례로 해결하고 하위 문제의 결과를 결합하여 최종적으로 원래 문제에 대한 답을 얻습니다.

const user = {
info: {
name: "Jacky",
address: { home: "MLB", company: "AI" },
},
};
// obj is the object to get the property, path is the path, and fallback is the default value
function get(obj, path, fallback) {
const parts = path. split(".");
const key = parts. shift();
if (typeof obj[key] !== "undefined") {
return parts. length > 0 ?
get(obj[key], parts. join("."), fallback) :
obj[key];
}
// return fallback if key not found
return fallback;
}
console.log(get(user, "info.name")); // Jacky
console.log(get(user, "info.address.home")); // MLB
console.log(get(user, "info.address.company")); // AI
console.log(get(user, "info.address.abc", "fallback")); // fallback


10. 임의의 문자열 생성

const randomString = () => Math.random().toString(36).slice(2)

randomString() // gi1qtdego0b
randomString() // f3qixv40mot
randomString() // eeelv1pm3ja


11. HTML 특수 문자 이스케이프

const escape = (str) => str.replace(/[&<>"']/g, (m) => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' }[m]))

escape('<div class="medium">Hi Medium.</div>') 
// &lt;div class=&quot;medium&quot;&gt;Hi Medium.&lt;/div&gt


12. 문자열을 camelCase로 변환

const toCamelCase = (str) => str.trim().replace(/[-_\s]+(.)?/g, (_, c) => (c ? c.toUpperCase() : ''));

toCamelCase('background-color'); // backgroundColor
toCamelCase('-webkit-scrollbar-thumb'); // WebkitScrollbarThumb
toCamelCase('_hello_world'); // HelloWorld
toCamelCase('hello_world'); // helloWorld


13. 두 숫자 사이의 임의의 정수 구하기

const random = (min, max) => Math.floor(Math.random() * (max - min + 1) + min)

random(1, 50) // 25
random(1, 50) // 34


14. 인수의 평균 값 구하기

const average = (...args) => args.reduce((a, b) => a + b) / args.length;

average(1, 2, 3, 4, 5);   // 3


15. 임의의 헥사 색상 생성

const randomColor = () => `#${Math.random().toString(16).slice(2, 8).padEnd(6, '0')}`

randomColor() // #9dae4f
randomColor() // #6ef10e


16. 다크 모드 감지

const isDarkMode = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches


17. Get the mouse selection

const getSelectedText = () => window.getSelection().toString()
getSelectedText()


18. Convert rgba to hexadecimal OR hexadecimal to rgba

const rgbaToHex = (r, g, b) => "#" + [r, g, b].map(num => parseInt(num).toString(16).padStart(2, '0')).join('')
rgbaToHex(0, 0 ,0) // #000000
rgbaToHex(255, 0, 127) //#ff007f
const hexToRgba = hex => {
const [r, g, b] = hex.match(/\w\w/g).map(val => parseInt(val, 16))
return `rgba(${r}, ${g}, ${b}, 1)`;
}
hexToRgba('#000000') // rgba(0, 0, 0, 1)
hexToRgba('#ff007f') // rgba(255, 0, 127, 1)


19. Generate a random string of specified length

const generateRandomString = length => [...Array(length)].map(() => Math.random().toString(36)[2]).join('')
generateRandomString(12) // cysw0gfljoyx
generateRandomString(12) // uoqaugnm8r4s


20. Clear all cookies

const clearCookies = document.cookie.split(';').forEach(cookie => document.cookie = cookie.replace(/^ +/, '').replace(/=.*/, `=;expires=${new Date(0).toUTCString()};path=/`))


21. Determine if the current tab is active or not

const checkTabInView = () => !document.hidden


22. Check if an element is focused

const isFocus = (ele) => ele === document.activeElement









2023년 6월 11일 일요일

잘알려지지 않은 유용한 JS API

 1. Page Visibility API

    사용자가 창을 최소화하거나 최대화하거나 탭을 전환하는지 여부에 관계없이 페이지의

    표시 상태가 변경될 때마다 이벤트를 발생

    * 활용

    사용자가 페이지에서 벗어날 때 비디오, 이미지 회전 또는 애니메이션을 일시 중지

    페이지에 API의 실시간 데이터가 표시되는 경우 사용자가 떠날 때 실시간 표시 동작을

    일시적으로 중지 등

document.addEventListener("visibilitychange", () => {
if (document.visibilityState === "visible") {
// page is visible
} else {
// page is hidden
}
});


2. Web Share API

운영 체제의 기본 공유 메커니즘에 액세스할 수 있으며, 이는 모바일 사용자에게 특히 유용합니다. 이 API를 사용하면 자체 공유 메커니즘을 만들거나 타사 공유 메커니즘을 사용하지 않고도 텍스트, 링크 및 파일을 공유

<div id="app">
<video controls id="video">
<source src="./yoshi.mp4" />
</video>
<div id="quote"></div>
<button type="button" id="share-button">Share Quote</button>
</div>
const shareButton = document.querySelector("#share-button");
const shareQuote = async (shareData) => {
try {
await navigator.share(shareData);
} catch (error) {
console.error(error);
}
};
const shareButton = document.querySelector("#share-button");
const shareQuote = async (shareData) => {
try {
await navigator.share(shareData);
} catch (error) {
console.error(error);
}
};
shareButton.addEventListener("click", () => {
let shareData = {
title: "A Beautiful Quote",
text: quote.textContent,
url: location.href,
};
shareQuote(shareData);
});


3. Broadcast Channel API

브라우저 컨텍스트는 서로 기본 데이터를 주고받을 수 있습니다. 브라우저 컨텍스트는 탭, 창 또는 페이지를 표시할 수 있는 모든 위치와 같은 요소를 나타냅니다. 보안상의 이유로 브라우저 컨텍스트 간의 통신은 출처가 같고 사용되지 않는 한 허용되지 않습니다. 동일한 출처의 두 브라우저 컨텍스트의 경우 해당 URL은 동일한 프로토콜(예: ), 도메인(예: ) 및 포트(예: )를 가져야 합니다.

    * 활용

    모든 탭에서 사용자를 로그인하거나 로그아웃합.

    자산이 업로드되는 시기를 감지하고 모든 페이지에 표시


4. Internationalization API

단순히 웹 페이지의 텍스트를 필요한 언어로 번역하는 것만으로는 날짜, 숫자, 단위 등과 같은 것들이 있기 때문에 해당 언어를 사용하는 사람들이 콘텐츠를 사용할 수 있도록 하는 것만으로는 충분하지 않습니다. 국가마다 다르며 변경될 수 있습니다.

const logDate = (locale) => {
const newDate = new Date("2022-10-24"); // YY/MM/DD
const dateTime = new Intl.DateTimeFormat(locale, {timeZone: "UTC"});
const formatedDate = dateTime.format(newDate);
console.log(formatedDate);
};
logDate("en-US"); // 10/24/2022
logDate("de-DE"); // 24.10.2022
logDate("zh-TW"); // 2022/10/24

5. Intersection Observer API

The Intersection Observer API is an API provided by modern browsers for monitoring the intersection state of DOM elements. Intersection Observer API, we can easily determine whether an element is entering or leaving the visible area, thus enabling various interactive effects and lazy loading, etc.

* Image lazy loading — where images are loaded only when they are scrolled to visibility.

* Infinite scrolling of content — that is, the user scrolls near the bottom of the content and loads more directly without the user having to turn the page, giving the user the illusion that the page can scroll infinitely.

* Detection of ad exposure — in order to calculate ad revenue, it is necessary to know the exposure of ad elements.

* Execute tasks or play animations when the user sees a certain area.

// Target elements
const targetElement = document.querySelector(".target");

// Create Intersection Observer
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
console.log("The target element enters the visible area.");
} else {
console.log("The target element leaves the visible area.");
}
});
},
{
root: null,
rootMargin: "0px",
threshold: 0.5,
}
);
// Start observing the target element
observer.observe(targetElement);

In this example, a target element is first selected using the method. Then an instance of Intersection Observer is created and a callback function is passed in that will be triggered when the target element enters or leaves the visible area.querySelector

Finally, the observation of the target element is started by calling the method. When the target element enters or leaves the visible area, the corresponding code in the callback function will be executed and the corresponding message will be printed to the console.observe


The following is a description of the parameters of the Intersection Observer API:

1.callback

Callback function for specifying an observer that is triggered when a target element enters or leaves an intersection.

The callback function takes one argument, the array, which contains one or more IntersectionObserverEntry objects, each representing the intersection state of a target element.entries

2.options

root: specifies the root element, the ancestor of the target element whose intersection state will be observed, the default is the viewport.

rootMargin: specifies the root element's boundary offset, which is used to expand or reduce the size of the intersection area.

threshold: specifies a threshold or an array of thresholds indicating the percentage of visibility of the target element to be used to trigger the callback function. For example, 0.5 means that the callback is triggered when the target element is at least half visible.

<img data-src="image.jpg" />

<script>
const observer = new IntersectionObserver((entries, observer) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
observer.unobserve(img);
}
});
});
document.querySelectorAll("img").forEach((img) => {
observer.observe(img);
});
</script>

In this example, we add a attribute to the image element to store the image's real address. Then a new IntersectionObserver instance is created to watch all the image elements. When an image element enters the visible area, we assign the attribute to the attribute, thus enabling lazy loading of images.data-srcdata-srcsrc


Infinite scrolling is a common UI design that allows users to load infinitely more content as they scroll. We can achieve infinite scrolling by listening to whether the last element enters the visible area or not.

<div id="content">
<div class="item">Item 1</div>
<div class="item">Item 2</div>
<div class="item">Item 3</div>
<!-- ... -->
<div class="item">Item N</div>
</div>

<script>
const content = document.getElementById("content");
const observer = new IntersectionObserver(
(entries, observer) => {
entries.forEach((entry) => {
if (entry.isIntersecting && entry.target === content.lastElementChild) {
// Load more content
}
});
},
{
root: null,
rootMargin: "0px",
threshold: 1.0,
}
);
observer.observe(content.lastElementChild);
</script>

In the above code, we add an IntersectionObserver instance to the last element, so that we can trigger the load more content action when the last element enters the visible area.


By listening to whether an element enters or leaves the viewable area, we can achieve some interesting effects, such as following the navigation bar.

<header>
<!-- Navigation bar -->
</header>
<section class="content">
<!-- Page content -->
</section>
<script>
const header = document.querySelector("header");
const content = document.querySelector(".content");
const observer = new IntersectionObserver(
(entries, observer) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
header.classList.add("fixed");
} else {
header.classList.remove("fixed");
}
});
},
{
root: null,
rootMargin: "-100px",
threshold: 0,
}
);
observer.observe(content);
</script>

In this example, we create an instance of IntersectionObserver to observe the page content elements. When the page content element enters the viewable area, we have the navigation bar fixed at the top of the page. When the page content element leaves the viewable area, we let the navigation bar resume its original position.


Pros and Cons

The benefits of Intersection Observer API include:

Ability to implement various kinds of interactive effects and lazy loading and other functions to improve user experience.

Ability to optimize page performance and avoid unnecessary network requests and calculations.

Disadvantages of Intersection Observer API include:

Poor compatibility, need to use polyfill for compatibility.

May affect page performance and cause browsers to trigger callback functions frequently if too many target elements are listened to.



Enhance Your Mobile Web Pages with 12 JavaScript APIs


Blob API

Blob API는 이진 데이터를 처리하는 데 사용되며 데이터를 Blob 개체로 쉽게 변환하거나 Blob 개체에서 데이터를 읽을 수 있습니다.

// Create a Blob object
const myBlob = new Blob(["Hello, world!"], { type: "text/plain" });
// Read the data of the Blob object
const reader = new FileReader();
reader. addEventListener("loadend", () => {
console.log(reader.result);
});
reader.readAsText(myBlob);


WeakSet

WeakSet은 Set과 비슷하지만 약하게 참조된 개체를 저장할 수 있습니다. 즉, 개체를 가리키는 다른 참조가 없는 경우 WeakSet에서 수동으로 제거할 필요 없이 가비지 수집기에서 개체를 회수할 수 있습니다.

const myWeakSet = new WeakSet();
const obj1 = {};
const obj2 = {};
myWeakSet.add(obj1);
myWeakSet.add(obj2);
console.log(myWeakSet.has(obj1)); // true
obj1 = null;
console.log(myWeakSet.has(obj1)); // false

사용 시나리오: 경우에 따라 일부 임시 개체를 저장해야 할 수 있지만 이러한 개체가 너무 많은 메모리를 차지하지 않도록 합니다. 이러한 개체는 WeakSet을 사용하여 쉽게 관리할 수 있습니다.


TextEncoder 및 TextDecoder

TextEncoder 및 TextDecoder는 문자열과 바이트 시퀀스 간의 변환을 처리하는 데 사용됩니다. 문자열을 바이트 시퀀스로 인코딩하거나 바이트 시퀀스를 문자열로 디코딩하는 데 편리합니다.

const encoder = new TextEncoder();
const decoder = new TextDecoder();
const myString = "Hello, world!";
const myBuffer = encoder.encode(myString);
console.log(myBuffer); // Uint8Array(13) [72, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100, 33]
const decodedString = decoder.decode(myBuffer);
console.log(decodedString); // "Hello, world!"

사용 시나리오: 웹 응용 프로그램에서는 문자열을 이진 데이터로 변환하거나 이진 데이터를 문자열로 변환해야 할 수 있습니다. 이러한 변환은 TextEncoder 및 TextDecoder를 사용하여 편리하게 수행됩니다.


Proxy API

프록시 API를 사용하여 개체 속성 읽기 및 할당과 같은 작업을 가로챌 수 있는 프록시 개체를 만들 수 있습니다. 이 함수는 메타프로그래밍 및 데이터 하이재킹과 같은 기능을 구현하는 데 사용할 수 있습니다.

const myObject = {
name: "John",
age: 30,
};
const myProxy = new Proxy(myObject, {
get(target, property) {
console.log(`Getting property ${property}`);
return target[property];
},
set(target, property, value) {
console.log(`Setting property ${property} to ${value}`);
target[property] = value;
},
});
console.log(myProxy.name); // "John"
myProxy.age = 31; // Setting property age to 31

사용 시나리오: 경우에 따라 고급 기능을 달성하기 위해 개체 속성 읽기 및 할당과 같은 작업을 가로채야 할 수 있습니다. 이러한 기능은 프록시 API를 사용하여 쉽게 구현할 수 있습니다.


Object.entries() 및 Object.values()

Object.entries()는 객체의 열거 가능한 속성 및 값의 배열을 가져오는 데 사용되며 Object.values()는 객체의 열거 가능한 속성 값의 배열을 가져오는 데 사용됩니다.

const myObject = {
name: "John",
age: 30,
};
console.log(Object.entries(myObject)); // [["name", "John"], ["age", 30]]
console.log(Object.values(myObject)); // ["John", 30]

사용 시나리오: 경우에 따라 개체의 열거 가능한 속성 또는 속성 값을 가져와야 할 수 있습니다. 이러한 함수는 Object.entries() 및 Object.values()를 사용하여 쉽게 구현할 수 있습니다.


IntersectionObserver (교차 관찰자)

IntersectionObserver는 요소가 뷰포트에 들어오는지 여부를 감지하는 데 사용할 수 있으며 무한 스크롤 및 지연 로드와 같은 기능을 구현하는 데 사용할 수 있습니다.

Observer = new IntersectionObserver((entries, observer) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
console.log(`${entry.target.id} is now visible`);
observer.unobserve(entry.target);
}
});
});
const myElement = document.getElementById("myElement");
myObserver.observe(myElement);

사용 시나리오: 웹 응용 프로그램에서는 무한 스크롤 및 지연 로딩과 같은 기능을 구현해야 할 수 있으며 이러한 기능은 IntersectionObserver를 사용하여 쉽게 실현할 수 있습니다.


Symbol

Symbol은 고유 식별자를 만드는 데 사용할 수 있으며 개체의 개인 속성 또는 메서드를 정의하는 데 사용할 수 있습니다.

const mySymbol = Symbol("mySymbol");
const myObject = {
[mySymbol]: "This is a private property",
publicProperty: "This is a public property",
};
console.log(myObject[mySymbol]); // "This is a private property"
console.log(myObject.publicProperty); // "This is a public property"

사용 시나리오: 경우에 따라 개체의 개인 속성 또는 메서드를 정의해야 할 수 있으며, 이는 Symbol을 사용하여 쉽게 실현할 수 있습니다.


Reflect 

Reflect API는 동적으로 메서드 또는 객체 생성자를 호출하는 것과 같은 메타 프로그래밍을 구현하는 데 사용할 수 있습니다.

class MyClass {
constructor(value) {
this.value = value;
}
getValue() {
return this.value;
}
}
const myObject = Reflect.construct(MyClass, ["Hello, world!"]);
const myMethod = Reflect.get(myObject, "getValue");
const myValue = myMethod.call(myObject);
console.log(myValue); // "Hello, world!"

사용 시나리오: 경우에 따라 개체의 메서드 또는 생성자를 동적으로 호출해야 할 수 있으며, 이는 Reflect API를 사용하여 쉽게 실현할 수 있습니다.


 Generator API

생성기 API는 비동기 작업 또는 지연 계산을 구현하는 데 사용할 수 있는 반복자를 생성하는 데 사용할 수 있습니다.

function* myGenerator() {
yield "Hello";
yield "world";
yield "!";
}
const myIterator = myGenerator();
console.log(myIterator.next().value); // "Hello"
console.log(myIterator.next().value); // "world"
console.log(myIterator.next().value); // "!"

사용 시나리오: 경우에 따라 비동기 작업 또는 지연 계산을 구현해야 할 수 있으며 이러한 함수는 생성기 API를 사용하여 쉽게 구현할 수 있습니다.


Web Workers

웹 작업자는 백그라운드 스레드에서 JavaScript 코드를 실행하는 데 사용할 수 있으며, 이를 사용하여 성능을 향상시키거나 복잡한 계산을 구현할 수 있습니다.


// main.js
const myWorker = new Worker("worker.js");
myWorker.postMessage("Hello, worker!");
myWorker.onmessage = (event) => {
console.log(`Message received from worker: ${event.data}`);
};
// worker.js
onmessage = (event) => {
console.log(`Message received in worker: ${event.data}`);
postMessage("Hello, main!");
};

사용 시나리오: 웹 응용 프로그램에서는 계산 집약적인 작업을 많이 처리하거나 장기 실행 작업을 수행해야 할 수 있습니다. 웹 작업자를 사용하면 성능이 향상되거나 사용자 인터페이스 차단을 방지할 수 있습니다.


AudioContext

AudioContext는 오디오를 처리하는 데 사용할 수 있으며 오디오 재생 및 음향 효과 처리와 같은 함수를 구현하는 데 사용할 수 있습니다.

const audioContext = new AudioContext();
fetch("https://example.com/audio.mp3")
.then((response) => response.arrayBuffer())
.then((arrayBuffer) => audioContext.decodeAudioData(arrayBuffer))
.then((audioBuffer) => {
const source = audioContext.createBufferSource();
source.buffer = audioBuffer;
source.connect(audioContext.destination);
source.start();
});

사용 시나리오: 웹 응용 프로그램에서는 오디오 재생 및 음향 효과 처리와 같은 기능을 구현해야 할 수 있으며 이러한 기능은 AudioContext를 사용하여 쉽게 실현할 수 있습니다.