JavaScript 入门详解:从基础语法到对象和原型链
往期回顾
目录
- 前言
- [一、JavaScript 是什么?](#一、JavaScript 是什么?)
- [二、JavaScript 能做什么?](#二、JavaScript 能做什么?)
- [三、JavaScript 的发展历史](#三、JavaScript 的发展历史)
- [四、JavaScript、HTML、CSS 三者的关系](#四、JavaScript、HTML、CSS 三者的关系)
- [五、JavaScript 的运行过程](#五、JavaScript 的运行过程)
- [六、JavaScript 的组成:ECMAScript、DOM、BOM](#六、JavaScript 的组成:ECMAScript、DOM、BOM)
- [七、JavaScript 的三种书写方式](#七、JavaScript 的三种书写方式)
- 八、注释、输入与输出
- 九、变量:var、let、const
- [十、动态类型:JS 和 C/Java 最大的差异之一](#十、动态类型:JS 和 C/Java 最大的差异之一)
- 十一、基本数据类型
- [十二、number 数字类型](#十二、number 数字类型)
- [十三、string 字符串类型](#十三、string 字符串类型)
- [十四、boolean、undefined 和 null](#十四、boolean、undefined 和 null)
- 十五、运算符
- 十六、条件语句:if、三元表达式、switch
- 十七、循环语句:while、for、break、continue
- 十八、数组:创建、访问、新增和删除
- 十九、函数:封装一段可重复执行的代码
- 二十、作用域与作用域链
- 二十一、对象:属性和方法的集合
- [二十二、构造函数与 new 关键字](#二十二、构造函数与 new 关键字)
- 二十三、原型和原型链
- [二十四、JavaScript 和 Java 到底有什么关系?](#二十四、JavaScript 和 Java 到底有什么关系?)
- [二十五、JavaScript 常见坑点总结](#二十五、JavaScript 常见坑点总结)
- 全文总结
前言
学习前端三件套时,我们一般会按这个顺序来:HTML--->CSS ---> JavaScript
前面学习 HTML 的时候,我们知道:
HTML 负责网页结构。
学习 CSS 的时候,我们知道:
CSS 负责网页样式。
那么 JavaScript 负责什么?
一句话:
JavaScript 负责网页行为。
如果把网页比作一个人:
text
HTML:骨架
CSS:皮肤、衣服、妆容
JavaScript:动作、反应、灵魂
没有 JavaScript,网页大多数时候只是"静态展示"。
有了 JavaScript,网页才可以:
text
点击按钮弹窗
输入表单校验
轮播图自动切换
菜单展开收起
页面局部刷新
和服务器交换数据
做网页游戏
写前端工程
甚至写服务器和桌面应用
所以 JavaScript 的学习是必不可少的
一、JavaScript 是什么?
JavaScript,简称 JS,是一门脚本语言。
它最早主要运行在浏览器中,用来给网页添加交互效果。
比如:
javascript
alert('你好,JavaScript!');
这行代码可以让浏览器弹出一个提示框。
1. JS 是脚本语言
脚本语言通常不需要像 C/C++ 那样先单独编译成可执行文件。
JS 代码一般由解释器或 JS 引擎读取、解析、执行。
在浏览器中,JS 代码由浏览器内置的 JavaScript 引擎执行。
例如 Chrome 浏览器中的 JS 引擎叫:V8
2. JS 是编程语言
HTML 是标记语言,主要描述结构。
CSS 是样式语言,主要描述表现。
JavaScript 则是真正的编程语言,它可以:
text
定义变量
进行运算
写条件判断
写循环
封装函数
创建对象
操作数组
处理用户输入
控制页面元素
和服务器通信
例如:
javascript
var age = 18;
if (age >= 18) {
console.log('成年人');
} else {
console.log('未成年人');
}
这里就有变量、判断和输出逻辑。
3. JS 是动态类型语言
JavaScript 的变量类型不是在声明时固定死的,而是在运行过程中根据赋值决定。
例如:
javascript
var a = 10;
a = 'hello';
一开始 a 是数字,后来又变成了字符串。
这和 C、C++、Java 这类静态类型语言很不一样。
二、JavaScript 能做什么?
最开始,JavaScript 主要是为了在网页中做简单的表单验证。
比如用户注册时检查:
text
用户名是否为空
密码长度是否够
邮箱格式是否正确
但是后来,JavaScript 越来越强大。
现在它可以做的事情非常多。
1. 网页开发
这是 JavaScript 最经典的应用场景。
比如:
text
按钮点击
表单校验
轮播图
下拉菜单
弹窗
页面动态渲染
前后端交互
2. 网页游戏开发
很多 2D 小游戏可以用 JavaScript 实现。
比如:
text
贪吃蛇
打砖块
飞机大战
2048
小游戏页面
常见技术包括:
text
Canvas
DOM
事件监听
定时器
3. 服务器开发
通过 Node.js,JavaScript 也可以运行在服务器端。
也就是说,JS 不再只能写浏览器页面。
它也可以写:
text
后端接口
Web 服务器
命令行工具
自动化脚本
构建工具
4. 桌面应用开发
通过 Electron,可以使用 HTML + CSS + JavaScript 开发桌面程序。
著名的 VS Code 就是基于 Electron 技术构建的。
5. 移动端应用开发
JavaScript 还可以通过一些跨平台框架开发移动端应用。
例如:
text
React Native
Ionic
uni-app
Taro
所以今天的 JavaScript,更像是一门通用型语言。
三、JavaScript 的发展历史
JavaScript 的历史非常有意思。
1. JavaScript 之父:Brendan Eich
JavaScript 的作者是 Brendan Eich。
1995 年,他在 Netscape 公司工作时,用很短时间设计出了 JavaScript 的早期版本。
2. 最初不叫 JavaScript
JavaScript 最开始叫:
text
LiveScript
后来因为当时 Java 非常流行,为了借助 Java 的热度,Netscape 将 LiveScript 改名为 JavaScript。
这也导致很多初学者误以为:
JavaScript 是 Java 的脚本版。
实际上并不是。
Java 和 JavaScript 的关系,大概就像:
雷锋 和 雷峰塔
印度 和 印度尼西亚
老婆饼 和 老婆(手动狗头)
3. ECMAScript 标准化
后来,为了让不同浏览器中的 JavaScript 行为更加统一,JavaScript 被提交给 ECMA 组织标准化。
这个标准叫:
text
ECMAScript
我们平时说的 ES5、ES6,其实就是 ECMAScript 的不同版本。
可以这样理解:
text
ECMAScript:语言标准
JavaScript:标准的一种具体实现和常用名称
4. ES6 是一个重要节点
ES6,也叫 ECMAScript 2015,是 JavaScript 发展史上非常重要的版本。
它引入了很多现代语法:
text
let / const
箭头函数
模板字符串
解构赋值
class
模块化 import/export
Promise
初学阶段可以先掌握基础语法,但后面一定要逐步过渡到现代 JS 写法。
四、JavaScript、HTML、CSS 三者的关系
前端三件套可以这样理解:
text
HTML:网页结构
CSS:网页样式
JavaScript:网页行为
1. HTML:骨架
HTML 决定页面上有什么。
html
<h1>登录页面</h1>
<input type="text" placeholder="请输入用户名">
<button>登录</button>
这里定义了标题、输入框、按钮。
2. CSS:皮肤
CSS 决定页面长什么样。
css
button {
width: 120px;
height: 40px;
background-color: #1677ff;
color: white;
border-radius: 20px;
}
这里控制按钮的大小、颜色、圆角。
3. JavaScript:灵魂
JavaScript 决定页面能做什么。
javascript
var btn = document.querySelector('button');
btn.onclick = function () {
alert('你点击了登录按钮');
};
这里让按钮具有点击响应。
五、JavaScript 的运行过程
JavaScript 代码通常保存在 .html 或 .js 文件中。
当我们打开页面时,大致过程如下:
text
1. 浏览器读取 HTML 文件
2. 解析 HTML 和 CSS
3. 构建页面结构和样式
4. 遇到 JavaScript 代码
5. 交给 JS 引擎解析执行
6. JS 可以操作页面、响应事件、输出结果
1. 浏览器中的两个重要部分
浏览器可以简单拆成:
text
渲染引擎
JavaScript 引擎
2. 渲染引擎
渲染引擎负责解析:
text
HTML
CSS
然后把页面画出来。
有些人平时说的"浏览器内核",很多时候就是指渲染引擎。
3. JavaScript 引擎
JavaScript 引擎负责执行 JS 代码。
例如 Chrome 的 V8 引擎。
JS 引擎会读取 JS 代码,解析并执行。
4. 数据流动过程
可以粗略理解为:
text
硬盘中的文件
↓
浏览器读取到内存
↓
JS 引擎解析代码
↓
CPU 执行指令
所以说,我们写的代码最终还是要被计算机转换成能执行的指令。
六、JavaScript 的组成:ECMAScript、DOM、BOM
JavaScript 在浏览器中通常由三部分组成:
text
ECMAScript
DOM
BOM
1. ECMAScript:核心语法
ECMAScript 规定 JS 的基础语法。
比如:
text
变量
数据类型
运算符
条件语句
循环语句
函数
对象
数组
这部分就是语言本身。
2. DOM:操作网页内容
DOM 全称:
text
Document Object Model
文档对象模型
它可以让 JS 操作页面中的元素。
比如:
javascript
var title = document.querySelector('h1');
title.innerText = '新的标题';
这段代码可以修改页面中的标题内容。
DOM 负责:
text
查找元素
修改文本
修改属性
修改样式
添加元素
删除元素
绑定事件
3. BOM:操作浏览器窗口
BOM 全称:
text
Browser Object Model
浏览器对象模型
它可以让 JS 操作浏览器相关内容。
比如:
javascript
alert('提示信息');
console.log(location.href);
BOM 常见对象有:
text
window
location
history
navigator
screen
4. 浏览器端 JS 和 Node.js 的区别
在浏览器中:
text
JS = ECMAScript + DOM + BOM
在 Node.js 中:
text
JS = ECMAScript + Node.js API
Node.js 没有浏览器页面,所以一般不关注 DOM 和 BOM。
七、JavaScript 的三种书写方式
JS 常见写法有三种:
text
行内式
内嵌式
外部式
1. 行内式
直接写在 HTML 标签属性里。
html
<input type="button" value="点我一下" onclick="alert('hello')">
特点:
text
写起来快
适合简单测试
不推荐大量使用
缺点是 HTML 和 JS 混在一起,不利于维护。
2. 内嵌式
写在 <script> 标签中。
html
<script>
alert('hello JavaScript');
</script>
一般可以写在 body 结束标签之前:
html
<body>
<button>点我</button>
<script>
console.log('页面加载完成');
</script>
</body>
3. 外部式
把 JS 代码写到单独的 .js 文件中。
例如创建:
text
hello.js
写入:
javascript
alert('hello 外部 JS');
然后在 HTML 中引入:
html
<script src="hello.js"></script>
注意:
html
<script src="hello.js"></script>
这种外部引入方式中,script 标签内部不要再写 JS 代码。
也就是说,不推荐这样写:
html
<script src="hello.js">
alert('这句不会按预期执行');
</script>
实际开发中,外部式最常用。
八、注释、输入与输出
1. 单行注释
javascript
// 这是单行注释
在vscode里面按ctrl+/可以一键打上注释
2. 多行注释
javascript
/*
这是多行注释
可以写多行内容
*/
注意:
多行注释不要嵌套多行注释。
3. 输入:prompt
javascript
var name = prompt('请输入你的姓名:');
prompt 会弹出一个输入框。
用户输入的结果通常返回的是字符串。
4. 输出:alert
javascript
alert('你好');
alert 会弹出一个提示框。
它一般用于简单演示,不适合大量调试。
5. 输出:console.log
javascript
console.log('这是一条日志');
console.log 会把内容输出到浏览器控制台。
打开方式:
text
F12 -> Console
console.log 是程序员调试代码的重要工具。
6. 什么是日志?
日志就像医生看病时的检查报告。
普通用户不一定看得懂,但程序员可以通过日志判断程序运行到哪一步、变量是什么值、哪里出了问题。
而我们平时写JS代码的时候,是无法在网页界面上看到直接的运行结果的
所以当我们在调试 JS 时,要学会打开控制台,看日志。一般来讲这个键是在网页端按F12
九、变量:var、let、const
变量可以理解成内存中的一个盒子。
盒子有名字,里面可以放数据。
1. var 声明变量
javascript
var name = 'zhangsan';
var age = 20;
其中:
text
var:声明变量的关键字
name:变量名
=:赋值
'zhangsan':变量的值
2. 使用变量
javascript
var age = 20;
console.log(age);
age = 30;
console.log(age);
变量可以读取,也可以修改。
3. let 声明变量
现代 JS 中更推荐使用 let。
javascript
let score = 100;
score = 90;
let 和 var 都可以声明变量,但 let 的作用域规则更清晰。
4. const 声明常量
如果一个值后面不希望被重新赋值,可以用 const。
javascript
const PI = 3.1415926;
注意:
javascript
const PI = 3.14;
PI = 3.1415; // 报错
5. 变量命名建议
text
1. 尽量见名知意
2. 不要用拼音缩写乱写
3. 多个单词推荐小驼峰
4. 不要使用 JS 关键字
示例:
javascript
let userName = '张三';
let userAge = 18;
let totalScore = 100;
十、动态类型:JS 和 C/Java 最大的差异之一
JavaScript 是动态类型语言。
也就是说,变量的类型是在运行时决定的。
javascript
let a = 10;
console.log(typeof a); // number
a = 'hello';
console.log(typeof a); // string
同一个变量,前一刻可以是数字,后一刻可以是字符串。
1. 和 C/Java 的区别
C、C++、Java、Go 等语言通常是静态类型语言。
例如 Java:
java
int age = 20;
age = "hello"; // 编译报错
变量一旦声明为 int,就不能突然变成字符串。
2. 动态类型的优点
text
写起来灵活
语法门槛较低
适合快速开发
3. 动态类型的缺点
text
类型错误可能运行时才暴露
大型项目中维护难度增加
容易产生隐式类型转换问题
这也是后来 TypeScript 流行的重要原因之一。
TypeScript 可以理解为给 JavaScript 加了一套类型系统。
十一、基本数据类型
JavaScript 常见基本类型包括:
text
number
string
boolean
undefined
null
symbol
bigint
初学阶段我们会重点讲前五个:
text
number:数字
string:字符串
boolean:布尔值
undefined:未定义
null:空值
现代 JS 中还增加了:
text
symbol:唯一值
bigint:大整数
但入门阶段可以先了解,不必深挖。
十二、number 数字类型
JavaScript 中的普通数字统一是 number 类型。
它不区分整数和小数。
javascript
let a = 10;
let b = 3.14;
console.log(typeof a); // number
console.log(typeof b); // number
1. 不同进制数字
javascript
let a = 10; // 十进制
let b = 0b1010; // 二进制
let c = 0o12; // 八进制
let d = 0x0a; // 十六进制
注意:
text
0b 表示二进制
0o 表示八进制
0x 表示十六进制
2. 特殊数字值
JavaScript 中有几个特殊数字值:
text
Infinity
-Infinity
NaN
3. Infinity
javascript
let max = Number.MAX_VALUE;
console.log(max * 2); // Infinity
表示超过了 JS 能表示的数字范围。
4. NaN
NaN 表示:
text
Not a Number
不是一个数字
例如:
javascript
console.log('hehe' - 10); // NaN
但是注意:
javascript
console.log('hehe' + 10); // hehe10
因为 + 遇到字符串时,可能变成字符串拼接。
5. isNaN
可以使用 isNaN 判断是否不是数字。
javascript
console.log(isNaN(10)); // false
console.log(isNaN('hehe' - 10)); // true
十三、string 字符串类型
字符串就是一串文本。
可以使用单引号或双引号。
javascript
let a = 'hello';
let b = "world";
1. 字符串中有引号怎么办?
可以单双引号搭配使用:
javascript
let msg1 = "My name is 'zhangsan'";
let msg2 = 'My name is "zhangsan"';
也可以使用转义字符:
javascript
let msg = "My name is \"zhangsan\"";
2. 常见转义字符
| 转义字符 | 含义 |
|---|---|
\n |
换行 |
\t |
制表符 |
\\ |
反斜杠 |
\' |
单引号 |
\" |
双引号 |
3. 字符串长度
javascript
let str = 'hello';
console.log(str.length); // 5
中文也可以计算长度:
javascript
let str = '哈哈';
console.log(str.length); // 2
4. 字符串拼接
javascript
let name = '张三';
let age = 18;
console.log('姓名:' + name + ',年龄:' + age);
注意:
javascript
console.log(100 + 100); // 200
console.log('100' + 100); // 100100
只要 + 两边有字符串,就可能变成字符串拼接。
5. 模板字符串
现代 JS 更推荐模板字符串。
javascript
let name = '张三';
let age = 18;
console.log(`姓名:${name},年龄:${age}`);
模板字符串使用反引号:
text
`
它可以更方便地拼接变量,也支持换行。
十四、boolean、undefined 和 null
1. boolean 布尔类型
布尔类型只有两个值:
text
true
false
它常用于条件判断。
javascript
let isLogin = true;
if (isLogin) {
console.log('已经登录');
}
2. undefined
如果一个变量声明了,但没有赋值,结果就是 undefined。
javascript
let a;
console.log(a); // undefined
3. null
null 表示空值。
javascript
let user = null;
4. undefined 和 null 的区别
text
undefined:还没有定义值,偏向"没赋值"
null:明确为空,偏向"空对象/空值"
十五、运算符
JavaScript 中的运算符和 C/Java 有不少相似之处。
1. 算术运算符
javascript
let a = 10;
let b = 3;
console.log(a + b);
console.log(a - b);
console.log(a * b);
console.log(a / b);
console.log(a % b);
2. 赋值和复合赋值
javascript
let a = 10;
a += 5; // a = a + 5
a -= 3;
a *= 2;
a /= 4;
a %= 3;
3. 自增自减
javascript
let i = 1;
i++;
i--;
4. 比较运算符
javascript
console.log(10 > 5);
console.log(10 <= 5);
console.log(10 == '10');
console.log(10 === '10');
重点区别:
text
== 会进行隐式类型转换
=== 不会进行隐式类型转换
示例:
javascript
console.log(10 == '10'); // true
console.log(10 === '10'); // false
实际开发中更推荐使用:
javascript
===
!==
因为它们更严格,更不容易踩坑。
5. 逻辑运算符
javascript
&& 与
|| 或
! 非
示例:
javascript
let age = 20;
let hasTicket = true;
if (age >= 18 && hasTicket) {
console.log('可以入场');
}
十六、条件语句:if、三元表达式、switch
1. if 语句
javascript
if (条件) {
语句;
}
示例:
javascript
let num = 10;
if (num % 2 === 0) {
console.log('偶数');
}
2. if else
javascript
let num = 9;
if (num % 2 === 0) {
console.log('偶数');
} else {
console.log('奇数');
}
注意:
判断奇数时,不建议只写:
javascript
num % 2 === 1
因为负奇数取余可能得到 -1。
更稳妥的写法是:
javascript
num % 2 !== 0
3. else if
javascript
let num = 0;
if (num > 0) {
console.log('正数');
} else if (num < 0) {
console.log('负数');
} else {
console.log('0');
}
4. 判断闰年
javascript
let year = 2000;
if (year % 100 === 0) {
if (year % 400 === 0) {
console.log('闰年');
} else {
console.log('不是闰年');
}
} else {
if (year % 4 === 0) {
console.log('闰年');
} else {
console.log('不是闰年');
}
}
可以合并成:
javascript
let year = 2000;
if ((year % 4 === 0 && year % 100 !== 0) || year % 400 === 0) {
console.log('闰年');
} else {
console.log('不是闰年');
}
5. 三元表达式
语法:
javascript
条件 ? 表达式1 : 表达式2
示例:
javascript
let age = 18;
let result = age >= 18 ? '成年人' : '未成年人';
console.log(result);
适合简单的二选一逻辑。
6. switch
switch 适合多分支判断。
javascript
let day = 3;
switch (day) {
case 1:
console.log('星期一');
break;
case 2:
console.log('星期二');
break;
case 3:
console.log('星期三');
break;
default:
console.log('输入有误');
}
注意:
text
case 后面通常要写 break
否则可能发生 case 穿透
十七、循环语句:while、for、break、continue
循环用于重复执行某段代码。
1. while 循环
javascript
while (条件) {
循环体;
}
示例:打印 1 到 10。
javascript
let num = 1;
while (num <= 10) {
console.log(num);
num++;
}
2. while 计算阶乘
javascript
let result = 1;
let i = 1;
while (i <= 5) {
result *= i;
i++;
}
console.log(result); // 120
3. continue
continue 表示结束本次循环,继续下一次循环。
javascript
let i = 1;
while (i <= 5) {
if (i === 3) {
i++;
continue;
}
console.log('我在吃第' + i + '个李子');
i++;
}
注意:
使用 continue 时,别忘了更新循环变量,否则可能死循环。
4. break
break 表示结束整个循环。
javascript
let i = 1;
while (i <= 5) {
if (i === 3) {
break;
}
console.log('我在吃第' + i + '个李子');
i++;
}
5. for 循环
javascript
for (初始化; 条件; 更新) {
循环体;
}
示例:
javascript
for (let i = 1; i <= 10; i++) {
console.log(i);
}
6. for 计算阶乘
javascript
let result = 1;
for (let i = 1; i <= 5; i++) {
result *= i;
}
console.log(result);
十八、数组:创建、访问、新增和删除
数组可以保存一组数据。
1. 创建数组
使用构造函数:
javascript
let arr = new Array();
更常用的是字面量:
javascript
let arr = [];
创建带元素的数组:
javascript
let arr = [1, 2, 'haha', false];
JavaScript 的数组中可以存放不同类型的数据。
不过实际开发中,最好让数组元素类型尽量统一。
2. 访问数组元素
数组下标从 0 开始。
javascript
let arr = ['小猪佩奇', '小猪乔治', '小羊苏西'];
console.log(arr[0]);
console.log(arr[1]);
console.log(arr[2]);
如果访问越界:
javascript
console.log(arr[3]); // undefined
这里会给出undefined的一个结果而不是直接报错,这点和java有所差异。
3. 修改数组元素
javascript
arr[2] = '小猫凯迪';
console.log(arr);
4. length 属性
javascript
console.log(arr.length);
length 表示数组长度。
5. 新增元素:push
javascript
let arr = [1, 2, 3];
arr.push(4);
console.log(arr); // [1, 2, 3, 4]
6. 通过下标新增
javascript
let arr = [];
arr[2] = 10;
console.log(arr); // [empty, empty, 10]
这种写法可能产生空洞数组,不太推荐。
7. 删除元素:splice
javascript
let arr = [9, 5, 2, 7];
arr.splice(2, 1);
console.log(arr); // [9, 5, 7]
解释:
text
第一个参数:从哪个下标开始
第二个参数:删除几个元素
8. 练习:筛选奇数
javascript
let arr = [9, 5, 2, 7, 3, 6, 8];
let newArr = [];
for (let i = 0; i < arr.length; i++) {
if (arr[i] % 2 !== 0) {
newArr.push(arr[i]);
}
}
console.log(newArr);
十九、函数:封装一段可重复执行的代码
函数可以把一段代码封装起来,重复使用。
1. 函数声明
javascript
function hello() {
console.log('hello');
}
调用函数:
javascript
hello();
注意:
函数定义不会自动执行,必须调用才会执行。
2. 带参数的函数
javascript
function sum(num1, num2) {
return num1 + num2;
}
let ret = sum(10, 20);
console.log(ret);
3. 实参和形参个数不匹配
JavaScript 中,函数传参比较灵活。
javascript
function sum(num1, num2) {
return num1 + num2;
}
console.log(sum(10, 20, 30)); // 30
console.log(sum(10)); // NaN
如果实参多了,多余的参数通常不参与。
如果实参少了,多出来的形参值是 undefined。
4. arguments
在普通函数中,可以使用 arguments 获取所有实参。
javascript
function add() {
let sum = 0;
for (let i = 0; i < arguments.length; i++) {
sum += arguments[i];
}
return sum;
}
console.log(add(10, 20));
console.log(add(1, 2, 3, 4));
5. 函数表达式
javascript
let add = function (a, b) {
return a + b;
};
console.log(add(10, 20));
这里 function (a, b) { ... } 是匿名函数,然后赋值给变量 add。
6. 函数是一等公民
JavaScript 中,函数可以像普通变量一样使用。
函数可以:
text
赋值给变量
作为参数传递
作为返回值返回
存放在对象里成为方法
这也是 JS 非常灵活的原因之一。
二十、作用域与作用域链
作用域表示变量在代码中的有效范围。
1. 全局作用域
在函数外部声明的变量,通常属于全局作用域。
javascript
let num = 10;
function test() {
console.log(num);
}
test();
2. 函数作用域
函数内部声明的变量,只在函数内部有效。
javascript
function test() {
let num = 20;
console.log(num);
}
test();
console.log(num); // 报错
3. var 的函数作用域
在 ES6 之前,var 主要是函数作用域。
javascript
if (true) {
var a = 10;
}
console.log(a); // 10
这和很多语言不一样。
4. let 和 const 的块级作用域
现代 JS 中,let 和 const 有块级作用域。
javascript
if (true) {
let a = 10;
}
console.log(a); // 报错
所以现在更推荐使用 let 和 const。
5. 作用域链
函数可以定义在函数内部。
内部函数可以访问外部函数的变量。
javascript
let num = 1;
function test1() {
let num = 10;
function test2() {
let num = 20;
console.log(num);
}
test2();
}
test1();
查找变量时,会从内到外一层层找。
这个链式查找过程就叫作用域链。
可以画成这样:
text
test2 局部作用域
↓ 找不到就往外
test1 局部作用域
↓ 找不到就往外
全局作用域
二十一、对象:属性和方法的集合
对象可以理解成一个具体的事物。
例如:
text
电脑 是一个类别
我的联想笔记本 是一个具体对象
对象通常由两部分组成:
text
属性:描述特征
方法:描述行为
比如一个学生对象:
text
属性:姓名、年龄、身高
方法:学习、跑步、打招呼
1. 为什么需要对象?
如果用数组保存学生信息:
javascript
let student = ['张三', 175, 140];
问题是:
text
175 是身高还是体重?
140 是体重还是分数?
含义不清楚。
用对象更清晰:
javascript
let student = {
name: '张三',
height: 175,
weight: 140
};
2. 使用字面量创建对象
javascript
let student = {
name: '蔡徐坤',
height: 175,
weight: 170,
sayHello: function () {
console.log('hello');
}
};
3. 访问对象属性
使用点语法:
javascript
console.log(student.name);
使用中括号:
javascript
console.log(student['height']);
4. 调用对象方法
javascript
student.sayHello();
注意:
调用方法时不要忘记小括号。
5. 使用 new Object 创建对象
javascript
let student = new Object();
student.name = '张三';
student.height = 175;
student.weight = 140;
student.sayHello = function () {
console.log('hello');
};
实际开发中,更常用对象字面量。
二十二、构造函数与 new 关键字
如果要创建多个结构相似的对象,手写对象字面量会很麻烦。
比如创建多只猫:
javascript
let mimi = {
name: '咪咪',
type: '中华田园喵',
miao: function () {
console.log('喵');
}
};
let xiaohei = {
name: '小黑',
type: '波斯喵',
miao: function () {
console.log('猫呜');
}
};
这时候可以使用构造函数。
1. 构造函数基本写法
javascript
function Cat(name, type, sound) {
this.name = name;
this.type = type;
this.miao = function () {
console.log(sound);
};
}
创建对象:
javascript
let mimi = new Cat('咪咪', '中华田园喵', '喵');
let xiaohei = new Cat('小黑', '波斯喵', '猫呜');
console.log(mimi.name);
mimi.miao();
2. 构造函数注意事项
text
构造函数名首字母一般大写
内部使用 this 表示当前对象
构造函数通常不需要 return
调用时必须配合 new
3. new 做了什么?
new 的执行过程可以理解为四步:
text
1. 创建一个空对象 {}
2. 让 this 指向这个空对象
3. 执行构造函数代码,给对象添加属性和方法
4. 返回这个对象
也就是说:
javascript
let mimi = new Cat('咪咪', '中华田园喵', '喵');
大致相当于:
text
创建一个空猫对象
把 this 指向这只猫
给这只猫添加 name、type、miao
最后把这只猫返回给 mimi
二十三、原型和原型链
原型是 JavaScript 对象体系中非常重要的概念。
初学时不需要一次性全部吃透,但一定要先建立直觉。
1. 为什么需要原型?
如果我们在构造函数中这样写方法:
javascript
function Cat(name, type) {
this.name = name;
this.type = type;
this.miao = function () {
console.log('喵');
};
}
每创建一只猫,都会创建一份新的 miao 函数。
如果创建 1000 只猫,就会有 1000 份类似方法。
这会浪费内存。
2. 使用 prototype 共享方法
javascript
function Cat(name, type) {
this.name = name;
this.type = type;
}
Cat.prototype.miao = function () {
console.log('喵');
};
let mimi = new Cat('咪咪', '中华田园喵');
let xiaohei = new Cat('小黑', '波斯喵');
mimi.miao();
xiaohei.miao();
这样,所有通过 Cat 创建出来的对象,都可以共享 Cat.prototype 上的方法。
3. 原型链是什么?
当访问一个对象的属性或方法时,JS 会先在对象自己身上找。
如果找不到,就去它的原型对象上找。
如果还找不到,就继续往原型的原型上找。
这个查找链条就叫:
text
原型链
可以画成这样:
text
mimi
↓ 找不到 miao
Cat.prototype
↓ 找不到
Object.prototype
↓ 找不到
null
4. 原型链的意义
原型链让对象之间可以共享属性和方法。
它是 JavaScript 实现"继承"效果的重要机制。
注意:
JavaScript 的继承本质上不是传统 Java 那种 class 继承,而是对象和对象之间通过原型建立关联。
二十四、JavaScript 和 Java 到底有什么关系?
实际上JavaScript 和 Java 并不是同一种语言。
1. 语法上有些相似
JavaScript 的部分语法看起来像 Java/C。
比如:
javascript
if (...) {
}
for (...) {
}
function test() {
}
所以有 Java 或 C 基础的人,学 JS 基础语法会感觉比较熟悉。
2. 类型系统不同
Java 是静态类型:
java
int age = 18;
JavaScript 是动态类型:
javascript
let age = 18;
age = '十八岁';
3. 对象模型不同
Java 主要是基于类的面向对象。
JavaScript 早期主要是基于原型的对象系统。
虽然 ES6 引入了 class,但它本质上仍然是基于原型机制的语法糖。
4. 访问控制不同
Java 中有:
text
private
public
protected
JavaScript 传统对象模型中,属性通常可以被外部直接访问。
现代 JS 中也有私有字段语法,例如:
javascript
class Person {
#name;
constructor(name) {
this.#name = name;
}
}
但初学阶段可以先理解普通对象属性。
5. "鸭子类型"思想
JavaScript 中常见一个思想:
不关心你具体是什么类型,只关心你有没有我要用的方法。
比如:
javascript
function add(list, item) {
list.add(item);
}
只要传进来的对象有 add 方法,就可以用。
这和 Java 中通过接口、继承来约束类型的方式很不一样。
二十五、JavaScript 常见坑点总结
2. 字符串忘记加引号
错误:
javascript
let name = zhangsan;
正确:
javascript
let name = 'zhangsan';
3. 中英文标点混用
错误:
javascript
console.log('hello');
正确:
javascript
console.log('hello');
JS 中的括号、分号、引号一般都要用英文标点。
4. 混淆 == 和 ===
javascript
console.log(10 == '10'); // true
console.log(10 === '10'); // false
建议默认使用:
javascript
===
!==
5. 字符串和数字相加
javascript
console.log('100' + 100); // 100100
如果想做数字运算,要先转成数字:
javascript
let num = Number('100');
console.log(num + 100); // 200
6. undefined 参与运算
javascript
let a;
console.log(a + 10); // NaN
变量使用前要确认是否已经赋值。
7. continue 导致死循环
javascript
let i = 1;
while (i <= 5) {
if (i === 3) {
continue;
}
console.log(i);
i++;
}
当 i === 3 时,直接 continue,i++ 没执行,于是死循环。
正确写法:
javascript
let i = 1;
while (i <= 5) {
if (i === 3) {
i++;
continue;
}
console.log(i);
i++;
}
8. 数组越界不是报错,而是 undefined
javascript
let arr = [1, 2, 3];
console.log(arr[10]); // undefined
这和 C/C++ 的数组越界行为不同。
9. 函数参数个数不匹配
javascript
function sum(a, b) {
return a + b;
}
console.log(sum(10)); // NaN
因为 b 是 undefined。
10. 对象方法忘记加括号
javascript
student.sayHello; // 只是访问函数
student.sayHello(); // 真正调用函数
全文总结
最后把 JavaScript 基础压缩成几句话。
1. JavaScript 是什么?
JavaScript 是一门主要用于 Web 开发的编程语言。
它最开始运行在浏览器中,现在也可以通过 Node.js 运行在服务器端。
2. JavaScript 在前端中负责什么?
text
HTML:结构
CSS:样式
JavaScript:行为
JavaScript 负责让页面能响应用户操作。
3. JavaScript 由什么组成?
浏览器端 JS 主要包括:
text
ECMAScript:核心语法
DOM:操作页面
BOM:操作浏览器
4. JavaScript 的核心语法有哪些?
text
变量
数据类型
运算符
条件语句
循环语句
数组
函数
对象
作用域
原型链
5. JavaScript 最大的特点之一是什么?
它是动态类型语言。
变量类型可以在运行过程中变化。
这让 JS 很灵活,但也带来了隐式类型转换、运行时错误等问题。