JS Module是一种将复杂的代码分解成独立的功能单元,方便维护和协作的技术。在JS中,Module通常指代一个独立的js文件,这个文件中将某个特定的功能进行了封装,并提供了对外的接口。其他js文件可以通过这些暴露出来的接口来使用这个模块。
举例来说,有一个名为"utils.js"的模块,里面定义了一些函数用于辅助其他模块的开发。
// utils.js
export function add(a, b) {
return a + b;
}
export function substract(a, b) {
return a - b;
}
export function multiply(a, b) {
return a * b;
}
其他模块可以使用"utils.js"中提供的函数,只需要在文件中引入即可。
// main.js
import { add, substract } from './utils';
console.log(add(1, 2)); // 3
console.log(substract(5, 3)); // 2
JS模组化能够提高代码的可读性和可维护性,有助于团队协作和代码重复利用,是现代Web开发中不可缺少的一部分技术。
以下是JS Module的重点:
分离与封装程式码 - 模组提供了一个方法来将程式码结构化,并使其更易于管理和重复使用。
降低全域命名冲突的风险 - 模组可让您在不同的区域中使用相同的变量名称,从而降低全域污染和命名冲突的风险。
支援封装私有函数和变数 - 模组可让您将程式码封装起来,以防止外部访问或更改私有函数和变数。
增强代码重用性 - 模组提供了一个方法来组织和重复使用功能,使代码可读性更高,并降低了代码的复杂度。
实现高质量的代码 - 模组可使程式码更容易调试和测试,从而提高代码的品质。
支援多版本和异步加载 - 模组可使复杂的代码更容易管理,并支援多个异步模组的同步和非同步加载。
支援模组清单和依赖关系管理 - 模组可使您轻松管理和维护相互依赖的模组,并确保它们正确加载。
相容于不同环境 - 模组可在不同的 JavaScript 环境中运行,如浏览器、Node.js 和其他运行 JavaScript 的环境。
const calculator = require('./calculator');
console.log(calculator.add(1, 2)); // 3
console.log(calculator.subtract(4, 2)); // 2
console.log(calculator.multiply(3, 4)); // 12
console.log(calculator.divide(10, 5)); // 2
console.log(calculator.calculate('1+2-3*4/5')); // -0.2
答案:
// calculator.js
const add = (a, b) => a + b;
const subtract = (a, b) => a - b;
const multiply = (a, b) => a * b;
const divide = (a, b) => a / b;
const calculate = (formula) => {
let numbers = formula.split(/[\+\-\*\/]/).map(Number);
let operators = formula.split(/[1234567890\.]+/).filter(Boolean);
for (let i = 0; i < operators.length; i++) {
if (operators[i] === '*') {
numbers.splice(i, 2, numbers[i] * numbers[i+1]);
operators.splice(i, 1);
i--;
} else if (operators[i] === '/') {
numbers.splice(i, 2, numbers[i] / numbers[i+1]);
operators.splice(i, 1);
i--;
}
}
let result = numbers[0];
for (let i = 0; i < operators.length; i++) {
if (operators[i] === '+') {
result += numbers[i+1];
} else if (operators[i] === '-') {
result -= numbers[i+1];
}
}
return result;
};
module.exports = {
add,
subtract,
multiply,
divide,
calculate
};
const randomAnimation = require('./randomAnimation');
document.querySelector('#button1').addEventListener('click', () => {
randomAnimation.fadeOut('box1');
});
document.querySelector('#button2').addEventListener('click', () => {
randomAnimation.colorCycle('box2');
});
document.querySelector('#button3').addEventListener('click', () => {
randomAnimation.shake('box3');
});
答案:
// randomAnimation.js
const fadeOut = (elementId) => {
document.querySelector(`#${elementId}`).style.opacity = 1;
let opacity = 1;
let intervalId = setInterval(() => {
opacity -= 0.1;
document.querySelector(`#${elementId}`).style.opacity = opacity;
if (opacity <= 0) {
clearInterval(intervalId);
}
}, 50);
};
const colorCycle = (elementId) => {
let currentColorIndex = 0;
let colors = ['#FF0000', '#00FF00', '#0000FF', '#FFFF00', '#00FFFF', '#FF00FF'];
let intervalId = setInterval(() => {
document.querySelector(`#${elementId}`).style.backgroundColor = colors[currentColorIndex];
currentColorIndex = (currentColorIndex + 1) % colors.length;
}, 200);
};
const shake = (elementId) => {
let positions = [{x:0, y:0}, {x:5, y:5}, {x:-5, y:-5}, {x:5, y:-5}, {x:-5, y:5}, {x:5, y:0}, {x:-5, y:0}, {x:0, y:5}, {x:0, y:-5}];
let originalPosition = {x: document.querySelector(`#${elementId}`).offsetLeft, y: document.querySelector(`#${elementId}`).offsetTop};
let currentPositionIndex = 0;
let intervalId = setInterval(() => {
let newPosition = {x: originalPosition.x + positions[currentPositionIndex].x, y: originalPosition.y + positions[currentPositionIndex].y};
document.querySelector(`#${elementId}`).style.left = `${newPosition.x}px`;
document.querySelector(`#${elementId}`).style.top = `${newPosition.y}px`;
currentPositionIndex = (currentPositionIndex + 1) % positions.length;
}, 50);
};
module.exports = {
fadeOut,
colorCycle,
shake
};
const cart = require('./cart');
cart.add({name: 'shirt', price: 20});
cart.add({name: 'pants', price: 30});
console.log(cart.totalPrice()); // 50
cart.remove('shirt');
console.log(cart.totalPrice()); // 30
cart.clear();
console.log(cart.totalPrice()); // 0
答案:
// cart.js
let items = [];
const add = (item) => {
items.push(item);
};
const remove = (itemName) => {
items = items.filter((item) => item.name !== itemName);
};
const totalPrice = () => {
return items.reduce((sum, item) => sum + item.price, 0);
};
const clear = () => {
items = [];
};
module.exports = {
add,
remove,
totalPrice,
clear
};
const videoPlayer = require('./videoPlayer');
videoPlayer.setVideo('path/to/video.mp4');
document.querySelector('#playButton').addEventListener('click', () => {
videoPlayer.play();
});
document.querySelector('#pauseButton').addEventListener('click', () => {
videoPlayer.pause();
});
document.querySelector('#skipBackButton').addEventListener('click', () => {
videoPlayer.skip(-10);
});
document.querySelector('#skipForwardButton').addEventListener('click', () => {
videoPlayer.skip(10);
});
document.querySelector('#fullScreenButton').addEventListener('click', () => {
videoPlayer.fullScreen();
});
答案:
// videoPlayer.js
let videoUrl = '';
let isPlaying = false;
let currentTime = 0;
let volume = 0.5;
const setVideo = (url) => {
videoUrl = url;
document.querySelector('#videoElement').setAttribute('src', url);
};
const play = () => {
if (isPlaying) return;
document.querySelector('#videoElement').play();
isPlaying = true;
};
const pause = () => {
if (!isPlaying) return;
document.querySelector('#videoElement').pause();
isPlaying = false;
};
const skip = (seconds) => {
let newTime = document.querySelector('#videoElement').currentTime + seconds;
if (newTime < 0) {
newTime = 0;
} else if (newTime > document.querySelector('#videoElement').duration) {
newTime = document.querySelector('#videoElement').duration;
}
document.querySelector('#videoElement').currentTime = newTime;
};
const fullScreen = () => {
document.querySelector('#videoElement').requestFullscreen();
};
const setVolume = (value) => {
volume = value;
document.querySelector('#videoElement').volume = volume;
};
module.exports = {
setVideo,
play,
pause,
skip,
fullScreen,
setVolume
};
const waterfall = require('./waterfall');
const images = ['path/to/image1.jpg', 'path/to/image2.jpg', 'path/to/image3.jpg', ...];
let currentPage = 0;
let loading = false;
let loadedAll = false;
window.addEventListener('scroll', () => {
if (loading || loadedAll) return;
if (window.innerHeight + window.scrollY >= document.body.offsetHeight) {
loadNextPage();
}
});
const loadNextPage = async () => {
currentPage++;
loading = true;
const newImages = [];
// 模拟从API中加载图片
for (let i = 0; i < 10; i++) {
const imageIndex = (currentPage - 1) * 10 + i;
if (imageIndex >= images.length) {
loadedAll = true;
break;
}
newImages.push(await loadImage(images[imageIndex]));
}
waterfall.addImages(newImages);
loading = false;
}
const loadImage = (url) => {
return new Promise((resolve, reject) => {
const image = new Image();
image.addEventListener('load', () => {
resolve(image);
});
image.src = url;
});
};
答案:
// waterfall.js
let columns = [];
const columnCount = 3;
const margin = 10;
const container = document.querySelector('#container');
const addImages = (images) => {
images.forEach((image) => {
const columnIndex = getLowestColumnIndex();
const left = columnIndex * (image.width + margin);
const top = columns[columnIndex].height + margin;
const imageElement = document.createElement('img');
imageElement.setAttribute('src', image.src);
imageElement.style.position = 'absolute';
imageElement.style.left = `${left}px`;
imageElement.style.top = `${top}px`;
container.appendChild(imageElement);
columns[columnIndex].height = top + image.height;
columns[columnIndex].images.push(imageElement);
});
};
const getLowestColumnIndex = () => {
let columnIndex = 0;
for (let i = 1; i < columns.length; i++) {
if (columns[i].height < columns[columnIndex].height) {
columnIndex = i;
}
}
return columnIndex;
};
const initialize = () => {
columns = [];
for (let i = 0; i < columnCount; i++) {
columns.push({height: 0, images: []});
}
};
initialize();
module.exports = {
addImages
};