【JavaScript】代码整理
JavaScript 学习代码归档
参考出处
所有代码示例整理自 廖雪峰JavaScript教程,仅用于个人学习归档。
1. 循环结构对比
for…in vs for…of
// for...in 遍历对象属性(包括原型链)
const obj = { a: 1, b: 2, c: 3 };
for (const key in obj) {console.log(key); // 输出: "a", "b", "c"console.log(obj[key]); // 输出: 1, 2, 3
}// 数组使用 for...in(不推荐)
const arr = ['a', 'b', 'c'];
arr.customProp = 'I am custom'; // 添加自定义属性for (const index in arr) {console.log(index); // 输出: "0", "1", "2", "customProp"
}// for...of 遍历可迭代对象的值
for (const v of arr) {console.log(v); // 输出: "a", "b", "c"
}
迭代器原理
// 手动实现迭代器
const arr = [1, 2, 3];
const iterator = arr[Symbol.iterator]();console.log(iterator.next()); // 输出: { value: 1, done: false }
console.log(iterator.next()); // 输出: { value: 2, done: false }
console.log(iterator.next()); // 输出: { value: 3, done: false }
console.log(iterator.next()); // 输出: { value: undefined, done: true }
2. 函数与作用域
基础函数
// 返回最大值对象
function max(a, b) {if (a > b) {return { a };} else {return { b };}
}console.log(max(15, 20)); // 输出: { b: 20 }// 函数嵌套与变量作用域
function foo() {var x = 1;function bar() {var x = 'A';console.log('x in bar() = ' + x); // 'A'}console.log('x in foo() = ' + x); // 1bar(); // 调用内部函数
}foo();// 变量提升(hoisting)
function foo() {var x = 'Hello, ' + y; // hello + undefinedconsole.log(x);var y = 'Bob'; // 变量声明被提升到函数顶部
}foo(); // 输出: "Hello, undefined"
全局作用域
// 浏览器环境
var course = 'Learn JavaScript';
console.log(course); // 'Learn JavaScript'
console.log(window.course); // 'Learn JavaScript'// Node.js 环境(需显式挂载到 global)
globalThis.course = 'Learn JavaScript';
console.log(global.course); // 'Learn JavaScript'
块级作用域(ES6)
// var 无块级作用域
function foo() {for (var i = 0; i < 100; i++) {// ...}i += 100; // 仍然可以引用变量i
}// let 具有块级作用域
function foo() {let sum = 0;for (let i = 0; i < 100; i++) {sum += i;}// SyntaxError: i 在此作用域未定义// console.log(i);
}
3. 解构赋值(ES6)
数组解构
// 传统方式
let array = ['hello', 'JavaScript', 'ES6'];
let x = array[0];
let y = array[1];
let z = array[2];// 解构赋值
let [a, b, c] = ['hello', 'JavaScript', 'ES6'];
console.log(`a = ${a}, b = ${b}, c = ${c}`); // 输出: a = hello, b = JavaScript, c = ES6
对象解构
// 基础对象解构
let person = {name: '小明',age: 20,gender: 'male',passport: 'G-12345678',
};let { name, age, passport } = person;
console.log(`name = ${name}, age = ${age}, passport = ${passport}`);// 嵌套对象解构
let { address: { city, zip } } = {address: {city: 'Beijing',street: 'No.1 Road',zipcode: '100001'}
};
console.log(city, zip); // 输出: Beijing undefined// 默认值
let { single = true } = person;
console.log(single); // 输出: true// 交换变量
let x = 1, y = 2;
[x, y] = [y, x];
console.log(x, y); // 输出: 2 1
4. 高阶函数与数组方法
map()
// 数组元素平方
function pow(x) {return x * x;
}let arr = [1, 2, 3];
let results = arr.map(pow); // [1, 4, 9]
console.log(results);// 字符串转整数(常见陷阱)
let arr = ['1', '2', '3'];
// 错误写法:arr.map(parseInt) 会导致 NaN
let r = arr.map(str => parseInt(str, 10)); // [1, 2, 3]
console.log(r);
reduce()
// 数组求和
let sum = [1, 3, 5, 7, 9].reduce((x, y) => x + y); // 25
console.log(sum);// 求乘积
function product(arr) {return arr.reduce((a, b) => a * b, 1);
}// 字符串转整数
function string2int(s) {return s.split('').map(c => c.charCodeAt(0) - '0'.charCodeAt(0)).reduce((a, b) => a * 10 + b, 0);
}
filter()
// 过滤奇数
let odd = [1, 2, 4, 5].filter(x => x % 2 !== 0); // [1, 5]
console.log(odd);// 数组去重
let unique = ['apple', 'apple', 'banana'].filter((element, index, self) => {return self.indexOf(element) === index;
});
console.log(unique); // ['apple', 'banana']
sort()
// 数字排序
let arr = [10, 2, 1];
arr.sort((x, y) => x - y); // [1, 2, 10]
console.log(arr);// 字符串忽略大小写排序
let arr = ['Google', 'apple', 'Microsoft'];
arr.sort((s1, s2) => {x1 = s1.toUpperCase();x2 = s2.toUpperCase();return x1 < x2 ? -1 : x1 > x2 ? 1 : 0;
}); // ['apple', 'Google', 'Microsoft']
console.log(arr);
其他数组方法
// every() - 判断所有元素是否满足条件
let allPositive = [1, 2, 3].every(x => x > 0); // true
console.log(allPositive);// find() - 查找第一个符合条件的元素
let firstEven = [1, 3, 4, 5].find(x => x % 2 === 0); // 4
console.log(firstEven);// forEach() - 遍历数组
['a', 'b'].forEach(x => console.log(x)); // 输出: a, b
5. 闭包与箭头函数
闭包
// 计数器闭包
function create_counter(initial) {let x = initial || 0;return {inc: function () {x += 1;return x;}}
}let c1 = create_counter();
console.log(c1.inc()); // 1
console.log(c1.inc()); // 2
箭头函数
// 基本语法
let sum = (a, b) => a + b;// 闭包与this指向
let obj = {birth: 1990,getAge: function () {let fn = () => new Date().getFullYear() - this.birth;return fn();}
};
console.log(obj.getAge()); // 25(当前年份为2025时)
6. 实用案例
斐波那契数列
function fib(max) {let a = 0, b = 1, arr = [0, 1];while (arr.length < max) {[a, b] = [b, a + b];arr.push(b);}return arr;
}console.log(fib(5)); // [0, 1, 1, 2, 3]
JSON处理
// json
let xiaoming = {name: '小明',age: 14,gender: true,height: 1.65,grade: null,'middle-school': '\"W3C\" Middle School',skills: ['JavaScript', 'Java', 'Python', 'Lisp']
};let s = JSON.stringify(xiaoming);
console.log(s);let s2 = JSON.stringify(xiaoming, null, ' ');
console.log(s2);// 第二个参数用于控制如何筛选对象的键值,如果我们只想输出指定的属性,可以传入Array:
console.log(JSON.stringify(xiaoming, ['name', 'skills'], ' '));// 还可以传入一个函数,这样对象的每个键值对都会被函数先处理:
function convert(key, value) {if (typeof value === 'string') {return value.toUpperCase();}return value;
}console.log(JSON.stringify(xiaoming, convert, ' '));// 如果我们还想要精确控制如何序列化小明,
// 可以给xiaoming定义一个toJSON()的方法,直接返回JSON应该序列化的数据:
let xiaoming = {name: '小明',age: 14,gender: true,height: 1.65,grade: null,'middle-school': '\"W3C\" Middle School',skills: ['JavaScript', 'Java', 'Python', 'Lisp'],toJSON: function () {return { // 只输出name和age,并且改变了key:'Name': this.name,'Age': this.age};}
};console.log(JSON.stringify(xiaoming)); // '{"Name":"小明","Age":14}'// JSON.parse()还可以接收一个函数,用来转换解析出的属性:let obj = JSON.parse('{"name":"小明","age":14}', function (key, value) {if (key === 'name') {return value + '同学';}return value;
});
console.log(JSON.stringify(obj)); // {name: '小明同学', age: 14}
天气API请求(需浏览器环境)
let url = 'https://api.openweathermap.org/data/2.5/forecast?q=Beijing,cn&appid=800f49846586c3ba6e7052cfc89af16c';fetch(url).then(response => response.json()).then(data => {const city = data.city.name;const weather = data.list[0].weather[0].main;console.log(`${city}的天气:${weather}`);}).catch(error => console.error('获取天气失败:', error));
let url = 'https://api.openweathermap.org/data/2.5/forecast?q=Beijing,cn&appid=800f49846586c3ba6e7052cfc89af16c';fetch(url).then(response => {if (!response.ok) {throw new Error(`HTTP error! Status: ${response.status}`);}return response.json();}).then(data => {const city = data.city.name;const forecasts = data.list.map(item => ({time: item.dt_txt,weather: item.weather[0].main,description: item.weather[0].description,temperature: (item.main.temp - 273.15).toFixed(1), // 转换为摄氏度humidity: item.main.humidity,wind_speed: item.wind.speed}));const result = {city,forecasts};// 打印或弹窗显示结果console.log(result);alert(JSON.stringify(result, null, 2));}).catch(error => {console.error('获取天气失败:', error);alert('无法获取天气信息,请查看控制台日志');});
JavaScript 构造函数与继承机制
1. 构造函数基础
传统构造函数写法
// 基础构造函数
function Student(name) {this.name = name;this.hello = function () {alert('Hello, ' + this.name + '!');}
}// 正确创建实例
let xiaoming = new Student('小明');
xiaoming.hello(); // Hello, 小明!// 不使用 new 调用的问题
// let xiaohong = Student('小红'); // 错误!this 指向全局对象
安全增强型构造函数
function Student(name) {// 自动检测是否使用 new 调用if (!(this instanceof Student)) {return new Student(name);}this.name = name;this.hello = function () {alert('Hello, ' + this.name + '!');}
}// 可以安全地省略 new
let xiaoming = Student('小明'); // 实际上会调用 new Student()
共享原型方法
function Student(name) {this.name = name;
}// 将方法挂载到原型上实现共享
Student.prototype.hello = function () {alert('Hello, ' + this.name + '!');
};// 所有实例共享同一个 hello 函数
let xiaoming = new Student('小明');
let xiaohong = new Student('小红');
console.log(xiaoming.hello === xiaohong.hello); // true
2. 灵活参数处理模式
function Student(props) {this.name = props.name || '匿名'; // 默认值this.grade = props.grade || 1; // 默认值
}Student.prototype.hello = function () {alert('Hello, ' + this.name + '!');
};// 工厂函数模式
function createStudent(props) {return new Student(props || {});
}// 使用示例
let xiaoming = createStudent({ name: '小明' });
console.log(xiaoming.grade); // 1(默认值)
3. 原型链继承实现
基础继承示例
// 父类
function Student(props) {this.name = props.name || 'Unnamed';
}Student.prototype.hello = function () {alert('Hello, ' + this.name + '!');
};// 子类
function PrimaryStudent(props) {// 调用父类构造函数Student.call(this, props);this.grade = props.grade || 1;
}// 原型继承函数
function inherits(Child, Parent) {let F = function () {};F.prototype = Parent.prototype;Child.prototype = new F();Child.prototype.constructor = Child;
}// 实现继承
inherits(PrimaryStudent, Student);// 添加子类特有方法
PrimaryStudent.prototype.getGrade = function () {return this.grade;
};
类继承示例(ES6)
// 父类
class Student {constructor(name) {this.name = name;}hello() {console.log('Hello, ' + this.name + '!');}
}// 子类
class PrimaryStudent extends Student {constructor(name, grade) {super(name); // 必须调用父类构造函数this.grade = grade;}myGrade() {console.log('I am at grade ' + this.grade);}
}// 使用示例
let xiaoming = new PrimaryStudent('小明', 5);
xiaoming.hello(); // Hello, 小明!
xiaoming.myGrade(); // I am at grade 5
4. 练习:构造函数与继承
实现 Cat 类
function Cat(name) {this.name = name;
}// 所有 Cat 实例共享 say 方法
Cat.prototype.say = function () {return 'Hello, ' + this.name + '!';
};// 测试代码
let kitty = new Cat('Kitty');
let doraemon = new Cat('哆啦A梦');if (kitty && kitty.name === 'Kitty'&& kitty.say&& typeof kitty.say === 'function'&& kitty.say() === 'Hello, Kitty!'&& kitty.say === doraemon.say
) {console.log('测试通过!');
} else {console.log('测试失败!');
}