- Published on
JavaScript 变量与数据类型
- Authors
- Name
- 青雲
JavaScript 是一门动态类型语言,这意味着你无需提前声明变量的类型。在程序运行时,解释器会自动处理变量的类型。
变量简介
在 JavaScript 中,变量是用来存储数据值的容器。你可以使用 var
, let
, 或者 const
来声明一个变量。
var
:在ES6之前广泛使用,定义一个函数作用域的变量或者定义一个全局变量,无块作用域概念。let
:ES6引入,定义一个块级作用域变量,只在最近的一组大括号内有效。const
:ES6引入,定义一个块级作用域的常量,并且这个常量不可以再赋值。
示例:
var oldWay = "我是老式声明变量的方式";
let newWay = "我是新式声明变量的方式";
const constantValue = "我是一个常量";
console.log(oldWay); // 输出: 我是老式声明变量的方式
console.log(newWay); // 输出: 我是新式声明变量的方式
console.log(constantValue); // 输出: 我是一个常量
数据类型
基本数据类型(原始类型)
JavaScript 有七种基本数据类型,它们是不可变的和可被复制的。
String(字符串)
代表文本数据,可以包括字母、数字或符号,必须用引号(单引号 '
、双引号 "
或模板字符串 ```)包裹。
let greeting = 'Hello, World!';
let favNum = '42';
let template = `I said: ${greeting}`;
Number(数字)
JavaScript 里的所有数字都是浮点类型的,即它们都有小数点。 JavaScript也能表示整数,但这些实际上是没有小数点的浮点数。
let integer = 100;
let floatingPoint = 10.5;
Boolean(布尔值)
只有两个值:true
和 false
。这是 JavaScript 中最简单的数据类型,经常用于逻辑判断。
let isAdult = true;
let isMinor = false;
Null(空值)
null
在 JavaScript 中表示“无的值”或“空值”。它只有一个值:null
。
let empty = null;
Undefined(未定义)
一个没有被赋值的变量会有一个默认值 undefined
。
let notAssigned;
console.log(notAssigned); // 输出 "undefined"
Symbol(符号)
ES6 新增的类型,用于创建匿名和唯一的值。
let sym1 = Symbol('desc');
let sym2 = Symbol('desc');
console.log(sym1 === sym2); // 输出 "false",即使描述相同,也是不同的值
BigInt
ES10 引入的新型数据类型,表示大整数。
const bigInt = 1234567890123456789012345678901234567890n;
let bigNumber = BigInt(9007199254740991) + BigInt(1);
console.log(bigNumber); // 输出:9007199254740992n
对象类型
在 JavaScript 中,对象可以被看作是属性的集合。与基本类型不同的是,对象类型存储的是引用地址,所以当你复制或者传递时,操作的是同一内存地址。除了基本数据类型以外,JavaScript 中的其他值都是对象。
Object
对象是包含一系列“键值对”的集合。可以用大括号 来创建一个新对象。
let person = {
name: 'Alice',
age: 25,
isStudent: true
};
Array
数组是一种特殊的对象,用于保存一系列有序的值。使用方括号 [] 可以创建一个数组。
let colors = ['Red', 'Green', 'Blue'];
console.log(colors[0]); // "Red"
Function
函数实际上是具有相关联代码的对象。
function greet(name) {
return 'Hello ' + name;
}
console.log(greet('Alice')); // "Hello Alice"
动态类型
JavaScript 是一种动态类型语言,这意味着同一个变量可以被赋予不同类型的值。 示例:
let dynamicVar = "Hello, World";
console.log(typeof dynamicVar); // 输出: string
dynamicVar = 50;
console.log(typeof dynamicVar); // 输出: number
dynamicVar = true;
console.log(typeof dynamicVar); // 输出: boolean
dynamicVar = function() { console.log("Hi!"); };
console.log(typeof dynamicVar); // 输出: function
类型转换
在 JavaScript 中,类型转换发生在当运算符和函数被应用到不同类型的值上时。类型转换主要分为两种:显式转换和隐式转换。
显示转换
显式类型转换,又称为类型强制,是指开发者直接指定变量从一种类型转换为另一种类型。在 JavaScript 中可以通过各种内建函数进行显式转换。
字符串转换
我们可以使用 String
函数或者 .toString()
方法把一个值转换为字符串。
let value = 123;
let stringValue = String(value); // 使用String函数
console.log(stringValue); // 输出:"123"
console.log(typeof stringValue); // 输出:"string"
stringValue = value.toString(); // 使用.toString()方法
console.log(stringValue); // 输出:"123"
console.log(typeof stringValue); // 输出:"string"
数字转换
要将一个值转换为数字,可以使用 Number
函数,或者 parseInt
和 parseFloat
函数,取决于我们想要整数还是浮点数。
let stringNumber = "123";
let numberValue = Number(stringNumber); // 使用Number函数
console.log(numberValue); // 输出:123
console.log(typeof numberValue); // 输出:"number"
stringNumber = "123.456";
numberValue = parseFloat(stringNumber); // 获取浮点数
console.log(numberValue); // 输出:123.456
numberValue = parseInt(stringNumber); // 获取整数
console.log(numberValue); // 输出:123
布尔转换
Boolean
函数用来把任何类型的值转换为布尔类型。在 JavaScript 中,false
, 0
, -0
, 0n
, ""
, null
, undefined
, 和 NaN
都是被认为是 falsy(即它们会被转换为 false
),而其他所有的值都被当作是 truthy(会被转换为 true
)。
let truthyValue = "Hello";
let falsyValue = "";
console.log(Boolean(truthyValue)); // 输出:true
console.log(Boolean(falsyValue)); // 输出:false
隐式类型转换
隐式转换是指当代码中的操作符应用于不同类型的值时,JavaScript 解释器自动将数据类型转换为适合该操作符的类型。这种现象常常会在比较操作、逻辑操作、加法或减法等场合出现。
字符串拼接
使用加号 (+
) 来处理字符串和其他类型的值时,JavaScript 会将所有的值转换为字符串。
let result = "Hit points: " + 50; // 数字被转换为字符串
console.log(result); // 输出:"Hit points: 50"
result = "The answer is " + true; // 布尔值被转换为字符串
console.log(result); // 输出:"The answer is true"
数学运算
在执行数学运算时,如果其中一个操作数是字符串,JavaScript 会尝试将这个字符串转换成数字。如果转换失败,则结果为 NaN
(Not-a-Number)。
let result = "4" - "2"; // 字符串被转换为数字
console.log(result); // 输出:2,因为两个字符串都可以转换为数字
result = "five" * 2; // 字符串不能被转换为数字
console.log(result); // 输出:NaN
逻辑运算
在逻辑运算如 &&
和 ||
中,JavaScript 会将值转换为布尔类型来决定运算的结果。
let result = "Cat" && "Dog"; // 两个值都是 truthy
console.log(result); // 输出:"Dog"
result = false || "Dog"; // 第一个值是 falsy,返回第二个值
console.log(result); // 输出:"Dog"
比较运算
比较运算中的类型转换尤其有趣,因为不同的比较运算符有不同的行为。 使用 ==
(宽松相等)会进行隐式类型转换。
console.log(123 == "123"); // 输出:true,字符串被转换为数字
console.log(1 == true); // 输出:true,布尔值被转换为数字
而使用 ===
(严格相等)不会进行类型转换。
console.log(123 === "123"); // 输出:false,没有类型转换
console.log(1 === true); // 输出:false,没有类型转换
类型转换中的陷阱
比较相等时使用 == 而不是 ===
使用 ==
(宽松相等)来比较不同类型的值会引发隐式类型转换,而 ===
(严格相等)则不会进行类型转换。
// 这会导致隐式类型转换
console.log(0 == ""); // 输出:true
console.log(0 == "0"); // 输出:true
console.log(false == "0"); // 输出:true
// 严格相等运算符不会进行类型转换
console.log(0 === ""); // 输出:false
console.log(0 === "0"); // 输出:false
console.log(false === "0");// 输出:false
如果使用 + 运算符连接字符串和数字
字符串和数字相加时,数字会被转换为字符串,这可能会导致不是你期望的结果。
console.log("3" + 4 + 5); // 输出:"345"
console.log(3 + 4 + "5"); // 输出:"75"
null
和 undefined
的比较
null
和 undefined
相比较时是一个特例,使用 ==
时它们相等,但是与其他值比较时不是这样。
console.log(null == undefined); // 输出:true
console.log(null == 0); // 输出:false
console.log(null === undefined);// 输出:false
使用 Object 作为键名
对象在转换为字符串时通常会变成 "[object Object]"
,因此在使用对象作为字典的键名时要小心。
let obj = {};
obj[{}] = "Value";
console.log(obj["[object Object]"]); // 输出:"Value"
NaN 的奇特行为
NaN
是一个表示非数字的特殊值,它与任何值都不相等,包括它自己。
console.log(NaN == NaN); // 输出:false
console.log(NaN === NaN); // 输出:false
console.log(isNaN(NaN)); // 输出:true
NaN
表示“不是一个数字”,但它的类型是 number
。
let result = 'abc' - 1;
console.log(result); // 输出:NaN
console.log(typeof result); // 输出:number
布尔值的转换规则
console.log(Boolean(0)); // 输出:false
console.log(Boolean(1)); // 输出:true
console.log(Boolean('')); // 输出:false
console.log(Boolean('Hello')); // 输出:true
console.log(Boolean(null)); // 输出:false
console.log(Boolean(undefined)); // 输出:false
console.log(Boolean([])); // 输出:true
console.log(Boolean({})); // 输出:true
严格模式与非严格模式
JavaScript 可以在严格模式下执行,这可以防止某些不安全的操作,如不声明变量就使用它。 开启严格模式很简单,只需在脚本或者函数的开头加上 use strict
。
'use strict';
let safeMode = "Now I'm in strict mode";
在严格模式下,如果试图使用未声明的变量,JavaScript 会抛出错误。
面试实战
题一:JavaScript中有哪些数据类型?
答案:JavaScript有两大类数据类型:原始数据类型和对象类型。 原始数据类型包括:
- undefined:表示未定义,变量声明但未初始化时的值。
- null:表示空值或不存在的对象引用。
- boolean:表示逻辑实体,可以是true或false。
- number:表示数字,可以是整数或浮点数,还包括特殊的NaN和Infinity。
- string:表示文本数据,字符串序列。
- symbol:ECMAScript 6引入的新类型,表示独一无二的值,常用于对象属性的键。
- bigint:ECMAScript 2020引入的新数据类型,用于表示大整数。
对象类型(非原始数据类型)包括:
- Function:表示代码块,可以执行。
- Object:表示键值对集合,包括如数组(Array)、日期(Date)和正则表达式(RegExp)等特殊对象类型。
题二:解释var, let和const的区别,并举例说明。
答案:var
, let
, 和 const
是JavaScript中声明变量的三个关键字,它们有不同的作用域和特性。
var
:声明一个变量,作用域为声明所在的函数或全局作用域,可以重复声明同一个变量,可以在声明之前使用(会提升),变量的值可以被修改。
var name = "Alice";
var name; // 重复声明是允许的
console.log(name); // 输出:Alice
let
:声明一个块级作用域的变量,不能在同一个块级作用域内重复声明,不能在声明之前使用(不会提升),变量的值可以修改。
let age = 30;
// let age; // SyntaxError: Identifier 'age' has already been declared
{
let age = 25; // 块级作用域内可以声明
console.log(age); // 输出:25
}
console.log(age); // 输出:30
const
:声明一个块级作用域的常量,同样不能重复声明且不能在声明前使用,声明时必须初始化,一旦赋值后不能再被修改(但如果值是对象,则对象的属性可以修改)。
const PI = 3.14;
// PI = 3; // TypeError: Assignment to constant variable.
const obj = { key: "value" };
obj.key = "new value"; // 可以修改对象属性
console.log(obj.key); // 输出:new value
解释以下代码的行为
const a = {name: 'Alice'};
a = {name: 'Bob'};
答案:代码会抛出 TypeError: Assignment to constant variable. 错误。 const
声明的变量是一个常量,不能被重新赋值。这里尝试为 a
重新赋值一个新对象 {name: 'Bob'}
,因此会抛出类型错误。不过要注意的是,常量对象的属性是可以修改的。
const a = { name: 'Alice' };
a.name = 'Bob';
console.log(a.name); // 输出 'Bob'
题三:如何检测变量的数据类型?
答案:可以使用typeof
运算符或instanceof
运算符,还可以使用Object.prototype.toString.call()
方法。
- typeof: 对于原始数据类型和函数比较有效。
typeof "Hello"; // "string"
typeof 42; // "number"
typeof true; // "boolean"
typeof Symbol(); // "symbol"
typeof undefined; // "undefined"
typeof function() {}; // "function"
- instanceof:用于检查一个对象是否为一个特定的构造函数的实例。
[] instanceof Array; // true
({}) instanceof Object; // true
- Object.prototype.toString.call():可以得到对象类型的最佳方式,对于所有标准的对象和用户定义的对象都有效。
Object.prototype.toString.call([]); // "[object Array]"
Object.prototype.toString.call({}); // "[object Object]"
题四:说明null和undefined的区别
null
是JavaScript的字面量,表示空值;它是一个对象类型,故意指定为"没有对象",这表示该处不应该有值。undefined
是全局对象的属性,表示变量已声明但还未被初始化。
一个变量在定义后没有赋值,那么它的值就是undefined
。而如果你想表示某个值或变量目前不存在,应该用null
来表示。
let foo;
console.log(foo); // undefined
let bar = null;
console.log(bar); // null
解释以下代码的输出
console.log(typeof null);
console.log(typeof undefined);
答案:
typeof null
输出'object'
。null
是一个特殊的关键字,表示一个空对象引用。在 JavaScript 的最初版本中,typeof null
也被定义为了'object'
,这是一个早期实现中的错误,但出于兼容性考虑,这个错误被保留下来了。typeof undefined
输出'undefined'
。undefined
表示变量已声明但未初始化,所以typeof undefined
正常返回'undefined'
。
题五:解释以下代码的输出
let x = 10;
let y = '10';
console.log(x + y);
console.log(x - y);
答案:
x + y
输出'1010'
。在x + y
中,+
操作符对一个字符串和一个数字进行操作时,进行字符串拼接,因此结果为'1010'
。x - y
输出0
。在x - y
中,-
操作符会将字符串'10'
转换为10
,于是计算结果为数值0
。
题六:== 和 === 有什么不同?
答案:==
是等值比较运算符,执行相等测试时会进行类型转换。如果两个值不是同一类型,JavaScript 会尝试将它们转换为一个适当的类型来比较。 ===
是严格等值比较运算符,不进行类型转换。如果两个值类型不一致,===
会立即返回 false,而不会试图将它们转换为同一类型。
解释以下代码的输出
let a;
let b = null;
console.log(a == b);
console.log(a === b);
答案:
a == b
输出 true。==
运算符在比较时,会将undefined
和null
看作相等,因此a == b
输出true
。a === b
输出false
。===
是严格相等运算符,它不仅比较值还比较类型。a
是undefined
,b
是null
,类型不同,因此a === b
输出false
。