第 3 章 · JavaScript 语法基础(上)
本篇介绍 JavaScript 的核心语法基础,因为作者还没吃透整个第三章,故分上下两篇发布。本次内容包括变语法、变量、以及部分数据类型的简单介绍,为后续学习打下坚实基础。
1. 基础语法规范
1.1 大小写敏感与命名规范
ECMAScript 中一切都区分大小写,包括变量、函数名和操作符。标识符推荐使用驼峰命名法:即第一个单词小写,后续单词首字母大写的命名方式。
// 推荐的命名方式
let firstName = "John";
let myCar = "Tesla";
function doSomethingImportant() {
// 函数体
}
1.2 严格模式
为了避免 ECMAScript 3 的不规范写法,可以启用严格模式:
// 全局严格模式
"use strict";
// 函数级严格模式
function doSomething() {
"use strict";
// 函数体
}
2. 变量声明:var、let、const
2.1 var 关键字
JS变量命名区别于C,var 是一种万能的变量类型,它可以用来声明任何类型的变量,包括数字、字符串、对象、数组等。
同时var 是传统的变量声明方式,具有以下特点:
a.类型可变性:
var message = "hi";//定义为字符串
message = 100; // 中途改变为数字类型,
// 合法,但不推荐
// 并且支持连续定义
var message = "hi",
found = false,
age = 29;
b.函数作用域:
function example() {
var localVar = "我是局部变量";
}
console.log(localVar); // 报错:该输出在函数外,此时 localVar 还未定义
c.变量提升(Hoisting):
// 实际写法
function foo() {
console.log(age); // undefined(不是报错!)
var age = 26;
}
// 等价于
function foo() {
var age; // 声明被提升到顶部
console.log(age); // undefined
age = 26; // 赋值留在原位置
}
2.2 let 关键字(非常推荐)
let 是 ES6 引入的现代变量声明方式:
块作用域:
if (true) {
let blockScoped = "我只在这个块内有效";
var functionScoped = "我在整个函数内有效";
}
console.log(blockScoped); // 因let只在最近的一对大括号内有效,所以这里会报错
console.log(functionScoped); // 正常输出
无变量提升:
console.log(age); // ReferenceError:age 没有定义
let age = 26;
全局声明差异:
与 var 关键字不同,使用 let 在全局作用域中声明的变量不会成为 window 对象的属性(var 声
明的变量则会)。
ES6 引入 let 后,设计更严谨:因为全局用 let 声明的变量(比如 let b = 20),会存到 “全局词法环境” 这个隐藏仓库里,不会成为 window 的属性
var globalVar = "我会成为 window 的属性";
let globalLet = "我不会成为 window 的属性";
//比var更安全的地方
console.log(window.globalVar); // "我会成为 window 的属性"
console.log(window.globalLet); // undefined
不可重复定义:
let a = 1;
let a = 2; // 报错:Identifier 'a' has already been declared
var b =1;
var b =2; //不报错,会覆盖之前的定义
循环中的应用:
// 使用 var(问题示例)
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 100); // 输出:3, 3, 3
}
// 使用 let(正确示例)
for (let i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 100); // 输出:0, 1, 2
}
2.3 const 声明
const 用于声明常量,具有 let 的所有特性,但有额外限制:
// 必须在声明时初始化
const PI = 3.14159;
// const EMPTY; // 语法错误
// 不能重新赋值
// PI = 3.14; // 运行时错误
// 对象内容可以修改
const person = {};
person.name = "Matt"; // 正常,修改对象属性
person.age = 25;
console.log(person); // { name: "Matt", age: 25 }
2.4 最佳实践
因此,对于标准化的js语法,推荐使用优先级:
const > let > var
- 默认使用
const - 需要重新赋值时使用
let - 避免使用
var!!!(除非需要兼容老版本浏览器)
3. 数据类型概览
3.1 typeof 操作符
typeof 用于返回数据的类型,返回的内容为以下字符串之一:
console.log(typeof undefined); // "undefined"
console.log(typeof true); // "boolean"
console.log(typeof "hello"); // "string"
console.log(typeof 42); // "number"
console.log(typeof {}); // "object"
console.log(typeof []); // "object"
console.log(typeof function(){}); // "function"
console.log(typeof Symbol()); // "symbol"
// ⚠️ 特殊情况
console.log(typeof null); // "object"
⚠️注意: typeof null 返回 "object" 是历史遗留问题,null 被认为是对空对象的引用。
4. 基本数据类型详解
4.1 Undefined 类型
定义: 未初始化的变量,默认值为 undefined,而在非严格模式下,未声明的变量,访问临时返回值也为 undefined。因此在此额外解释。
let message; // 声明但未初始化
console.log(message); // undefined
console.log(typeof message); // "undefined"
// 未声明的变量
// console.log(age); // ReferenceError
console.log(typeof age); // "undefined"
// 条件判断
if (message) {
// 不会执行,undefined 是假值
}
if (!message) {
// 会执行
}
if (age) {
// 会直接报错
}
这两者的区别是一个是 “合法变量” 的自然状态,一个是 “非法变量” 的临时妥协。
4.2 Null 类型
一般用Null定义还未使用的对象
let car = null; // 表示将来要存储对象
console.log(typeof car); // "object"
4.3 Boolean 类型
布尔值只有两个:true 和 false。
但所有其他 ECMAScript 类型的值都有相应布尔值的等价形式。
要将一个其他类型的值转换为布尔值,可以调用特定的 Boolean()转型函数:
假值(Falsy)记忆口诀:
// 记住这 6 个假值,其余都是真值
Boolean(false); // false
Boolean(0); // false
Boolean(-0); // false
Boolean(""); // false(空字符串)
Boolean(null); // false
Boolean(undefined); // false
Boolean(NaN); // false
// 真值示例
Boolean("0"); // true(非空字符串)
Boolean(" "); // true(包含空格的字符串)
Boolean([]); // true(空数组)
Boolean({}); // true(空对象)
5. Number 类型
5.1 浮点数处理
以下情况js为了在内存中更高效,会自动将浮点数转换为整数:
// 自动转换为整数
let floatNum1 = 1.; // 变成 1
let floatNum2 = 1.0; // 变成 1
// 保持浮点数
let floatNum3 = 1.1; // 1.1
let floatNum4 = 0.1; // 0.1
5.2 特殊数值
JS里存在被定义的无穷数:
// 无穷大
console.log(1 / 0); // Infinity正无穷
console.log(-1 / 0); // -Infinity负无穷
console.log(Number.MAX_VALUE * 2); // Infinity
同时有一种特殊类型NaN(Not a Number),表示不是一个数字。
其中isNaN()方法可以用来检测是否是NaN值。
// NaN(Not a Number)
console.log(0 / 0); // NaN
console.log("abc" * 2); // NaN
console.log(NaN == NaN); // false(NaN 不等于任何值,包括自己)
// 检测 NaN
console.log(isNaN(NaN)); // true
console.log(isNaN("10")); // false(可转换为数字)
console.log(isNaN("abc")); // true(不能转换为数字)
5.3 数值转换方法
Number() 方法(严格转换):
此方法的转换模式可参考以下例子
其中字符串的转换最为特殊:
纯种的“ ”里面带数字就可以转化(不能带字符混合),不然返回NaN
空的“ ”会返回0
除此以外都是NaN
Number(true); // 1
Number(false); // 0
Number(null); // 0
Number(undefined); // NaN
Number(""); // 0
Number("123"); // 123
Number("123abc"); // NaN
parseInt() 方法(宽松转换):
相比起Number方法,其对字符串的转换更宽松:
只要是开头有数字的字符串他都会识别
但对于空字符串则会返回NaN。
此方法只返回整数!!!
parseInt("123"); // 123
parseInt("123abc"); // 123(忽略后面的字符)
parseInt("abc123"); // NaN(开头不是数字)
parseInt(""); // NaN
parseInt("10", 2); // 2(二进制转换)
parseInt("10", 16); // 16(十六进制转换)
同时parseInt方法可以传入第二个参数,表示要以什么样的格式输出,如二进制十六进制等
parseFloat() 方法:
返回浮点数,其余参考上面👆
parseFloat("123.45"); // 123.45
parseFloat("123.45abc"); // 123.45
parseFloat("123.00"); // 123(自动转为整数)
6. String 类型
6.1 字符串不可变性
ECMAScript 中的字符串是不可变的(immutable),意思是一旦创建,它们的值就不能变了。要修改某个变量中的字符串值,必须先销毁原始的字符串,然后将包含新值的另一个字符串保存到该变量。
let lang = "Java";
lang = lang + "Script"; // 创建新字符串,销毁旧字符串
console.log(lang); // "JavaScript"
6.2 转换为字符串
toString() 方法:
toString以后缀的格式家在要转化的元素后。
而其同parseInt方法一样,可传入一个参数表示以什么形式输出
let age = 11;
let ageAsString = age.toString(); // "11"
let num = 10;
console.log(num.toString(2)); // "1010"(二进制)
console.log(num.toString(16)); // "a"(十六进制)
// null 和 undefined 没有 toString() 方法
// null.toString(); // 报错
String() 方法(安全转换):
如果对值是使用 null、undefined,返回“null”、“undefined”。
String(null); // "null"
String(undefined); // "undefined"
String(123); // "123"
6.3 模板字符串(ES6)
可以用``包裹字符串,在其内部的换行会直接被记录,可以省去换行符
用${ }包裹变量,可用于在字符串中插值
基础用法:
let name = "张三";
let age = 25;
// 传统拼接
let message1 = "我叫" + name + ",今年" + age + "岁";
// 模板字符串
let message2 = `我叫${name},今年${age}岁`;
// 多行字符串
let multiline = `
第一行
第二行
第三行
`;
标签函数(高级用法):
标签函数:会接收被插值记号分隔后的模板和对每个表达式求值的结果。这么说可能有点抽象,我下面举个例子:
function simpleTag(strings, aValExpression, bValExpression, sumExpression) {
console.log(strings);
console.log(aValExpression);
console.log(bValExpression);
console.log(sumExpression);
return 'foobar';
}
标签函数的写法与普通函数一致,而其传的参数比较有门道
对第一个参数默认就是一个strings,其包含了模板中非插值部分的字符串片段
其余的依次对应将要传入的插值,即${}里的东西
使用方式如下:
let taggedResult = simpleTag`${ a } + ${ b } = ${ a + b }`;
用``包裹着要传入的参数,此时strings= [“”, " + ", " = ", “”],首尾为空!
此时打印taggedResult会出现返回值foobar,同时内部打印分别对应传入的参数
原始字符串:
若想要获取原始的转译字符,可用string.raw方法
// 普通模板字符串会处理转义
console.log(`\u00A9`); // ©
// String.raw 保留原始字符
console.log(String.raw`\u00A9`); // \u00A9
console.log(String.raw`C:\\Users\\Documents`); // C:\\Users\\Documents
小结
本章介绍了 JavaScript 的部分核心语法基础:
- 变量声明:优先使用
const和let,避免var - 数据类型:介绍了5 种基本类型的特点和转换规则(还剩Symbol和Object)
- 类型转换:理解隐式转换和显式转换的差异
- 现代语法:善用模板字符串提升代码可读性
这些基础知识是后续学习对象、函数、异步编程等高级特性的重要前提,同时也会在面试中被高频提及。作者正在加紧学习后面的内容,感谢支持!!!
更多推荐



所有评论(0)