变量与数据类型
变量
变量是存储数据的容器。在JavaScript中,使用var
、let
或const
关键字声明变量。var
是ES5的声明方式,存在变量提升问题;let
和const
是ES6新增的块级作用域声明方式。
var name = "张三"; // 函数作用域
let age = 25; // 块级作用域
const PI = 3.14; // 块级作用域,不可重新赋值
变量命名规则:
- 必须以字母、下划线(_)或美元符号($)开头
- 后续字符可以是字母、数字、下划线或美元符号
- 区分大小写
- 不能使用保留字作为变量名
数据类型
JavaScript是弱类型语言,数据类型分为两大类:原始类型和对象类型。
原始类型(基本类型)
- Number类型:表示整数和浮点数
let integer = 10;
let float = 3.14;
let hex = 0xFF; // 255的十六进制表示
let infinity = Infinity;
let nan = NaN; // 非数字
- String类型:表示文本数据
let str1 = '单引号';
let str2 = "双引号";
let str3 = `模板字符串${integer}`; // ES6模板字符串
let str4 = "第一行\n第二行"; // 转义字符
- Boolean类型:逻辑值true/false
let isTrue = true;
let isFalse = false;
- Null类型:表示空值
let empty = null;
- Undefined类型:表示未定义
let notDefined;
console.log(notDefined); // undefined
- Symbol类型(ES6新增):表示唯一值
let sym1 = Symbol('key');
let sym2 = Symbol('key');
console.log(sym1 === sym2); // false
- BigInt类型(ES2020新增):表示大整数
const bigNum = 9007199254740991n;
对象类型(引用类型)
- Object类型:键值对集合
let person = {
name: "李四",
age: 30,
sayHi: function() {
console.log("你好!");
}
};
- Array类型:有序列表
let colors = ["red", "green", "blue"];
let mixed = [1, "text", true, {name: "王五"}];
- Function类型:可执行代码块
function add(a, b) {
return a + b;
}
let multiply = function(x, y) {
return x * y;
};
- Date类型:日期和时间
let now = new Date();
let specificDate = new Date(2023, 0, 1); // 2023年1月1日
- RegExp类型:正则表达式
let pattern = /javascript/i;
let regexp = new RegExp("javascript", "i");
类型检测
JavaScript提供了多种检测数据类型的方法:
- typeof操作符:返回数据类型的字符串表示
typeof 42; // "number"
typeof "text"; // "string"
typeof true; // "boolean"
typeof undefined; // "undefined"
typeof null; // "object" (历史遗留问题)
typeof {}; // "object"
typeof []; // "object"
typeof function(){};// "function"
- instanceof操作符:检测对象是否属于特定类
[] instanceof Array; // true
{} instanceof Object; // true
new Date() instanceof Date; // true
- Object.prototype.toString方法:更精确的类型检测
Object.prototype.toString.call(42); // "[object Number]"
Object.prototype.toString.call("text"); // "[object String]"
Object.prototype.toString.call(null); // "[object Null]"
Object.prototype.toString.call(undefined);// "[object Undefined]"
类型转换
JavaScript会自动进行隐式类型转换,也可以显式进行类型转换。
显式类型转换
- 转换为字符串
String(123); // "123"
(123).toString(); // "123"
- 转换为数字
Number("123"); // 123
parseInt("123px"); // 123
parseFloat("3.14"); // 3.14
- 转换为布尔值
Boolean(1); // true
Boolean(0); // false
Boolean(""); // false
Boolean("text"); // true
隐式类型转换
- 字符串拼接
"3" + 4; // "34"
3 + "4"; // "34"
- 数学运算
"5" - 2; // 3
"5" * "2"; // 10
- 逻辑运算
if ("text") { // true
console.log("执行");
}
变量作用域
JavaScript有三种作用域:
- 全局作用域:在函数外部声明的变量
var globalVar = "全局变量";
- 函数作用域:使用
var
声明的变量
function test() {
var localVar = "局部变量";
}
- 块级作用域:使用
let
和const
声明的变量
{
let blockVar = "块级变量";
const BLOCK_CONST = "块级常量";
}
变量提升
JavaScript引擎会在执行代码前将变量和函数声明提升到作用域顶部。
console.log(hoistedVar); // undefined
var hoistedVar = "提升的变量";
// 实际执行顺序相当于:
var hoistedVar;
console.log(hoistedVar);
hoistedVar = "提升的变量";
let
和const
也存在提升,但不会初始化,形成暂时性死区。
console.log(hoistedLet); // ReferenceError
let hoistedLet = "不会初始化";
常量
使用const
声明的变量必须初始化且不能重新赋值。
const MAX_SIZE = 100;
MAX_SIZE = 200; // TypeError: Assignment to constant variable
但对象和数组的内容可以修改:
const person = {name: "赵六"};
person.name = "钱七"; // 允许
person = {}; // TypeError
解构赋值
ES6新增的解构赋值语法可以方便地从数组或对象中提取值。
- 数组解构
let [a, b, c] = [1, 2, 3];
console.log(a); // 1
- 对象解构
let {name, age} = {name: "孙八", age: 40};
console.log(name); // "孙八"
- 默认值
let [x = 1, y = 2] = [10];
console.log(x, y); // 10 2
模板字符串
ES6的模板字符串提供了更强大的字符串处理能力。
let user = "周九";
let greeting = `你好,${user}!
今天是${new Date().toLocaleDateString()}`;
扩展运算符
扩展运算符...
可以将数组或对象展开。
let arr1 = [1, 2];
let arr2 = [...arr1, 3, 4]; // [1, 2, 3, 4]
let obj1 = {a: 1, b: 2};
let obj2 = {...obj1, c: 3}; // {a: 1, b: 2, c: 3}
原始类型与引用类型的区别
- 存储方式不同
- 原始类型:存储在栈内存中
- 引用类型:存储在堆内存中,栈中存储引用地址
- 复制行为不同
// 原始类型
let num1 = 10;
let num2 = num1; // 值复制
num2 = 20;
console.log(num1); // 10
// 引用类型
let obj1 = {value: 10};
let obj2 = obj1; // 引用复制
obj2.value = 20;
console.log(obj1.value); // 20
- 比较方式不同
// 原始类型
10 === 10; // true
// 引用类型
{} === {}; // false
深拷贝与浅拷贝
- 浅拷贝:只复制一层属性
let original = {a: 1, b: {c: 2}};
let shallowCopy = {...original};
- 深拷贝:递归复制所有层级
let deepCopy = JSON.parse(JSON.stringify(original));
动态类型特性
JavaScript是动态类型语言,变量类型可以随时改变。
let dynamic = "字符串"; // string
dynamic = 42; // number
dynamic = true; // boolean
严格相等与抽象相等
- 严格相等(===):不进行类型转换
1 === 1; // true
1 === "1"; // false
- 抽象相等(==):会进行类型转换
1 == 1; // true
1 == "1"; // true
类型转换规则
- 转换为布尔值
- false值:false, 0, "", null, undefined, NaN
- 其他值都转换为true
- 转换为数字
Number(true); // 1
Number(false); // 0
Number(null); // 0
Number(undefined); // NaN
Number("123"); // 123
Number("123abc");// NaN
- 转换为字符串
String(123); // "123"
String(true); // "true"
String(null); // "null"
String(undefined); // "undefined"
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn
上一篇:作用域样式(@scope)
下一篇:运算符与表达式