JavaScript基础入门:从零开始的“坑“之旅
嘿,朋友!如果你正在看这篇文章,我猜你大概是被JavaScript的各种"神奇"行为折磨过,或者正准备踏入这个既迷人又有点"神经质"的编程世界。不管怎样,坐稳了,咱们一起聊聊这门让人又爱又恨的语言。
一、JavaScript是个啥?别被名字骗了!
首先,JavaScript和Java的关系,就像雷锋和雷峰塔的关系——除了名字有点像,其他八竿子打不着。
1995年,一个叫Brendan Eich的大佬花了10天搞出了这门语言。没错,就是10天!所以如果你发现JS有些地方设计得有点"随意",嗯... 那是因为它真的是赶工出来的 😅
JavaScript最初叫Mocha,后来改名LiveScript,最后因为跟Sun公司(Java的东家)有合作,就蹭了个热度叫JavaScript。这波营销,我给满分!
二、数据类型:JS的"性格分裂"
JavaScript有7种原始类型(Primitive Types),记住它们,后面要考:
| 类型 | 说明 | 举个栗子 |
| Number | 数字(数字+小数) | 42,3.14 |
| BigInt | 超大整数 | 956562232484 |
| String | 字符串 | “HelloWorld” |
| Boolean | 布尔值 | true,false |
| Symbol | 唯一标识符 | Symbol(‘desc’) |
| Undefined | 未定义 | 变量声明了但没赋值 |
| Null | 空值 | 表示"故意为空" |
💡小提示:typeof的“迷惑行为”
typeof null; // "object" ← 这是JS的历史bug,一直没修
typeof undefined; // "undefined"
typeof []; // "object" ← 数组也是object
typeof {}; // "object"
看到没?typeof null返回"object",这是JavaScript著名的历史遗留bug,从1995年活到现在,为了兼容性一直没改。所以判断null要这样:
value === null; // 正确姿势
三、变量声明:var、let、const的"宫斗剧"
1. var —— 老员工,但有点"坑"
var是ES5及之前的变量声明方式,它有两个"致命伤":
问题一:变量提升(Hoisting)
console.log(name); // undefined(不会报错!)
var name = "张三";
上面的代码实际相当于:
var name; // 声明被提升到顶部
console.log(name); // undefined
name = "张三"; // 赋值留在原地
问题二:没有块级作用域
if (true) {
var x = 10;
}
console.log(x); // 10 ← 居然能访问到!
2. let —— 新时代的"好员工"(ES6)
console.log(name); // ReferenceError!报错才是正常的
let name = "李四";
if (true) {
let y = 20;
}
console.log(y); // ReferenceError!块级作用域生效了
3. const —— "一旦认定,绝不改变"
const PI = 3.14159;
PI = 3.14; // TypeError: Assignment to constant variable.
但是! const只保证引用不变,对象内容还是可以改的:
const person = { name: "王五" };
person.name = "赵六"; // 可以!
person = {}; // 报错!不能重新赋值
最佳实践:
- 默认用 const —— 能不变就不变,代码更安全
- 需要改变时用 let —— 比如循环计数器
- 尽量别用 var —— 除非你在维护老代码
四、函数:从"传统派"到"箭头派"
传统函数写法
function add(a, b) {
return a + b;
}
// 或者函数表达式
const add = function(a, b) {
return a + b;
};
箭头函数 —— ES6的"语法糖"(真香!)
// 完整写法
const add = (a, b) => {
return a + b;
};
// 简写:只有一行return时可以省略花括号和return
const add = (a, b) => a + b;
// 只有一个参数时可以省略括号
const square = x => x * x;
// 没有参数时括号不能省
const greet = () => "Hello World";
箭头函数的this:"我继承我爸的"
这是箭头函数最重要的特性!
const obj = {
name: "小明",
sayHi: function() {
setTimeout(function() {
console.log("Hi, " + this.name); // "Hi, undefined"
}, 100);
},
sayHiArrow: function() {
setTimeout(() => {
console.log("Hi, " + this.name); // "Hi, 小明"
}, 100);
}
};
箭头函数没有自己的this,它会继承外层作用域的this。这在回调函数里特别有用!
五、解构赋值:"开箱即用"的艺术
数组解构
// 传统写法
const arr = [1, 2, 3];
const a = arr[0];
const b = arr[1];
const c = arr[2];
// 解构写法(优雅!)
const [a, b, c] = [1, 2, 3];
// 跳过某些元素
const [first, , third] = [1, 2, 3]; // first=1, third=3
// 剩余元素
const [head, ...tail] = [1, 2, 3, 4]; // head=1, tail=[2,3,4]
// 默认值
const [x = 10, y = 20] = [1]; // x=1, y=20
对象解构
const user = {
name: "张三",
age: 25,
address: {
city: "北京",
street: "长安街"
}
};
// 基本解构
const { name, age } = user;
// 重命名
const { name: userName } = user; // userName = "张三"
// 默认值
const { name, gender = "未知" } = user; // gender = "未知"
// 嵌套解构
const { address: { city } } = user; // city = "北京"
// 函数参数解构(超实用!)
function printUser({ name, age }) {
console.log(`${name}今年${age}岁`);
}
printUser(user); // "张三今年25岁"
六、模板字符串:告别"+"号拼接
ES6之前,字符串拼接是这样的:
const name = "李四";
const age = 30;
const str = "你好," + name + "!你今年" + age + "岁了。";
ES6之后,用反引号(`)和${}:
const str = `你好,${name}!你今年${age}岁了。`;
// 还能写多行!
const html = `
<div>
<h1>${title}</h1>
<p>${content}</p>
</div>
`;
// 甚至能放表达式
const result = `2 + 3 = ${2 + 3}`; // "2 + 3 = 5"
七、数组方法:函数式编程入门
JavaScript数组有一堆超实用的方法,学会它们,代码质量直接起飞:
map —— "每个都变一变"
const nums = [1, 2, 3];
const doubled = nums.map(n => n * 2); // [2, 4, 6]
filter —— "只留符合条件的"
const nums = [1, 2, 3, 4, 5];
const evens = nums.filter(n => n % 2 === 0); // [2, 4]
reduce —— "汇总成一个值"
const nums = [1, 2, 3, 4];
const sum = nums.reduce((acc, n) => acc + n, 0); // 10
find —— "找到第一个符合条件的"
const users = [{name: "张三"}, {name: "李四"}];
const user = users.find(u => u.name === "李四"); // {name: "李四"}
includes —— "包不包含?"
[1, 2, 3].includes(2); // true
"hello".includes("ell"); // true
八、异步编程:从回调地狱到async/await
时代1:回调函数(Callback Hell)
getData(function(a) {
getMoreData(a, function(b) {
getMoreData(b, function(c) {
// ... 嵌套越来越深,人称"回调地狱"
});
});
});
时代2:Promise
getData()
.then(a => getMoreData(a))
.then(b => getMoreData(b))
.then(c => console.log(c))
.catch(err => console.error(err));
时代3:async/await—— 终极解决方案
async function fetchData() {
try {
const a = await getData();
const b = await getMoreData(a);
const c = await getMoreData(b);
console.log(c);
} catch (err) {
console.error(err);
}
}
async/await让异步代码看起来像同步代码,可读性大大提升!
九、一些"坑"和冷知识
1. == vs ===:严格相等的重要性
0 == "0"; // true ← 会进行类型转换
0 === "0"; // false ← 类型不同直接false
null == undefined; // true
null === undefined; // false
// 最佳实践:永远用 === 和 !==
2. 假值(Falsy Values)大全
下面这些值在条件判断中都是"假":
false
0
"" (空字符串)
null
undefined
NaN
document.all // 浏览器里的历史遗留
3. 0.1 + 0.2 !== 0.3
0.1 + 0.2 === 0.3; // false!
0.1 + 0.2; // 0.30000000000000004
这是因为计算机用二进制存储浮点数,有些小数无法精确表示。解决方法:
Math.abs(0.1 + 0.2 - 0.3) < Number.EPSILON; // true
4. 闭包(Closure)—— JS的"黑科技"
function makeCounter() {
let count = 0;
return function() {
return ++count;
};
}
const counter = makeCounter();
counter(); // 1
counter(); // 2
counter(); // 3
内部函数"记住"了外部函数的变量,这就是闭包!
十、总结:JavaScript学习路线图
- 基础语法 → 变量、数据类型、运算符、条件、循环
- 函数 → 声明、调用、作用域、箭头函数
- 对象和数组 → 创建、访问、常用方法
- ES6+新特性 → let/const、解构、模板字符串、展开运算符
- 异步编程 → Promise、async/await
- 进阶概念 → 闭包、原型链、事件循环
总结
JavaScript是一门容易上手,但难以精通的语言。它有很多"坑",但也有很多巧妙的设计。希望这篇文章能帮你建立起对JS的整体认知,少走弯路。
记住:最好的学习方式就是写代码。看完这篇文章,打开你的编辑器,动手试试吧!
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)