当前位置: 首页 > news >正文

JavaScript学习教程,从入门到精通,JavaScript 数据类型详解(7)

JavaScript 数据类型详解

JavaScript 是一种动态类型语言,这意味着变量可以持有任何类型的数据,并且可以在程序执行过程中改变其数据类型。JavaScript 有以下基本数据类型:

1. Undefined 类型

Undefined 类型只有一个值,即 undefined。当变量被声明但未被赋值时,它的值就是 undefined

// Undefined 类型示例
let undeclaredVar; // 声明但未赋值的变量
let undefinedVar = undefined; // 显式赋值为undefined

console.log(undeclaredVar); // 输出: undefined
console.log(undefinedVar);  // 输出: undefined
console.log(typeof undeclaredVar); // 输出: "undefined"

// 函数没有返回值时,默认返回undefined
function noReturn() {
  // 没有return语句
}
console.log(noReturn()); // 输出: undefined

// 访问对象不存在的属性
const obj = { name: "Alice" };
console.log(obj.age); // 输出: undefined

2. Null 类型

Null 类型也只有一个值,即 null。它表示一个空对象指针,通常用于表示有意地缺少任何对象值。

// Null 类型示例
let nullVar = null; // 显式赋值为null

console.log(nullVar); // 输出: null
console.log(typeof nullVar); // 输出: "object" (这是JavaScript的一个历史遗留问题)

// 使用场景:初始化一个变量,稍后将赋值为对象
let futureObject = null;
futureObject = { name: "Bob" };

// 清空对象引用
let person = { name: "Charlie" };
person = null; // 断开引用,原对象会被垃圾回收

// 与undefined的区别
console.log(null == undefined); // 输出: true (宽松相等)
console.log(null === undefined); // 输出: false (严格相等)

3. Boolean 类型

Boolean 类型有两个值:truefalse,用于表示逻辑实体。

// Boolean 类型示例
let isTrue = true;
let isFalse = false;

console.log(isTrue); // 输出: true
console.log(isFalse); // 输出: false
console.log(typeof isTrue); // 输出: "boolean"

// 布尔转换
console.log(Boolean(1)); // 输出: true (非零数字为true)
console.log(Boolean(0)); // 输出: false (零为false)
console.log(Boolean("")); // 输出: false (空字符串为false)
console.log(Boolean("hello")); // 输出: true (非空字符串为true)
console.log(Boolean(null)); // 输出: false
console.log(Boolean(undefined)); // 输出: false
console.log(Boolean({})); // 输出: true (对象总是true)

// 逻辑运算符
console.log(true && false); // 输出: false (逻辑与)
console.log(true || false); // 输出: true (逻辑或)
console.log(!true); // 输出: false (逻辑非)

// 条件语句中的使用
if (isTrue) {
  console.log("This will be executed");
} else {
  console.log("This won't be executed");
}

4. Number 类型

Number 类型用于表示整数和浮点数。JavaScript 使用 IEEE 754 标准来表示数字。

// Number 类型示例
let integer = 42; // 整数
let float = 3.14159; // 浮点数
let scientific = 1.23e5; // 科学计数法 (1.23 × 10^5 = 123000)
let hex = 0xff; // 十六进制 (255)
let octal = 0o10; // 八进制 (8)
let binary = 0b1010; // 二进制 (10)

console.log(integer, float, scientific, hex, octal, binary);

// 特殊数值
let infinity = Infinity; // 无穷大
let negativeInfinity = -Infinity; // 负无穷大
let notANumber = NaN; // 非数字 (Not a Number)

console.log(infinity, negativeInfinity, notANumber);
console.log(typeof infinity); // 输出: "number"

// NaN 的特性
console.log(NaN === NaN); // 输出: false (NaN不等于任何值,包括它自己)
console.log(isNaN(NaN)); // 输出: true (使用isNaN函数检测)
console.log(isNaN("hello")); // 输出: true (字符串"hello"转换为数字是NaN)
console.log(Number.isNaN(NaN)); // 输出: true (ES6更安全的检测方法)
console.log(Number.isNaN("hello")); // 输出: false (不会强制转换)

// 数值范围
console.log(Number.MAX_VALUE); // 最大正数 (~1.79e+308)
console.log(Number.MIN_VALUE); // 最小正数 (~5e-324)
console.log(Number.MAX_SAFE_INTEGER); // 最大安全整数 (2^53 - 1)
console.log(Number.MIN_SAFE_INTEGER); // 最小安全整数 (-(2^53 - 1))

// 数值运算
console.log(0.1 + 0.2); // 输出: 0.30000000000000004 (浮点数精度问题)
console.log((0.1 * 10 + 0.2 * 10) / 10); // 输出: 0.3 (解决方法)

// 数值转换
console.log(Number("123")); // 输出: 123
console.log(Number("123.45")); // 输出: 123.45
console.log(Number("123abc")); // 输出: NaN
console.log(parseInt("123.45")); // 输出: 123 (解析整数部分)
console.log(parseFloat("123.45abc")); // 输出: 123.45 (解析浮点数部分)

5. String 类型

String 类型用于表示文本数据,由零个或多个 16 位 Unicode 字符组成。

// String 类型示例
let singleQuotes = 'Hello, world!'; // 单引号字符串
let doubleQuotes = "Hello, world!"; // 双引号字符串
let backticks = `Hello, world!`; // 模板字符串(ES6)
let emptyString = ""; // 空字符串

console.log(singleQuotes, doubleQuotes, backticks, emptyString);
console.log(typeof singleQuotes); // 输出: "string"

// 转义字符
let escaped = "First line\nSecond line\tTabbed\"Quote\'Quote\\Backslash";
console.log(escaped);
/*
输出:
First line
Second line    Tabbed"Quote'Quote\Backslash
*/

// 字符串长度
let str = "JavaScript";
console.log(str.length); // 输出: 10

// 访问字符
console.log(str[0]); // 输出: "J" (ES5+方式)
console.log(str.charAt(1)); // 输出: "a" (传统方式)
console.log(str.charCodeAt(0)); // 输出: 74 (J的Unicode编码)

// 字符串不可变性
str[0] = "X"; // 尝试修改字符串
console.log(str); // 输出: "JavaScript" (字符串不会被修改)

// 字符串连接
let concat1 = "Hello" + " " + "World"; // 使用+运算符
let concat2 = "Hello".concat(" ", "World"); // 使用concat方法
console.log(concat1, concat2);

// 模板字符串(ES6)
let name = "Alice";
let age = 25;
let template = `My name is ${name} and I'm ${age} years old.`;
console.log(template); // 输出: My name is Alice and I'm 25 years old.

// 多行字符串
let multiLine = `This is
a multi-line
string.`;
console.log(multiLine);

// 常用字符串方法
let sample = "Hello, JavaScript!";

console.log(sample.toUpperCase()); // 输出: "HELLO, JAVASCRIPT!"
console.log(sample.toLowerCase()); // 输出: "hello, javascript!"
console.log(sample.indexOf("Java")); // 输出: 7 (首次出现位置)
console.log(sample.lastIndexOf("a")); // 输出: 9 (最后出现位置)
console.log(sample.includes("Script")); // 输出: true (是否包含)
console.log(sample.startsWith("Hello")); // 输出: true (是否以...开头)
console.log(sample.endsWith("!")); // 输出: true (是否以...结尾)
console.log(sample.slice(7, 10)); // 输出: "Jav" (提取子串)
console.log(sample.substring(7, 10)); // 输出: "Jav" (类似slice)
console.log(sample.substr(7, 3)); // 输出: "Jav" (从位置7开始取3个字符)
console.log(sample.split(", ")); // 输出: ["Hello", "JavaScript!"] (分割字符串)
console.log(sample.replace("JavaScript", "World")); // 输出: "Hello, World!" (替换)
console.log("  trim me  ".trim()); // 输出: "trim me" (去除两端空格)

类型检测与转换

// 类型检测
console.log(typeof undefined); // 输出: "undefined"
console.log(typeof null); // 输出: "object" (历史遗留问题)
console.log(typeof true); // 输出: "boolean"
console.log(typeof 42); // 输出: "number"
console.log(typeof "hello"); // 输出: "string"

// 更精确的类型检测
console.log(Object.prototype.toString.call(undefined)); // [object Undefined]
console.log(Object.prototype.toString.call(null)); // [object Null]
console.log(Object.prototype.toString.call(true)); // [object Boolean]
console.log(Object.prototype.toString.call(42)); // [object Number]
console.log(Object.prototype.toString.call("hello")); // [object String]

// 类型转换
// 转换为字符串
console.log(String(123)); // 输出: "123"
console.log(String(true)); // 输出: "true"
console.log(String(null)); // 输出: "null"
console.log(String(undefined)); // 输出: "undefined"
console.log(123 + ""); // 输出: "123" (隐式转换)

// 转换为数字
console.log(Number("123")); // 输出: 123
console.log(Number("123.45")); // 输出: 123.45
console.log(Number(true)); // 输出: 1
console.log(Number(false)); // 输出: 0
console.log(Number(null)); // 输出: 0
console.log(Number(undefined)); // 输出: NaN
console.log(+"123"); // 输出: 123 (使用+运算符隐式转换)

// 转换为布尔值
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(!!"hello"); // 输出: true (使用!!运算符隐式转换)

以上内容涵盖了 JavaScript 的基本数据类型及其相关操作,包括 Undefined、Null、Boolean、Number 和 String 类型。理解这些数据类型及其行为对于编写健壮的 JavaScript 代码至关重要。

案例案例

下面我将通过几个实际开发中常见的场景,展示不同数据类型的具体应用。

1. 表单验证(Boolean/String 应用)

/**
 * 用户注册表单验证
 * 应用: Boolean判断, String处理
 */
function validateRegistrationForm(user) {
  // 检查用户名
  if (!user.username || user.username.trim().length < 6) {
    return {
      valid: false,
      message: "用户名不能为空且至少6个字符"
    };
  }

  // 检查密码强度 (至少8位,包含字母和数字)
  const passwordRegex = /^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{8,}$/;
  if (!passwordRegex.test(user.password)) {
    return {
      valid: false,
      message: "密码必须至少8位且包含字母和数字"
    };
  }

  // 检查邮箱格式
  const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
  if (!emailRegex.test(user.email)) {
    return {
      valid: false,
      message: "请输入有效的邮箱地址"
    };
  }

  // 检查同意条款 (Boolean类型检查)
  if (!user.agreeTerms) {
    return {
      valid: false,
      message: "必须同意服务条款"
    };
  }

  // 所有验证通过
  return {
    valid: true,
    message: "验证通过"
  };
}

// 测试用例
const testUser1 = {
  username: "john_doe",
  password: "abc12345",
  email: "john@example.com",
  agreeTerms: true
};

const testUser2 = {
  username: "joe",
  password: "password",
  email: "invalid-email",
  agreeTerms: false
};

console.log(validateRegistrationForm(testUser1));
// 输出: { valid: true, message: "验证通过" }

console.log(validateRegistrationForm(testUser2));
// 输出: { valid: false, message: "用户名不能为空且至少6个字符" }

2. 购物车计算(Number 应用)

/**
 * 购物车结算功能
 * 应用: Number精确计算, 浮点数处理
 */
class ShoppingCart {
  constructor() {
    this.items = [];
    this.taxRate = 0.08; // 8%税率
  }

  addItem(name, price, quantity = 1) {
    this.items.push({
      name,
      // 使用Number()确保价格为数字类型
      price: Number(price),
      quantity: Number(quantity)
    });
  }

  // 计算小计 (避免浮点数精度问题)
  calculateSubtotal() {
    // 使用整数运算避免浮点问题 (以分为单位)
    const subtotalInCents = this.items.reduce((total, item) => {
      return total + Math.round(item.price * 100) * item.quantity;
    }, 0);
    
    // 转换回元
    return subtotalInCents / 100;
  }

  // 计算税费
  calculateTax() {
    const subtotal = this.calculateSubtotal();
    // 使用toFixed解决显示问题,但返回数字类型
    return parseFloat((subtotal * this.taxRate).toFixed(2));
  }

  // 计算总价
  calculateTotal() {
    const subtotal = this.calculateSubtotal();
    const tax = this.calculateTax();
    return parseFloat((subtotal + tax).toFixed(2));
  }

  // 生成账单摘要
  generateReceipt() {
    console.log("=== 购物清单 ===");
    this.items.forEach(item => {
      console.log(`${item.name} x${item.quantity}: ¥${(item.price * item.quantity).toFixed(2)}`);
    });

    console.log("\n=== 结算信息 ===");
    console.log(`小计: ¥${this.calculateSubtotal().toFixed(2)}`);
    console.log(`税费 (${this.taxRate * 100}%): ¥${this.calculateTax().toFixed(2)}`);
    console.log(`总计: ¥${this.calculateTotal().toFixed(2)}`);
  }
}

// 使用示例
const cart = new ShoppingCart();
cart.addItem("iPhone 13", 5999.99);
cart.addItem("AirPods Pro", 1499, 2);
cart.addItem("USB-C 充电线", 79.5, 3);

cart.generateReceipt();
/*
输出:
=== 购物清单 ===
iPhone 13 x1: ¥5999.99
AirPods Pro x2: ¥2998.00
USB-C 充电线 x3: ¥238.50

=== 结算信息 ===
小计: ¥9236.49
税费 (8%): ¥738.92
总计: ¥9975.41
*/

3. 用户配置处理(Null/Undefined 应用)

/**
 * 应用配置管理器
 * 应用: Null/Undefined检查, 默认值处理
 */
class AppConfig {
  constructor(defaultConfig = {}) {
    // 合并默认配置
    this.config = {
      theme: "light",
      fontSize: 14,
      notifications: true,
      ...defaultConfig
    };
  }

  // 获取配置项 (处理可能的undefined)
  get(key) {
    // 使用nullish coalescing操作符(??)提供默认值
    return this.config[key] ?? `[配置项${key}不存在]`;
  }

  // 设置配置项 (处理null值)
  set(key, value) {
    if (value === null) {
      console.warn(`配置项${key}不能设置为null,操作已忽略`);
      return false;
    }
    
    // 使用optional chaining(?.)安全访问
    if (this.config?.[key] !== undefined || this.config.hasOwnProperty(key)) {
      this.config[key] = value;
      return true;
    }
    
    console.warn(`配置项${key}不存在,无法设置`);
    return false;
  }

  // 重置为默认值 (处理undefined情况)
  reset(key) {
    const defaults = {
      theme: "light",
      fontSize: 14,
      notifications: true
    };

    if (key === undefined) {
      // 重置所有配置
      this.config = { ...defaults };
      return true;
    }

    if (defaults[key] !== undefined) {
      this.config[key] = defaults[key];
      return true;
    }

    return false;
  }

  // 显示当前配置
  display() {
    console.log("当前配置:");
    Object.entries(this.config).forEach(([key, value]) => {
      console.log(`${key}: ${value} (${typeof value})`);
    });
  }
}

// 使用示例
const config = new AppConfig({
  theme: "dark",
  language: "zh-CN"
});

config.display();
/*
输出:
当前配置:
theme: dark (string)
fontSize: 14 (number)
notifications: true (boolean)
language: zh-CN (string)
*/

console.log(config.get("theme")); // 输出: dark
console.log(config.get("nonExistent")); // 输出: [配置项nonExistent不存在]

config.set("fontSize", 16);
config.set("nonExistent", "value"); // 警告: 配置项nonExistent不存在,无法设置
config.set("theme", null); // 警告: 配置项theme不能设置为null,操作已忽略

config.display();
/*
输出:
当前配置:
theme: dark (string)
fontSize: 16 (number)
notifications: true (boolean)
language: zh-CN (string)
*/

config.reset("fontSize");
config.display();
/*
输出:
当前配置:
theme: dark (string)
fontSize: 14 (number)
notifications: true (boolean)
language: zh-CN (string)
*/

4. 字符串模板生成器(String 高级应用)

/**
 * 动态HTML模板生成器
 * 应用: 模板字符串, 多行字符串, 字符串插值
 */
class TemplateEngine {
  constructor() {
    this.templates = {};
  }

  // 注册模板
  registerTemplate(name, templateString) {
    this.templates[name] = templateString;
  }

  // 渲染模板
  render(templateName, data = {}) {
    if (!this.templates[templateName]) {
      throw new Error(`模板 ${templateName} 未注册`);
    }

    let result = this.templates[templateName];
    
    // 替换所有 ${prop} 为实际值
    result = result.replace(/\$\{(\w+)\}/g, (match, prop) => {
      // 处理嵌套属性 (如 user.name)
      const value = prop.split('.').reduce((obj, key) => {
        return obj?.[key];
      }, data);
      
      // 如果值为undefined或null,替换为空字符串
      return value !== undefined && value !== null ? value : '';
    });

    return result;
  }
}

// 使用示例
const engine = new TemplateEngine();

// 注册用户卡片模板
engine.registerTemplate('userCard', `
  <div class="user-card">
    <h2>${'user.name'}</h2>
    <p class="email">${'user.email'}</p>
    
    ${'user.avatar' 
      ? `<img src="${'user.avatar'}" alt="${'user.name'}'s avatar" class="avatar">`
      : '<div class="default-avatar">No Avatar</div>'
    }
    
    <ul class="stats">
      <li>Posts: ${'stats.posts'}</li>
      <li>Followers: ${'stats.followers'}</li>
      <li>Following: ${'stats.following'}</li>
    </ul>
    
    ${'user.isAdmin' 
      ? '<button class="admin-btn">Admin Panel</button>' 
      : '<button class="message-btn">Send Message</button>'
    }
  </div>
`);

// 准备数据
const userData = {
  user: {
    name: "Alice Johnson",
    email: "alice@example.com",
    avatar: "https://example.com/avatars/alice.jpg",
    isAdmin: true
  },
  stats: {
    posts: 42,
    followers: 1024,
    following: 64
  }
};

// 渲染模板
const renderedHtml = engine.render('userCard', userData);
console.log(renderedHtml);
/*
输出:
<div class="user-card">
  <h2>Alice Johnson</h2>
  <p class="email">alice@example.com</p>
  
  <img src="https://example.com/avatars/alice.jpg" alt="Alice Johnson's avatar" class="avatar">
  
  <ul class="stats">
    <li>Posts: 42</li>
    <li>Followers: 1024</li>
    <li>Following: 64</li>
  </ul>
  
  <button class="admin-btn">Admin Panel</button>
</div>
*/

5. 数字格式化工具(Number 高级应用)

/**
 * 数字格式化工具集
 * 应用: Number处理, 数学运算, 国际化
 */
class NumberFormatter {
  // 格式化货币
  static formatCurrency(value, currency = 'CNY', locale = 'zh-CN') {
    return new Intl.NumberFormat(locale, {
      style: 'currency',
      currency: currency,
      minimumFractionDigits: 2,
      maximumFractionDigits: 2
    }).format(Number(value));
  }

  // 格式化百分比
  static formatPercent(value, decimalPlaces = 2) {
    const percent = Number(value) * 100;
    return percent.toFixed(decimalPlaces) + '%';
  }

  // 格式化大数字 (如 1K, 1M)
  static abbreviateNumber(value, decimalPlaces = 1) {
    const num = Number(value);
    if (num < 1000) return num.toString();
    
    const units = ['K', 'M', 'B', 'T'];
    const exp = Math.floor(Math.log10(num) / 3);
    const abbreviated = num / Math.pow(1000, exp);
    
    // 处理1.0K等情况,去掉小数部分
    if (abbreviated % 1 === 0 && decimalPlaces > 0) {
      return abbreviated.toFixed(0) + units[exp - 1];
    }
    
    return abbreviated.toFixed(decimalPlaces) + units[exp - 1];
  }

  // 生成随机数范围
  static randomInRange(min, max, integer = true) {
    const minNum = Number(min);
    const maxNum = Number(max);
    const random = Math.random() * (maxNum - minNum) + minNum;
    return integer ? Math.floor(random) : random;
  }

  // 安全计算 (避免浮点数精度问题)
  static safeCalculate(operation, ...numbers) {
    // 将所有数字转换为整数(放大10000倍)
    const scaledNumbers = numbers.map(num => 
      Math.round(Number(num) * 10000)
    );
    
    let result;
    switch (operation) {
      case '+':
        result = scaledNumbers.reduce((sum, num) => sum + num, 0);
        break;
      case '-':
        result = scaledNumbers.slice(1).reduce(
          (diff, num) => diff - num, scaledNumbers[0]
        );
        break;
      case '*':
        result = scaledNumbers.reduce((product, num) => product * num, 1);
        // 因为每个数都放大了10000倍,乘法需要额外处理
        result = result / Math.pow(10000, scaledNumbers.length - 1);
        break;
      case '/':
        result = scaledNumbers.slice(1).reduce(
          (quotient, num) => quotient / num, scaledNumbers[0]
        );
        // 除法也需要调整
        result = result * Math.pow(10000, scaledNumbers.length - 2);
        break;
      default:
        throw new Error('不支持的运算类型');
    }
    
    // 缩小回原始比例
    return result / 10000;
  }
}

// 使用示例
console.log(NumberFormatter.formatCurrency(1234.567)); // 输出: ¥1,234.57
console.log(NumberFormatter.formatCurrency(1234.567, 'USD', 'en-US')); // 输出: $1,234.57

console.log(NumberFormatter.formatPercent(0.12345)); // 输出: 12.35%
console.log(NumberFormatter.formatPercent(0.12345, 1)); // 输出: 12.3%

console.log(NumberFormatter.abbreviateNumber(1234)); // 输出: 1.2K
console.log(NumberFormatter.abbreviateNumber(1234567)); // 输出: 1.2M
console.log(NumberFormatter.abbreviateNumber(1000)); // 输出: 1K

console.log(NumberFormatter.randomInRange(1, 10)); // 输出: 1到10的随机整数
console.log(NumberFormatter.randomInRange(0.1, 1.0, false)); // 输出: 0.1到1.0的随机浮点数

// 解决浮点数精度问题
console.log(0.1 + 0.2); // 输出: 0.30000000000000004
console.log(NumberFormatter.safeCalculate('+', 0.1, 0.2)); // 输出: 0.3

console.log(1.1 * 1.1); // 输出: 1.2100000000000002
console.log(NumberFormatter.safeCalculate('*', 1.1, 1.1)); // 输出: 1.21

这些案例展示了 JavaScript 数据类型在实际开发中的应用场景,涵盖了表单验证、购物车计算、配置管理、模板生成和数字格式化等常见需求。每个案例都充分利用了不同数据类型的特性,并处理了边界情况和潜在问题。

相关文章:

  • 《AI开发工具和技能实战》专栏规划:从工具到应用的全链路指南
  • IntelliJ IDEA使用技巧(json字符串格式化)
  • vue3+vue-router4的安装使用以及路由守卫
  • Android audio(2)-audioservice
  • 蓝桥杯-卡片
  • android wifi 连接流程(framework)
  • k8s之Service类型详解
  • 01-Redis-基础
  • JavaScript 用法详解
  • C++使用WebView2控件,通过IPC通信与Javascript交互
  • 蓝桥杯-门牌制作
  • JVM生产环境调优实战
  • 如何将 对个 把b3dm 合并成一个模型
  • pnpm 中 Next.js 模块无法找到问题解决
  • Android 定制飞行模式和通话中设置菜单置灰
  • Social GAN(CVPR2018)
  • K8S核心技术点
  • 深入解析:Python爬取Bilibili视频的技术创新与高阶实践
  • 内容中台驱动AI服务智能化实践
  • Go 语言数据类型
  • 正规的百度快排seo/重庆seo霸屏
  • 行业网站系统/网店推广软文范例
  • 什么网站可以做动画/竞价托管哪家效果好
  • 深圳网站建设制作设计/公司员工培训方案
  • 武汉洪山做网站推广/十大广告公司
  • 0511城市建设网站棚户区改造/百度问答首页