TypeScript 与 ES6 核心差异解析:从变量声明到模块系统

作者:青柠

时间:2026-10-31

浏览:179

本文深入解析 TypeScript 与 ES6 的核心区别。重点对比 var/let/const 的作用域与变量提升机制,详解模板字符串、箭头函数中 this 指向及默认参数等 ES6 特性。同时阐述 TypeScript 的静态类型系统、编译流程及其在大型项目中的优势,并对比两者在适用场景上的差异,帮助开发者根据项目需求做出技术选型。

文章目录

概述

若关注 JavaScript 的最新动态,必然对 ECMAScript 6(ES6)及 ECMAScript 7 的热议有所耳闻。许多人会问:ECMAScript 与 JavaScript 究竟有何关联与区别? ECMAScript 是一种脚本语言的规范标准。JavaScript 则是该规范的一个具体实现,此外还有 Jscript 和 ActionScript 等实现方式。

ECMAScript 6和ES7简介

JavaScript 主要运行于浏览器环境(也可运行于 Node.js 服务端)。各浏览器均基于 ECMAScript 规范实现各自的 JavaScript 引擎。因此,浏览器提供的功能大体一致,使得代码具有跨浏览器兼容性;然而,不同浏览器对同一功能的实现细节可能存在细微差异。

TypeScript概述

TypeScript 是 JavaScript 的超集,可编译为纯 JavaScript 代码。它支持在任何浏览器、计算机及操作系统上运行,且为开源项目。

(注:以上内容源自 TypeScript 官网)

核心差异概览

特性TypeScriptES6 (ES2015+)
类型系统静态类型(编译时检查)动态类型(运行时检查)
超集关系ES6 的超集,包含所有 ES6 特性TypeScript 的子集
编译需求需要编译为 JavaScript现代浏览器/Node.js 可直接运行
主要目标大型应用、企业级开发所有 JavaScript 应用

TypeScript 系统详细对比

变量声明:var、let 与 const

ES6 引入了 let 和 const 两种新的变量声明方式。为何需要新增声明方式?让我们通过代码示例来探讨。

var a = 1;
// ~~~
var a = 2;
console.log(a);

上述代码运行正常,但第一个 a 变量会被第二个声明的 a 覆盖,导致打印结果为 2。若中间包含大量代码且命名不规范,此类问题极易引发 Bug,这也是早期 JavaScript 开发中常见的问题来源。

let 关键字的使用

let a = 1;
// ~~~
let a = 2;     //这里就会报错
console.log(a);

在第二个 let a 声明处会直接报错,代码无法运行。

var x = 'global';
let y = 'global';
console.log(this.x); // "global"
console.log(this.y); // undefined

使用 声明的变量会绑定到全局对象(或当前上下文对象),而 声明的变量则不会绑定到全局对象。

function varTest() {
  var x = 1;
  {
    var x = 2;  // 同样的变量!
    console.log(x);  // 2
  }
  console.log(x);  // 2
}

function letTest() {
  let x = 1;
  {
    let x = 2;  // 不同的变量
    console.log(x);  // 2
  }
  console.log(x);  // 1
}

let声明的变量只在其声明的块或子块中可用,这一点,与var相似。二者之间最主要的区别在于var声明的变量的作用域是整个封闭函数。注意:这里是用{}围成的子块,以下情况是一样的打印结果

function varTest() {
      var x = 1;
      function test() {
            var x = 2; // 不同的变量
            console.log(x); // 2
      }
      test();
      console.log(x); // 1
}
function letTest() {
      let x = 1;
      function test() {
            let x = 2; // 不同的变量
            console.log(x); // 2
      }
      test();
      console.log(x); // 1
}
console.log(name);
console.log(age);
var name = "测试";
let age = 18;

运行结果

概述

变量提升现象:可以看到,name 打印结果为 undefined,而 age 直接报错。这表明 var 声明的变量存在变量提升,而 let 没有。 暂时性死区(TDZ):ES6 明确规定,若块中存在 和 命令,则该区块对这些变量从一开始就形成封闭作用域。只要在声明前使用这些变量,就会报错。这种语法机制称为“暂时性死区”(temporal dead zone,简称 TDZ)。

const 关键字的使用

const 声明的是常量,具有只读属性,不可修改。需要注意的是,不可修改的仅仅是 引用地址 本身,而 引用地址 内部属性的变化是允许的。具体理解如下。

const a = 0;
const b = {
    c: 0,
    d: 1
}
b.c = 15;   // 没有问题
b = 14;     // 抛出异常
a = 12;     // 抛出异常

运行结果

概述

模板字面量(Template Literals)

初次接触此特性便令人喜爱,它极大地简化了字符串拼接操作,无需再使用繁琐的拼接方式。

键盘按键位置

位于键盘 Esc 键下方的第一个按键(即反引号键)。

使用示例

let message = "什么玩意";
  let logMessage = `
    模板字面量是${message},
    我是第二行了吧
  `;
  console.log(logMessage) // 模板字面量是什么玩意

${} 用于插入变量,且保留其中的空格和换行格式。

运行结果

概述

箭头函数(Arrow Functions)

据称 JavaScript 开发中有几大公认难点。若前述的 var声明变量混淆 算作一个小难点,那么 this指向 则是一个大挑战,该问题在现代编程中一直存在。箭头函数 的出现解决了绝大多数 this指向 相关的问题。

this 指向保持不变

// 图片地址
 let img_url = "https://upload-images.jianshu.io/upload_images/13962818-8ab62dc051112573.jpg";
 // 创建对象
 let img = new Image();
 // 改变图片的src
 img.src = img_url;
 // 加载完成执行
 img.onload = function () {
   // 打印
   console.dir(this);
 };

 // 创建对象
 let img1 = new Image();
 // 改变图片的src
 img1.src = img_url;
 // 加载完成执行
 img1.onload = () => {
      // 打印
      console.log(this);
 };

运行结果

概述

使用箭头函数时,this 仍指向外部的 window对象,而普通函数的 this 指向 调用者(此处调用者为 img对象)。

若箭头函数仅包含一条语句,可省略 return。

let arr = [1, 2, 3, 4, 5, 6, 7];
let filterArr = arr.filter((item) => item % 2 === 0);
console.log(arr, filterArr);

运行结果

概述

此处的 filter 方法需返回一个值。若返回值为 true,则保留该值;若为 false,则过滤掉,并返回一个新数组,原数组保持不变。尽管箭头函数看似未显式返回,但这正是其特性之一:若仅有一条语句,可省略 return。

函数参数默认值

function sum(x = 1, y = 2, z = 3){
    return x + y + z;
}
sum();      // 6
sum(2 , 3); // 8

展开运算符与剩余参数

let params = [1,2,3];
console.log(...params);

运行结果

概述

当需要编写支持动态参数的方法时,可使用此符号。

function push(targetArr, ...nums){
    for(let i = 0,len = nums.length; i < len; i++){
        targetArr.push(nums[0]);
    }
}

let arr = [];
push(arr, 12, 45);
console.log(arr)

运行结果

概述

通过此类 push 方法,可支持一个或多个参数,无需将后续参数整合为对象或数组,书写更为简洁。

乘方运算符

// Es5
const area = 3.14 * Math.pow(r, 2);
// Es6
const area = 3.14 * (r ** r);

模块(Modules)

注意:若使用 HTML 测试模块内容,需执行两步操作。

  • 在 script 标签上务必添加 type="module",否则报错,提示不能在模块外部直接使用 import 语句。
  • 使用服务器模式打开 HTML文件(VS Code 可安装 Live Server插件 插件,WS 可直接点击右上角选择浏览器运行),否则可能因跨域限制而报错。

index.js 示例

// 1 
export const index = 5555;

const key = "key";
const good = 1234;

// 2 A
export {
      key,good
}

// B
export default {
      test :function(params) {
          console.log(params)  
      }
}
测试 HTML 代码
<script type="module">
            import { index } from "./index.js";    //导入1
            import utils from "./index.js";        //导入2
            import * as newUtils from "./index.js";//导入3
            console.log(index);
            console.log(newGood);
            console.log(newKey);
            utils.test("这个世界");
            console.log(newUtils);
            console.log(newUtils.index);
            console.log(newUtils.good);
            console.log(newUtils.key);
            newUtils.default.test("这个世界");
 </script>

1 和 2 两种导出方式本质相同,区别在于 1 是逐个导出,而 2 是一次性导出多个。两者皆可,建议:若导出内容较少,可使用方式 2;若导出内容过多,导出语句可能位于文件底部,此时推荐逐个导出(此为个人建议)。

后续两种 A(export)和 B(export default)导出需注意以下几点。

  1. export 导出的元素,可通过 import {A, B} from "文件地址" 引入,这相当于进行了对象解构赋值。
  2. export default 导出的元素可直接接收,默认导出的是一个匿名对象,需指定名称后方可使用其属性,此处不能使用解构赋值。
  3. 第三种导入方式将内部所有导出集中到 newUtils,打印后可发现,导出 B 中的对象被放置在 newUtils 的 default 属性中。

运行结果

概述

更改导出名称

index.js 示例

const index = 5555;
const newInfo = 4444;
const key = "key";
const good = 1234;  
export {
      newInfo,
      index as newIndex
}
export default {
      newKey :key,
      good,
      test :function(params) {
          console.log(params)  
      }
}
<script type="module">
            import { newIndex, newInfo as info } from "./index.js";
            import utils from "./index.js";
            import * as newUtils from "./index.js";
            console.log(newIndex);         //关注点1 
            console.log(info);             //关注点2
            utils.test("这个世界");
            console.log(utils.good);
            console.log(utils.newKey);
            console.log(newUtils); 
            console.log(newUtils.newInfo);  //关注点3
            console.log(newUtils.newIndex); //关注点4
            newUtils.default.test("这个世界");
 </script>

运行结果

概述

改名方式 1

good 与 key 均通过 export default 导出,但 key 被重命名为 newKey,导致导入时需使用新键名 newKey。

改名方式 —— as 关键字

  • newInfo 与 index 均通过 export 导出,但 index 通过 as 转换为 newIndex,导致导入时需使用新键名 newIndex。
  • newInfo 导出时为 newInfo,但可在导入时使用 as 关键字,将 newInfo 重命名为 info。

最后需关注 newUtils 对象,导出前改名的结果直接体现于此,而导入时改名则不体现,这符合预期。

开发体验对比

TypeScript 的优势

// 1. 智能提示和自动完成
interface User {
    id: number;
    name: string;
    email: string;
    age?: number;
}

function processUser(user: User) {
    // 输入 user. 时,IDE 会提示所有可用属性
    console.log(user.name); // 有智能提示
    // console.log(user.nam); // 编译时报错:属性不存在
}

// 2. 重构支持
// 重命名变量、函数、类时,TypeScript 能安全地更新所有引用

// 3. 代码文档化
/**
 * 计算两个点的距离
 * @param p1 第一个点
 * @param p2 第二个点
 * @returns 两点间的距离
 */
function calculateDistance(p1: Point, p2: Point): number {
    // 函数签名就是文档
}

// 4. 早期错误检测
const users: User[] = [];
users.push({ name: "张三" }); // 编译时报错:缺少 id 和 email

// 5. 更好的协作
// 类型定义作为团队间的契约

ES6 的情况

// 1. 运行时错误
function processUser(user) {
    console.log(user.name); // 如果 user 是 undefined,运行时崩溃
    console.log(user.nam);  // 拼写错误,运行时返回 undefined
}

// 2. 文档依赖注释
/**
 * @param {Object} user - 用户对象
 * @param {string} user.name - 用户名
 * @param {string} user.email - 邮箱
 */
function processUser(user) {
    // JSDoc 注释,但不是强制的
}

编译与运行流程

TypeScript 编译过程

# 安装 TypeScript
npm install -g typescript

# 编译 TypeScript
tsc index.ts                    # 编译单个文件
tsc -p tsconfig.json           # 使用配置文件编译
tsc --watch                    # 监听模式

# 常用编译选项
tsc --noEmit                   # 只检查,不输出文件
tsc --strict                   # 启用所有严格检查
tsc --target ES2020           # 指定目标版本

ES6 运行方式

# 现代浏览器直接支持 ES6 模块
# 在 HTML 中
&lt;script type="module" src="app.js"&gt;&lt;/script&gt;

# Node.js 中(需要 package.json 中设置 "type": "module")
node app.js

# 或者使用标志
node --experimental-modules app.js

适用场景分析

TypeScript

  • 大型项目:代码量大,需具备更好的可维护性。

  • 团队协作:多人开发,需明确的接口定义。

  • 长期维护:项目生命周期长,需类型安全保障。

  • 库/框架开发:为使用者提供良好的类型支持。

  • 企业级应用:对代码质量有较高要求。

ES6

  • 小型项目:快速原型开发,简单应用。

  • 脚本工具:一次性脚本,命令行工具。

  • 学习/教学:避免类型系统的复杂性。

  • 已有项目迁移:逐步引入 TypeScript。

  • 性能敏感:避免编译开销(尽管开销很小)。

总结

TypeScript 并非旨在取代 ES6,而是在 ES6 基础上增加了类型系统这一强大工具。选择 TypeScript 还是 ES6,主要取决于:

  • 项目规模与复杂度

  • 团队经验与偏好

  • 维护周期长短

  • 对代码质量的要求

对于大多数现代 Web 开发,特别是 React、Vue、Angular 等框架项目,TypeScript 已成为事实上的标准,因其能显著提高开发效率和代码质量。

本文关于 TypeScript 与 ES6 区别的介绍到此结束。如需了解更多相关内容,请搜索本站往期文章或继续阅读相关文章,感谢支持!

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章