重要前提
安装AI Skills的关键前提是:必须科学上网,且开启TUN模式,这一点至关重要,直接决定安装能否顺利完成,在此郑重提醒三遍:科学上网,科学上网,科学上网。查看完整安装教程 →
javascript-fundamentals by manutej/luxor-claude-marketplace
npx skills add https://github.com/manutej/luxor-claude-marketplace --skill javascript-fundamentals一份涵盖 JavaScript 核心概念、现代 ES6+ 特性、异步编程模式以及构建健壮应用程序的行业最佳实践的全面指南。
在以下情况下,此技能至关重要:
JavaScript 有三种声明变量的方式,每种都有不同的作用域规则:
var : 函数作用域,存在变量提升,可以重新声明
function varExample() {
var x = 1;
if (true) {
var x = 2; // 同一个变量!
console.log(x); // 2
}
console.log(x); // 2
}
let : 块级作用域,不会提升到可用状态,不能重新声明
function letExample() {
let x = 1;
if (true) {
let x = 2; // 不同的变量
console.log(x); // 2
}
console.log(x); // 1
}
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
const : 块级作用域,必须初始化,引用不能被重新赋值
const PI = 3.14159;
// PI = 3; // 错误:赋值给常量变量
const user = { name: 'John' };
user.name = 'Jane'; // 可以 - 修改对象属性
// user = {}; // 错误 - 重新分配引用
最佳实践 : 默认使用 const,需要重新赋值时使用 let,避免使用 var。
JavaScript 有 7 种原始类型和对象:
原始类型 :
String: 文本数据Number: 整数和浮点数BigInt: 任意精度整数Boolean: true/falseundefined: 未初始化的变量null: 有意表示无值Symbol: 唯一标识符对象 : 键值对的集合,包括数组、函数、日期等。
// 类型检查
typeof "hello" // "string"
typeof 42 // "number"
typeof true // "boolean"
typeof undefined // "undefined"
typeof null // "object" (历史遗留错误!)
typeof {} // "object"
typeof [] // "object"
typeof function(){} // "function"
// 更好的数组检查
Array.isArray([]) // true
Array.isArray({}) // false
// Null 检查
value === null // 仅对 null 为 true
value == null // 对 null 和 undefined 都为 true
函数在 JavaScript 中是一等公民 - 它们可以赋值给变量、作为参数传递,并从其他函数返回。
函数声明 :
function greet(name) {
return `Hello, ${name}!`;
}
函数表达式 :
const greet = function(name) {
return `Hello, ${name}!`;
};
箭头函数 (ES6+):
const greet = (name) => `Hello, ${name}!`;
// 多个参数
const add = (a, b) => a + b;
// 单个参数(括号可选)
const double = x => x * 2;
// 多个语句(需要大括号和显式返回)
const complexFunction = (x, y) => {
const result = x + y;
return result * 2;
};
关键区别 :
this 绑定arguments 对象对象创建 :
// 对象字面量
const person = {
name: 'John',
age: 30,
greet() {
return `Hello, I'm ${this.name}`;
}
};
// 访问属性
person.name // 点表示法
person['name'] // 括号表示法(动态键)
// 添加/修改属性
person.email = 'john@example.com';
person.age = 31;
// 删除属性
delete person.email;
数组方法 :
const numbers = [1, 2, 3, 4, 5];
// 转换
numbers.map(n => n * 2) // [2, 4, 6, 8, 10]
numbers.filter(n => n > 2) // [3, 4, 5]
numbers.reduce((sum, n) => sum + n, 0) // 15
// 迭代
numbers.forEach(n => console.log(n));
// 搜索
numbers.find(n => n > 3) // 4
numbers.findIndex(n => n > 3) // 3
numbers.includes(3) // true
// 修改(改变原数组)
numbers.push(6) // 添加到末尾
numbers.pop() // 从末尾移除
numbers.unshift(0) // 添加到开头
numbers.shift() // 从开头移除
numbers.splice(2, 1) // 在索引 2 处移除 1 个元素
// 非修改性操作
numbers.slice(1, 3) // [2, 3]
numbers.concat([6, 7]) // [1, 2, 3, 4, 5, 6, 7]
[...numbers, 6, 7] // 展开运算符
闭包是一个函数,即使在外部函数返回后,它仍然可以访问其外部(封闭)词法作用域中的变量。
function createCounter() {
let count = 0; // 私有变量
return {
increment() {
return ++count;
},
decrement() {
return --count;
},
getCount() {
return count;
}
};
}
const counter = createCounter();
console.log(counter.increment()); // 1
console.log(counter.increment()); // 2
console.log(counter.getCount()); // 2
// count 无法直接访问
使用场景 :
JavaScript 使用原型继承。每个对象都有一个内部 [[Prototype]] 链接指向另一个对象。
// 构造函数
function Animal(name) {
this.name = name;
}
// 向原型添加方法
Animal.prototype.speak = function() {
return `${this.name} makes a sound`;
};
const dog = new Animal('Dog');
console.log(dog.speak()); // "Dog makes a sound"
// 继承
function Dog(name, breed) {
Animal.call(this, name); // 调用父构造函数
this.breed = breed;
}
// 建立原型链
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;
Dog.prototype.bark = function() {
return `${this.name} barks!`;
};
const myDog = new Dog('Buddy', 'Golden Retriever');
console.log(myDog.speak()); // "Buddy makes a sound" (继承的)
console.log(myDog.bark()); // "Buddy barks!" (自己的方法)
类为原型继承提供了语法糖:
class Animal {
constructor(name) {
this.name = name;
}
speak() {
return `${this.name} makes a sound`;
}
// 静态方法
static create(name) {
return new Animal(name);
}
}
class Dog extends Animal {
constructor(name, breed) {
super(name); // 调用父构造函数
this.breed = breed;
}
speak() {
return `${super.speak()} - Woof!`;
}
// Getter
get info() {
return `${this.name} is a ${this.breed}`;
}
// Setter
set nickname(value) {
this._nickname = value;
}
}
const myDog = new Dog('Buddy', 'Golden Retriever');
console.log(myDog.speak()); // "Buddy makes a sound - Woof!"
console.log(myDog.info); // "Buddy is a Golden Retriever"
myDog.nickname = 'Bud';
从数组提取值或从对象提取属性:
// 数组解构
const [first, second, ...rest] = [1, 2, 3, 4, 5];
console.log(first); // 1
console.log(second); // 2
console.log(rest); // [3, 4, 5]
// 对象解构
const user = { name: 'John', age: 30, city: 'NYC' };
const { name, age } = user;
console.log(name); // "John"
// 重命名
const { name: userName, age: userAge } = user;
// 默认值
const { country = 'USA' } = user;
// 嵌套解构
const data = {
user: { name: 'John', address: { city: 'NYC' } }
};
const { user: { address: { city } } } = data;
// 函数参数
function greet({ name, age = 0 }) {
return `${name} is ${age} years old`;
}
greet({ name: 'John', age: 30 }); // "John is 30 years old"
展开 (...) 展开元素:
// 数组
const arr1 = [1, 2, 3];
const arr2 = [...arr1, 4, 5]; // [1, 2, 3, 4, 5]
const combined = [...arr1, ...arr2];
// 对象
const obj1 = { a: 1, b: 2 };
const obj2 = { ...obj1, c: 3 }; // { a: 1, b: 2, c: 3 }
// 函数参数
Math.max(...arr1); // 3
// 浅拷贝
const copy = [...arr1];
const objCopy = { ...obj1 };
剩余 (...) 收集元素:
// 函数参数
function sum(...numbers) {
return numbers.reduce((total, n) => total + n, 0);
}
sum(1, 2, 3, 4); // 10
// 与其他参数一起使用
function multiply(multiplier, ...numbers) {
return numbers.map(n => n * multiplier);
}
multiply(2, 1, 2, 3); // [2, 4, 6]
多行字符串和字符串插值:
const name = 'John';
const age = 30;
// 字符串插值
const greeting = `Hello, ${name}!`;
// 表达式
const message = `In 5 years, you'll be ${age + 5}`;
// 多行
const multiline = `
This is a
multi-line
string
`;
// 标签模板
function highlight(strings, ...values) {
return strings.reduce((result, str, i) => {
return result + str + (values[i] ? `<mark>${values[i]}</mark>` : '');
}, '');
}
const html = highlight`Hello, ${name}! You are ${age} years old.`;
// "Hello, <mark>John</mark>! You are <mark>30</mark> years old."
可选链 (?.): 安全地访问嵌套属性:
const user = {
name: 'John',
address: {
city: 'NYC'
}
};
// 没有可选链
const city = user && user.address && user.address.city;
// 使用可选链
const city = user?.address?.city; // "NYC"
const zip = user?.address?.zip; // undefined (不会报错!)
// 与方法一起使用
user.getName?.(); // 仅当方法存在时才调用
// 与数组一起使用
const firstItem = arr?.[0];
空值合并 (??): 为 null/undefined 提供默认值:
// || 对任何假值返回右侧
const value1 = 0 || 'default'; // "default"
const value2 = '' || 'default'; // "default"
const value3 = false || 'default'; // "default"
// ?? 仅针对 null/undefined
const value4 = 0 ?? 'default'; // 0
const value5 = '' ?? 'default'; // ""
const value6 = false ?? 'default'; // false
const value7 = null ?? 'default'; // "default"
const value8 = undefined ?? 'default'; // "default"
导出 :
// 命名导出
export const PI = 3.14159;
export function add(a, b) {
return a + b;
}
export class Calculator {
// ...
}
// 导出多个
const multiply = (a, b) => a * b;
const divide = (a, b) => a / b;
export { multiply, divide };
// 默认导出(每个文件一个)
export default class App {
// ...
}
// 或者
class App { }
export default App;
导入 :
// 命名导入
import { PI, add } from './math.js';
import { multiply as mult } from './math.js'; // 重命名
// 默认导入
import App from './App.js';
// 混合默认和命名导入
import App, { PI, add } from './App.js';
// 导入全部
import * as Math from './math.js';
Math.PI;
Math.add(1, 2);
// 仅导入副作用
import './polyfills.js';
JavaScript 是单线程的,但通过事件循环处理异步操作:
console.log('1');
setTimeout(() => {
console.log('2');
}, 0);
Promise.resolve().then(() => {
console.log('3');
});
console.log('4');
// 输出: 1, 4, 3, 2
// 微任务(Promise)优先于宏任务(setTimeout)
传统的异步模式(可能导致"回调地狱"):
function fetchUser(userId, callback) {
setTimeout(() => {
callback(null, { id: userId, name: 'John' });
}, 1000);
}
function fetchPosts(userId, callback) {
setTimeout(() => {
callback(null, [{ id: 1, title: 'Post 1' }]);
}, 1000);
}
// 回调地狱
fetchUser(1, (error, user) => {
if (error) {
console.error(error);
return;
}
fetchPosts(user.id, (error, posts) => {
if (error) {
console.error(error);
return;
}
console.log(user, posts);
});
});
Promise 表示异步操作的最终完成(或失败):
// 创建 Promise
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
const success = true;
if (success) {
resolve('Success!');
} else {
reject(new Error('Failed!'));
}
}, 1000);
});
// 使用 Promise
promise
.then(result => {
console.log(result); // "Success!"
return result.toUpperCase();
})
.then(upperResult => {
console.log(upperResult); // "SUCCESS!"
})
.catch(error => {
console.error(error);
})
.finally(() => {
console.log('Cleanup');
});
// Promise 工具函数
Promise.all([promise1, promise2, promise3])
.then(results => {
// 全部解决: [result1, result2, result3]
});
Promise.race([promise1, promise2])
.then(result => {
// 第一个解决的
});
Promise.allSettled([promise1, promise2])
.then(results => {
// 全部完成(解决或拒绝)
// [{ status: 'fulfilled', value: ... }, { status: 'rejected', reason: ... }]
});
Promise.any([promise1, promise2])
.then(result => {
// 第一个兑现(解决)的
});
处理 Promise 的现代语法 (ES2017+):
async function fetchUserData(userId) {
try {
const user = await fetchUser(userId);
const posts = await fetchPosts(user.id);
const comments = await fetchComments(posts[0].id);
return { user, posts, comments };
} catch (error) {
console.error('Error:', error);
throw error;
}
}
// 使用异步函数
fetchUserData(1)
.then(data => console.log(data))
.catch(error => console.error(error));
// 并行执行
async function fetchAllData() {
const [users, posts, comments] = await Promise.all([
fetchUsers(),
fetchPosts(),
fetchComments()
]);
return { users, posts, comments };
}
// 顺序执行 vs 并行执行
async function sequential() {
const result1 = await operation1(); // 等待
const result2 = await operation2(); // 然后等待
return [result1, result2];
}
async function parallel() {
const [result1, result2] = await Promise.all([
operation1(), // 同时开始两个
operation2() // 操作
]);
return [result1, result2];
}
// 使用 async/await 的 try-catch
async function robustFetch(url) {
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
return data;
} catch (error) {
if (error.name === 'TypeError') {
console.error('Network error:', error);
} else {
console.error('Error:', error);
}
throw error; // 重新抛出或处理
}
}
// Promise catch
fetchData()
.then(data => processData(data))
.catch(error => {
// 捕获来自 fetchData 和 processData 的错误
console.error(error);
});
// 全局错误处理器
window.addEventListener('unhandledrejection', event => {
console.error('Unhandled promise rejection:', event.reason);
event.preventDefault();
});
封装私有数据并公开公共 API:
const Calculator = (function() {
// 私有变量
let history = [];
// 私有函数
function log(operation) {
history.push(operation);
}
// 公共 API
return {
add(a, b) {
const result = a + b;
log(`${a} + ${b} = ${result}`);
return result;
},
subtract(a, b) {
const result = a - b;
log(`${a} - ${b} = ${result}`);
return result;
},
getHistory() {
return [...history]; // 返回副本
},
clearHistory() {
history = [];
}
};
})();
Calculator.add(5, 3); // 8
console.log(Calculator.getHistory()); // ["5 + 3 = 8"]
模块模式的更清晰变体:
const UserManager = (function() {
// 私有
let users = [];
function findUserById(id) {
return users.find(u => u.id === id);
}
function validateUser(user) {
return user && user.name && user.email;
}
// 公共方法
function addUser(user) {
if (validateUser(user)) {
users.push(user);
return true;
}
return false;
}
function getUser(id) {
return findUserById(id);
}
function getAllUsers() {
return [...users];
}
// 揭示公共 API
return {
add: addUser,
get: getUser,
getAll: getAllUsers
};
})();
创建对象而不指定确切的类:
function createUser(name, role) {
const roles = {
admin: {
permissions: ['read', 'write', 'delete'],
level: 3
},
editor: {
permissions: ['read', 'write'],
level: 2
},
viewer: {
permissions: ['read'],
level: 1
}
};
const roleConfig = roles[role] || roles.viewer;
return {
name,
role,
...roleConfig,
hasPermission(permission) {
return this.permissions.includes(permission);
},
toString() {
return `${this.name} (${this.role})`;
}
};
}
const admin = createUser('Alice', 'admin');
const editor = createUser('Bob', 'editor');
console.log(admin.hasPermission('delete')); // true
console.log(editor.hasPermission('delete')); // false
确保只存在一个实例:
const Config = (function() {
let instance;
function createInstance() {
return {
apiUrl: 'https://api.example.com',
timeout: 5000,
retries: 3,
get(key) {
return this[key];
},
set(key, value) {
this[key] = value;
}
};
}
return {
getInstance() {
if (!instance) {
instance = createInstance();
}
return instance;
}
};
})();
const config1 = Config.getInstance();
const config2 = Config.getInstance();
console.log(config1 === config2); // true
// 现代 ES6 类版本
class Database {
constructor() {
if (Database.instance) {
return Database.instance;
}
this.connection = null;
Database.instance = this;
}
connect() {
if (!this.connection) {
this.connection = 'Connected to DB';
}
return this.connection;
}
}
const db1 = new Database();
const db2 = new Database();
console.log(db1 === db2); // true
订阅和发布事件:
class EventEmitter {
constructor() {
this.events = {};
}
on(event, listener) {
if (!this.events[event]) {
this.events[event] = [];
}
this.events[event].push(listener);
// 返回取消订阅函数
return () => this.off(event, listener);
}
off(event, listenerToRemove) {
if (!this.events[event]) return;
this.events[event] = this.events[event].filter(
listener => listener !== listenerToRemove
);
}
emit(event, ...args) {
if (!this.events[event]) return;
this.events[event].forEach(listener => {
listener(...args);
});
}
once(event, listener) {
const onceWrapper = (...args) => {
listener(...args);
this.off(event, onceWrapper);
};
this.on(event, onceWrapper);
}
}
// 使用
const emitter = new EventEmitter();
const unsubscribe = emitter.on('data', (data) => {
console.log('Received:', data);
});
emitter.emit('data', { id: 1 }); // "Received: { id: 1 }"
unsubscribe();
emitter.emit('data', { id: 2 }); // 无输出
缓存函数结果以提高性能:
function memoize(fn) {
const cache = new Map();
return function(...args) {
const key = JSON.stringify(args);
if (cache.has(key)) {
console.log('Cached result');
return cache.get(key);
}
const result = fn.apply(this, args);
cache.set(key, result);
return result;
};
}
// 计算密集型函数
function fibonacci(n) {
if (n <= 1) return n;
return fibonacci(n - 1) + fibonacci(n - 2);
}
const memoizedFib = memoize(fibonacci);
console.log(memoizedFib(40)); // 第一次慢
console.log(memoizedFib(40)); // 立即(已缓存)
// 与对象方法一起使用
const calculator = {
multiplier: 2,
calculate: memoize(function(n) {
return n * this.multiplier;
})
};
// 常量 - UPPERCASE_SNAKE_CASE
const MAX_RETRIES = 3;
const API_BASE_URL = 'https://api.example.com';
// 变量和函数 - camelCase
let userName = 'John';
function getUserData() { }
// 类 - PascalCase
class UserAccount { }
class HTTPHandler { }
// 私有约定 - 以下划线开头
class Widget {
constructor() {
this._privateProperty = 'internal';
}
_privateMethod() {
// 实现
}
}
// 布尔变量 - 使用 is/has/can 前缀
const isActive = true;
const hasPermission = false;
const canEdit = true;
// 函数 - 使用动词前缀
function getUser() { }
function setConfig() { }
function validateInput() { }
function handleClick() { }
// 自定义错误类
class ValidationError extends Error {
constructor(message, field) {
super(message);
this.name = 'ValidationError';
this.field = field;
}
}
class NetworkError extends Error {
constructor(message, statusCode) {
super(message);
this.name = 'NetworkError';
this.statusCode = statusCode;
}
}
// 抛出特定错误
function validateEmail(email) {
if (!email.includes('@')) {
throw new ValidationError('Invalid email format', 'email');
}
return true;
}
// 处理不同类型的错误
try {
validateEmail('invalid');
} catch (error) {
if (error instanceof ValidationError) {
console.error(`Validation failed for ${error.field}: ${error.message}`);
} else {
console.error('Unexpected error:', error);
}
}
// 异步错误处理
async function fetchWithRetry(url, retries = 3) {
for (let i = 0; i < retries; i++) {
try {
const response = await fetch(url);
if (!response.ok) {
throw new NetworkError('Request failed', response.status);
}
return await response.json();
} catch (error) {
if (i === retries - 1) throw error; // 最后一次重试
console.log(`Retry ${i + 1}/${retries}`);
await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1)));
}
}
}
// 1. 避免在循环中进行不必要的操作
// 不好
for (let i = 0; i < array.length; i++) { } // 每次迭代都计算长度
// 好
const len = array.length;
for (let i = 0; i < len; i++) { }
// 更好 - 使用内置方法
array.forEach(item => { });
// 2. 防抖昂贵的操作
function debounce(fn, delay) {
let timeoutId;
return function(...args) {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => fn.apply(this, args), delay);
};
}
const expensiveSearch = debounce((query) => {
// API 调用
}, 300);
// 3. 节流高频事件
function throttle(fn, limit) {
let inThrottle;
return function(...args) {
if (!inThrottle) {
fn.apply(this, args);
inThrottle = true;
setTimeout(() => inThrottle = false, limit);
}
};
}
window.addEventListener('scroll', throttle(() => {
// 处理滚动
}, 100));
// 4. 使用对象/Map 进行查找
// 不好 - O(n)
const colors = ['red', 'blue', 'green'];
colors.includes('blue'); // 线性搜索
// 好 - O(1)
const colorSet = new Set(['red', 'blue', 'green']);
colorSet.has('blue'); // 常数时间
// 5. 避免内存泄漏
// 不好 - 事件监听器未移除
element.addEventListener('click', handler);
// 好
const handler = () => { };
element.addEventListener('click', handler);
// 稍后...
element.removeEventListener('click', handler);
// 6. 使用 WeakMap 存储私有数据
const privateData = new WeakMap();
class MyClass {
constructor() {
privateData.set(this, { secret: 'value' });
}
getSecret() {
return privateData.get(this).secret;
}
}
// 当实例被垃圾回收时,WeakMap 中的条目也会被回收
// 1. 单一职责原则
// 不好 - 函数做太多事
function processUserData(userData) {
// 验证
// 转换
// 保存到数据库
// 发送邮件
// 更新 UI
}
// 好 - 分离关注点
function validateUser(userData) { }
function transformUserData(userData) { }
function saveUser(userData) { }
function sendWelcomeEmail(user) { }
function updateUI(user) { }
// 2. 纯函数(无副作用)
// 不好 - 修改输入
function addToCart(cart, item) {
cart.items.push(item);
return cart;
}
// 好 - 返回新对象
function addToCart(cart, item) {
return {
...cart,
items: [...cart.items, item]
};
}
// 3. 避免魔法数字
// 不好
if (user.role === 2) { }
// 好
const ROLES = {
ADMIN: 1,
EDITOR: 2,
VIEWER: 3
};
if (user.role === ROLES.EDITOR) { }
// 4. 使用默认参数
// 不好
function greet(name) {
name = name || 'Guest';
return `Hello, ${name}`;
}
// 好
function greet(name = 'Guest') {
return `Hello, ${name}`;
}
// 5. 使用卫语句进行提前返回
// 不好
function processOrder(order) {
if (order) {
if (order.items.length > 0) {
if (order.total > 0) {
// 处理订单
}
}
}
}
// 好
function processOrder(order) {
if (!order) return;
if (order.items.length === 0) return;
if (order.total <= 0) return;
// 处理订单
}
// 1. 清除定时器和间隔
const timerId = setTimeout(() => { }, 1000);
clearTimeout(timerId);
const intervalId = setInterval(() => { }, 1000);
clearInterval(intervalId);
// 2. 移除事件监听器
const handler = () => { };
element.addEventListener('click', handler);
element.removeEventListener('click', handler);
// 3. 完成后将引用设为 null
let largeData = fetchLargeDataset();
// 使用数据...
largeData = null; // 允许垃圾回收
// 4. 使用 WeakMap/WeakSet 进行缓存
const cache = new WeakMap();
let obj = { data: 'value' };
cache.set(obj, 'cached value');
obj = null; // 缓存条目自动移除
// 5. 避免全局变量
// 不好
var globalUser = { };
// 好 - 使用模块/闭包
(function() {
const user = { };
// 在本地使用 user
})();
// 6. 小心闭包
function createHeavyObject() {
const heavyData = new Array(1000000);
// 不好 - 闭包使 heavyData 保持在内存中
return function() {
console.log(heavyData.length);
};
// 好 - 只捕获需要的内容
const length = heavyData.length;
return function() {
console.log(length);
};
}
// 1. 编写可测试的代码 - 纯函数
// 可测试
function calculateTotal(items) {
return items.reduce((sum, item) => sum + item.price, 0);
}
// 难以测试 - 依赖外部状态
function calculateTotal() {
return cart.items.reduce((sum, item) => sum + item.price, 0);
}
// 2. 依赖注入
// 难以测试
class UserService {
constructor() {
this.api = new ApiClient();
}
}
// 易于测试 - 注入依赖
class UserService {
constructor(apiClient) {
this.api = apiClient;
}
}
A comprehensive guide to core JavaScript concepts, modern ES6+ features, asynchronous programming patterns, and industry best practices for building robust applications.
This skill is essential when:
JavaScript has three ways to declare variables, each with different scoping rules:
var : Function-scoped, hoisted, can be redeclared
function varExample() {
var x = 1;
if (true) {
var x = 2; // Same variable!
console.log(x); // 2
}
console.log(x); // 2
}
let : Block-scoped, not hoisted to usable state, cannot be redeclared
function letExample() {
let x = 1;
if (true) {
let x = 2; // Different variable
console.log(x); // 2
}
console.log(x); // 1
}
const : Block-scoped, must be initialized, reference cannot be reassigned
const PI = 3.14159;
// PI = 3; // Error: Assignment to constant variable
const user = { name: 'John' };
user.name = 'Jane'; // OK - modifying object properties
// user = {}; // Error - reassigning reference
Best Practice : Use const by default, let when reassignment is needed, avoid var.
JavaScript has 7 primitive types and objects:
Primitives :
String: Text dataNumber: Integers and floating-point numbersBigInt: Arbitrary precision integersBoolean: true/falseundefined: Uninitialized variablenull: Intentional absence of valueSymbol: Unique identifiersObjects : Collections of key-value pairs, including arrays, functions, dates, etc.
// Type checking
typeof "hello" // "string"
typeof 42 // "number"
typeof true // "boolean"
typeof undefined // "undefined"
typeof null // "object" (historical bug!)
typeof {} // "object"
typeof [] // "object"
typeof function(){} // "function"
// Better array checking
Array.isArray([]) // true
Array.isArray({}) // false
// Null checking
value === null // true only for null
value == null // true for null AND undefined
Functions are first-class citizens in JavaScript - they can be assigned to variables, passed as arguments, and returned from other functions.
Function Declaration :
function greet(name) {
return `Hello, ${name}!`;
}
Function Expression :
const greet = function(name) {
return `Hello, ${name}!`;
};
Arrow Function (ES6+):
const greet = (name) => `Hello, ${name}!`;
// Multiple parameters
const add = (a, b) => a + b;
// Single parameter (parentheses optional)
const double = x => x * 2;
// Multiple statements (need braces and explicit return)
const complexFunction = (x, y) => {
const result = x + y;
return result * 2;
};
Key Differences :
this bindingarguments objectObject Creation :
// Object literal
const person = {
name: 'John',
age: 30,
greet() {
return `Hello, I'm ${this.name}`;
}
};
// Accessing properties
person.name // Dot notation
person['name'] // Bracket notation (dynamic keys)
// Adding/modifying properties
person.email = 'john@example.com';
person.age = 31;
// Deleting properties
delete person.email;
Array Methods :
const numbers = [1, 2, 3, 4, 5];
// Transformation
numbers.map(n => n * 2) // [2, 4, 6, 8, 10]
numbers.filter(n => n > 2) // [3, 4, 5]
numbers.reduce((sum, n) => sum + n, 0) // 15
// Iteration
numbers.forEach(n => console.log(n));
// Search
numbers.find(n => n > 3) // 4
numbers.findIndex(n => n > 3) // 3
numbers.includes(3) // true
// Mutation (modify original)
numbers.push(6) // Add to end
numbers.pop() // Remove from end
numbers.unshift(0) // Add to start
numbers.shift() // Remove from start
numbers.splice(2, 1) // Remove 1 item at index 2
// Non-mutating
numbers.slice(1, 3) // [2, 3]
numbers.concat([6, 7]) // [1, 2, 3, 4, 5, 6, 7]
[...numbers, 6, 7] // Spread operator
A closure is a function that has access to variables in its outer (enclosing) lexical scope, even after the outer function has returned.
function createCounter() {
let count = 0; // Private variable
return {
increment() {
return ++count;
},
decrement() {
return --count;
},
getCount() {
return count;
}
};
}
const counter = createCounter();
console.log(counter.increment()); // 1
console.log(counter.increment()); // 2
console.log(counter.getCount()); // 2
// count is not directly accessible
Use Cases :
JavaScript uses prototypal inheritance. Every object has an internal [[Prototype]] link to another object.
// Constructor function
function Animal(name) {
this.name = name;
}
// Add method to prototype
Animal.prototype.speak = function() {
return `${this.name} makes a sound`;
};
const dog = new Animal('Dog');
console.log(dog.speak()); // "Dog makes a sound"
// Inheritance
function Dog(name, breed) {
Animal.call(this, name); // Call parent constructor
this.breed = breed;
}
// Set up prototype chain
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;
Dog.prototype.bark = function() {
return `${this.name} barks!`;
};
const myDog = new Dog('Buddy', 'Golden Retriever');
console.log(myDog.speak()); // "Buddy makes a sound" (inherited)
console.log(myDog.bark()); // "Buddy barks!" (own method)
Classes provide syntactic sugar over prototypal inheritance:
class Animal {
constructor(name) {
this.name = name;
}
speak() {
return `${this.name} makes a sound`;
}
// Static method
static create(name) {
return new Animal(name);
}
}
class Dog extends Animal {
constructor(name, breed) {
super(name); // Call parent constructor
this.breed = breed;
}
speak() {
return `${super.speak()} - Woof!`;
}
// Getter
get info() {
return `${this.name} is a ${this.breed}`;
}
// Setter
set nickname(value) {
this._nickname = value;
}
}
const myDog = new Dog('Buddy', 'Golden Retriever');
console.log(myDog.speak()); // "Buddy makes a sound - Woof!"
console.log(myDog.info); // "Buddy is a Golden Retriever"
myDog.nickname = 'Bud';
Extract values from arrays or properties from objects:
// Array destructuring
const [first, second, ...rest] = [1, 2, 3, 4, 5];
console.log(first); // 1
console.log(second); // 2
console.log(rest); // [3, 4, 5]
// Object destructuring
const user = { name: 'John', age: 30, city: 'NYC' };
const { name, age } = user;
console.log(name); // "John"
// Renaming
const { name: userName, age: userAge } = user;
// Default values
const { country = 'USA' } = user;
// Nested destructuring
const data = {
user: { name: 'John', address: { city: 'NYC' } }
};
const { user: { address: { city } } } = data;
// Function parameters
function greet({ name, age = 0 }) {
return `${name} is ${age} years old`;
}
greet({ name: 'John', age: 30 }); // "John is 30 years old"
Spread (...) expands elements:
// Arrays
const arr1 = [1, 2, 3];
const arr2 = [...arr1, 4, 5]; // [1, 2, 3, 4, 5]
const combined = [...arr1, ...arr2];
// Objects
const obj1 = { a: 1, b: 2 };
const obj2 = { ...obj1, c: 3 }; // { a: 1, b: 2, c: 3 }
// Function arguments
Math.max(...arr1); // 3
// Shallow copy
const copy = [...arr1];
const objCopy = { ...obj1 };
Rest (...) collects elements:
// Function parameters
function sum(...numbers) {
return numbers.reduce((total, n) => total + n, 0);
}
sum(1, 2, 3, 4); // 10
// With other parameters
function multiply(multiplier, ...numbers) {
return numbers.map(n => n * multiplier);
}
multiply(2, 1, 2, 3); // [2, 4, 6]
Multi-line strings and string interpolation:
const name = 'John';
const age = 30;
// String interpolation
const greeting = `Hello, ${name}!`;
// Expressions
const message = `In 5 years, you'll be ${age + 5}`;
// Multi-line
const multiline = `
This is a
multi-line
string
`;
// Tagged templates
function highlight(strings, ...values) {
return strings.reduce((result, str, i) => {
return result + str + (values[i] ? `<mark>${values[i]}</mark>` : '');
}, '');
}
const html = highlight`Hello, ${name}! You are ${age} years old.`;
// "Hello, <mark>John</mark>! You are <mark>30</mark> years old."
Optional Chaining (?.): Safely access nested properties:
const user = {
name: 'John',
address: {
city: 'NYC'
}
};
// Without optional chaining
const city = user && user.address && user.address.city;
// With optional chaining
const city = user?.address?.city; // "NYC"
const zip = user?.address?.zip; // undefined (no error!)
// With methods
user.getName?.(); // Only calls if method exists
// With arrays
const firstItem = arr?.[0];
Nullish Coalescing (??): Default values for null/undefined:
// || returns right side for ANY falsy value
const value1 = 0 || 'default'; // "default"
const value2 = '' || 'default'; // "default"
const value3 = false || 'default'; // "default"
// ?? only for null/undefined
const value4 = 0 ?? 'default'; // 0
const value5 = '' ?? 'default'; // ""
const value6 = false ?? 'default'; // false
const value7 = null ?? 'default'; // "default"
const value8 = undefined ?? 'default'; // "default"
Exporting :
// Named exports
export const PI = 3.14159;
export function add(a, b) {
return a + b;
}
export class Calculator {
// ...
}
// Export multiple
const multiply = (a, b) => a * b;
const divide = (a, b) => a / b;
export { multiply, divide };
// Default export (one per file)
export default class App {
// ...
}
// Or
class App { }
export default App;
Importing :
// Named imports
import { PI, add } from './math.js';
import { multiply as mult } from './math.js'; // Rename
// Default import
import App from './App.js';
// Mix default and named
import App, { PI, add } from './App.js';
// Import all
import * as Math from './math.js';
Math.PI;
Math.add(1, 2);
// Import for side effects only
import './polyfills.js';
JavaScript is single-threaded but handles async operations through the event loop:
console.log('1');
setTimeout(() => {
console.log('2');
}, 0);
Promise.resolve().then(() => {
console.log('3');
});
console.log('4');
// Output: 1, 4, 3, 2
// Microtasks (Promises) have priority over macrotasks (setTimeout)
Traditional async pattern (can lead to "callback hell"):
function fetchUser(userId, callback) {
setTimeout(() => {
callback(null, { id: userId, name: 'John' });
}, 1000);
}
function fetchPosts(userId, callback) {
setTimeout(() => {
callback(null, [{ id: 1, title: 'Post 1' }]);
}, 1000);
}
// Callback hell
fetchUser(1, (error, user) => {
if (error) {
console.error(error);
return;
}
fetchPosts(user.id, (error, posts) => {
if (error) {
console.error(error);
return;
}
console.log(user, posts);
});
});
Promises represent eventual completion (or failure) of an async operation:
// Creating a promise
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
const success = true;
if (success) {
resolve('Success!');
} else {
reject(new Error('Failed!'));
}
}, 1000);
});
// Using a promise
promise
.then(result => {
console.log(result); // "Success!"
return result.toUpperCase();
})
.then(upperResult => {
console.log(upperResult); // "SUCCESS!"
})
.catch(error => {
console.error(error);
})
.finally(() => {
console.log('Cleanup');
});
// Promise utilities
Promise.all([promise1, promise2, promise3])
.then(results => {
// All resolved: [result1, result2, result3]
});
Promise.race([promise1, promise2])
.then(result => {
// First to resolve
});
Promise.allSettled([promise1, promise2])
.then(results => {
// All completed (resolved or rejected)
// [{ status: 'fulfilled', value: ... }, { status: 'rejected', reason: ... }]
});
Promise.any([promise1, promise2])
.then(result => {
// First to fulfill (resolve)
});
Modern syntax for handling promises (ES2017+):
async function fetchUserData(userId) {
try {
const user = await fetchUser(userId);
const posts = await fetchPosts(user.id);
const comments = await fetchComments(posts[0].id);
return { user, posts, comments };
} catch (error) {
console.error('Error:', error);
throw error;
}
}
// Using the async function
fetchUserData(1)
.then(data => console.log(data))
.catch(error => console.error(error));
// Parallel execution
async function fetchAllData() {
const [users, posts, comments] = await Promise.all([
fetchUsers(),
fetchPosts(),
fetchComments()
]);
return { users, posts, comments };
}
// Sequential vs Parallel
async function sequential() {
const result1 = await operation1(); // Wait
const result2 = await operation2(); // Then wait
return [result1, result2];
}
async function parallel() {
const [result1, result2] = await Promise.all([
operation1(), // Start both
operation2() // simultaneously
]);
return [result1, result2];
}
// Try-catch with async/await
async function robustFetch(url) {
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
return data;
} catch (error) {
if (error.name === 'TypeError') {
console.error('Network error:', error);
} else {
console.error('Error:', error);
}
throw error; // Re-throw or handle
}
}
// Promise catch
fetchData()
.then(data => processData(data))
.catch(error => {
// Catches errors from fetchData AND processData
console.error(error);
});
// Global error handlers
window.addEventListener('unhandledrejection', event => {
console.error('Unhandled promise rejection:', event.reason);
event.preventDefault();
});
Encapsulate private data and expose public API:
const Calculator = (function() {
// Private variables
let history = [];
// Private function
function log(operation) {
history.push(operation);
}
// Public API
return {
add(a, b) {
const result = a + b;
log(`${a} + ${b} = ${result}`);
return result;
},
subtract(a, b) {
const result = a - b;
log(`${a} - ${b} = ${result}`);
return result;
},
getHistory() {
return [...history]; // Return copy
},
clearHistory() {
history = [];
}
};
})();
Calculator.add(5, 3); // 8
console.log(Calculator.getHistory()); // ["5 + 3 = 8"]
Cleaner variation of module pattern:
const UserManager = (function() {
// Private
let users = [];
function findUserById(id) {
return users.find(u => u.id === id);
}
function validateUser(user) {
return user && user.name && user.email;
}
// Public methods
function addUser(user) {
if (validateUser(user)) {
users.push(user);
return true;
}
return false;
}
function getUser(id) {
return findUserById(id);
}
function getAllUsers() {
return [...users];
}
// Reveal public API
return {
add: addUser,
get: getUser,
getAll: getAllUsers
};
})();
Create objects without specifying exact class:
function createUser(name, role) {
const roles = {
admin: {
permissions: ['read', 'write', 'delete'],
level: 3
},
editor: {
permissions: ['read', 'write'],
level: 2
},
viewer: {
permissions: ['read'],
level: 1
}
};
const roleConfig = roles[role] || roles.viewer;
return {
name,
role,
...roleConfig,
hasPermission(permission) {
return this.permissions.includes(permission);
},
toString() {
return `${this.name} (${this.role})`;
}
};
}
const admin = createUser('Alice', 'admin');
const editor = createUser('Bob', 'editor');
console.log(admin.hasPermission('delete')); // true
console.log(editor.hasPermission('delete')); // false
Ensure only one instance exists:
const Config = (function() {
let instance;
function createInstance() {
return {
apiUrl: 'https://api.example.com',
timeout: 5000,
retries: 3,
get(key) {
return this[key];
},
set(key, value) {
this[key] = value;
}
};
}
return {
getInstance() {
if (!instance) {
instance = createInstance();
}
return instance;
}
};
})();
const config1 = Config.getInstance();
const config2 = Config.getInstance();
console.log(config1 === config2); // true
// Modern ES6 class version
class Database {
constructor() {
if (Database.instance) {
return Database.instance;
}
this.connection = null;
Database.instance = this;
}
connect() {
if (!this.connection) {
this.connection = 'Connected to DB';
}
return this.connection;
}
}
const db1 = new Database();
const db2 = new Database();
console.log(db1 === db2); // true
Subscribe to and publish events:
class EventEmitter {
constructor() {
this.events = {};
}
on(event, listener) {
if (!this.events[event]) {
this.events[event] = [];
}
this.events[event].push(listener);
// Return unsubscribe function
return () => this.off(event, listener);
}
off(event, listenerToRemove) {
if (!this.events[event]) return;
this.events[event] = this.events[event].filter(
listener => listener !== listenerToRemove
);
}
emit(event, ...args) {
if (!this.events[event]) return;
this.events[event].forEach(listener => {
listener(...args);
});
}
once(event, listener) {
const onceWrapper = (...args) => {
listener(...args);
this.off(event, onceWrapper);
};
this.on(event, onceWrapper);
}
}
// Usage
const emitter = new EventEmitter();
const unsubscribe = emitter.on('data', (data) => {
console.log('Received:', data);
});
emitter.emit('data', { id: 1 }); // "Received: { id: 1 }"
unsubscribe();
emitter.emit('data', { id: 2 }); // Nothing logged
Cache function results for performance:
function memoize(fn) {
const cache = new Map();
return function(...args) {
const key = JSON.stringify(args);
if (cache.has(key)) {
console.log('Cached result');
return cache.get(key);
}
const result = fn.apply(this, args);
cache.set(key, result);
return result;
};
}
// Expensive function
function fibonacci(n) {
if (n <= 1) return n;
return fibonacci(n - 1) + fibonacci(n - 2);
}
const memoizedFib = memoize(fibonacci);
console.log(memoizedFib(40)); // Slow first time
console.log(memoizedFib(40)); // Instant (cached)
// With object methods
const calculator = {
multiplier: 2,
calculate: memoize(function(n) {
return n * this.multiplier;
})
};
// Constants - UPPERCASE_SNAKE_CASE
const MAX_RETRIES = 3;
const API_BASE_URL = 'https://api.example.com';
// Variables and functions - camelCase
let userName = 'John';
function getUserData() { }
// Classes - PascalCase
class UserAccount { }
class HTTPHandler { }
// Private convention - prefix with underscore
class Widget {
constructor() {
this._privateProperty = 'internal';
}
_privateMethod() {
// Implementation
}
}
// Boolean variables - use is/has/can prefix
const isActive = true;
const hasPermission = false;
const canEdit = true;
// Functions - use verb prefix
function getUser() { }
function setConfig() { }
function validateInput() { }
function handleClick() { }
// Custom error classes
class ValidationError extends Error {
constructor(message, field) {
super(message);
this.name = 'ValidationError';
this.field = field;
}
}
class NetworkError extends Error {
constructor(message, statusCode) {
super(message);
this.name = 'NetworkError';
this.statusCode = statusCode;
}
}
// Throw specific errors
function validateEmail(email) {
if (!email.includes('@')) {
throw new ValidationError('Invalid email format', 'email');
}
return true;
}
// Handle different error types
try {
validateEmail('invalid');
} catch (error) {
if (error instanceof ValidationError) {
console.error(`Validation failed for ${error.field}: ${error.message}`);
} else {
console.error('Unexpected error:', error);
}
}
// Async error handling
async function fetchWithRetry(url, retries = 3) {
for (let i = 0; i < retries; i++) {
try {
const response = await fetch(url);
if (!response.ok) {
throw new NetworkError('Request failed', response.status);
}
return await response.json();
} catch (error) {
if (i === retries - 1) throw error; // Last retry
console.log(`Retry ${i + 1}/${retries}`);
await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1)));
}
}
}
// 1. Avoid unnecessary operations in loops
// Bad
for (let i = 0; i < array.length; i++) { } // Length calculated each iteration
// Good
const len = array.length;
for (let i = 0; i < len; i++) { }
// Better - use built-in methods
array.forEach(item => { });
// 2. Debounce expensive operations
function debounce(fn, delay) {
let timeoutId;
return function(...args) {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => fn.apply(this, args), delay);
};
}
const expensiveSearch = debounce((query) => {
// API call
}, 300);
// 3. Throttle high-frequency events
function throttle(fn, limit) {
let inThrottle;
return function(...args) {
if (!inThrottle) {
fn.apply(this, args);
inThrottle = true;
setTimeout(() => inThrottle = false, limit);
}
};
}
window.addEventListener('scroll', throttle(() => {
// Handle scroll
}, 100));
// 4. Use object/map for lookups
// Bad - O(n)
const colors = ['red', 'blue', 'green'];
colors.includes('blue'); // Linear search
// Good - O(1)
const colorSet = new Set(['red', 'blue', 'green']);
colorSet.has('blue'); // Constant time
// 5. Avoid memory leaks
// Bad - event listener not removed
element.addEventListener('click', handler);
// Good
const handler = () => { };
element.addEventListener('click', handler);
// Later...
element.removeEventListener('click', handler);
// 6. Use WeakMap for private data
const privateData = new WeakMap();
class MyClass {
constructor() {
privateData.set(this, { secret: 'value' });
}
getSecret() {
return privateData.get(this).secret;
}
}
// When instance is garbage collected, WeakMap entry is too
// 1. Single Responsibility Principle
// Bad - function does too much
function processUserData(userData) {
// Validate
// Transform
// Save to database
// Send email
// Update UI
}
// Good - separate concerns
function validateUser(userData) { }
function transformUserData(userData) { }
function saveUser(userData) { }
function sendWelcomeEmail(user) { }
function updateUI(user) { }
// 2. Pure functions (no side effects)
// Bad - modifies input
function addToCart(cart, item) {
cart.items.push(item);
return cart;
}
// Good - returns new object
function addToCart(cart, item) {
return {
...cart,
items: [...cart.items, item]
};
}
// 3. Avoid magic numbers
// Bad
if (user.role === 2) { }
// Good
const ROLES = {
ADMIN: 1,
EDITOR: 2,
VIEWER: 3
};
if (user.role === ROLES.EDITOR) { }
// 4. Use default parameters
// Bad
function greet(name) {
name = name || 'Guest';
return `Hello, ${name}`;
}
// Good
function greet(name = 'Guest') {
return `Hello, ${name}`;
}
// 5. Guard clauses for early returns
// Bad
function processOrder(order) {
if (order) {
if (order.items.length > 0) {
if (order.total > 0) {
// Process order
}
}
}
}
// Good
function processOrder(order) {
if (!order) return;
if (order.items.length === 0) return;
if (order.total <= 0) return;
// Process order
}
// 1. Clear timers and intervals
const timerId = setTimeout(() => { }, 1000);
clearTimeout(timerId);
const intervalId = setInterval(() => { }, 1000);
clearInterval(intervalId);
// 2. Remove event listeners
const handler = () => { };
element.addEventListener('click', handler);
element.removeEventListener('click', handler);
// 3. Set references to null when done
let largeData = fetchLargeDataset();
// Use data...
largeData = null; // Allow garbage collection
// 4. Use WeakMap/WeakSet for caches
const cache = new WeakMap();
let obj = { data: 'value' };
cache.set(obj, 'cached value');
obj = null; // Cache entry automatically removed
// 5. Avoid global variables
// Bad
var globalUser = { };
// Good - use modules/closures
(function() {
const user = { };
// Use user locally
})();
// 6. Be careful with closures
function createHeavyObject() {
const heavyData = new Array(1000000);
// Bad - closure keeps heavyData in memory
return function() {
console.log(heavyData.length);
};
// Good - only capture what you need
const length = heavyData.length;
return function() {
console.log(length);
};
}
// 1. Write testable code - pure functions
// Testable
function calculateTotal(items) {
return items.reduce((sum, item) => sum + item.price, 0);
}
// Hard to test - depends on external state
function calculateTotal() {
return cart.items.reduce((sum, item) => sum + item.price, 0);
}
// 2. Dependency injection
// Hard to test
class UserService {
constructor() {
this.api = new ApiClient();
}
}
// Easy to test - inject dependencies
class UserService {
constructor(apiClient) {
this.api = apiClient;
}
}
// 3. Avoid side effects
// Side effects
function processData(data) {
console.log('Processing...'); // Side effect
updateDatabase(data); // Side effect
return transform(data);
}
// Pure
function transformData(data) {
return transform(data);
}
// Separate side effects
function processData(data) {
const transformed = transformData(data);
console.log('Processing...');
updateDatabase(transformed);
return transformed;
}
const arr = [1, 2, 3, 4, 5];
// Transform
arr.map(x => x * 2) // [2, 4, 6, 8, 10]
arr.filter(x => x > 2) // [3, 4, 5]
arr.reduce((sum, x) => sum + x) // 15
// Search
arr.find(x => x > 3) // 4
arr.findIndex(x => x > 3) // 3
arr.indexOf(3) // 2
arr.includes(3) // true
arr.some(x => x > 3) // true
arr.every(x => x > 0) // true
// Mutation
arr.push(6) // Add to end
arr.pop() // Remove from end
arr.unshift(0) // Add to start
arr.shift() // Remove from start
arr.splice(2, 1, 99) // Remove/add at index
// Non-mutating
arr.slice(1, 3) // [2, 3]
arr.concat([6, 7]) // [1, 2, 3, 4, 5, 6, 7]
[...arr] // Copy
arr.join(', ') // "1, 2, 3, 4, 5"
arr.reverse() // [5, 4, 3, 2, 1] (mutates!)
arr.sort((a, b) => a - b) // Sort (mutates!)
const obj = { a: 1, b: 2, c: 3 };
Object.keys(obj) // ['a', 'b', 'c']
Object.values(obj) // [1, 2, 3]
Object.entries(obj) // [['a', 1], ['b', 2], ['c', 3]]
Object.fromEntries([['a', 1]]) // { a: 1 }
Object.assign({}, obj, { d: 4 }) // { a: 1, b: 2, c: 3, d: 4 }
{ ...obj, d: 4 } // Same as above
Object.freeze(obj) // Make immutable
Object.seal(obj) // Prevent add/remove properties
Object.preventExtensions(obj) // Prevent adding properties
Object.hasOwnProperty.call(obj, 'a') // true
'a' in obj // true
obj.hasOwnProperty('a') // true (not recommended)
// 1. Equality
0 == '0' // true (type coercion)
0 === '0' // false (strict)
null == undefined // true
null === undefined // false
// 2. Type coercion
'5' + 3 // "53" (string concatenation)
'5' - 3 // 2 (numeric subtraction)
+'5' // 5 (unary plus converts to number)
!!'value' // true (double negation to boolean)
// 3. this binding
const obj = {
name: 'Object',
regular: function() { console.log(this.name); },
arrow: () => { console.log(this.name); }
};
obj.regular(); // "Object"
obj.arrow(); // undefined (arrow uses lexical this)
// 4. Falsy values
false, 0, -0, 0n, '', null, undefined, NaN
// 5. Array/Object comparison
[] === [] // false (different references)
{} === {} // false (different references)
// 6. Floating point
0.1 + 0.2 === 0.3 // false (0.30000000000000004)
Math.abs(0.1 + 0.2 - 0.3) < Number.EPSILON // true
// 7. Hoisting
console.log(x); // undefined (var hoisted)
var x = 5;
console.log(y); // ReferenceError (let not hoisted to usable state)
let y = 5;
This comprehensive guide covers the essential JavaScript fundamentals needed for modern development. Practice these concepts regularly and refer to the EXAMPLES.md file for detailed implementation scenarios.
Weekly Installs
60
Repository
GitHub Stars
49
First Seen
Jan 22, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
codex45
gemini-cli45
opencode45
cursor44
github-copilot40
claude-code39
React视图过渡API使用指南:实现原生浏览器动画与状态管理
9,100 周安装
Claude记忆搜索工具 - 高效检索会话历史,节省10倍令牌数
1,200 周安装
API文档自动生成器 - 支持REST/GraphQL/WebSocket,一键生成专业API文档
1,200 周安装
AI Sprint规划器 - 敏捷团队Scrum迭代计划工具,自动估算故事点与容量管理
1,200 周安装
Twitter/X API 技能:获取用户资料、推文、关注者、社群和趋势的完整工具包
1,200 周安装
小红书图片生成技能 - Markdown/HTML转精美小红书3:4截图,AI自动生成封面图
1,300 周安装
Vue.js Options API 最佳实践与 TypeScript 集成指南 - 解决常见开发问题
1,200 周安装