原生对象和宿主对象

55 阅读3分钟

一、基础定义与本质区别

1. 原生对象(Native Objects)

  • 定义:由 ECMAScript 规范直接定义的对象,与宿主环境(如浏览器、Node.js)无关。
  • 特点
    • 跨环境一致性:在所有 JavaScript 环境中行为相同(如 ArrayPromise)。
    • 全局可用:无需额外引入,直接通过全局作用域访问(如 window.Array)。
  • 示例StringObjectFunctionDateMap

2. 宿主对象(Host Objects)

  • 定义:由宿主环境提供的对象,用于连接 JavaScript 与外部系统。
  • 特点
    • 环境依赖性:不同宿主环境差异大(如浏览器的 window 与 Node.js 的 global)。
    • 动态扩展:可能随宿主环境升级新增 API(如浏览器的 fetch)。
  • 示例
    • 浏览器:windowdocumentXMLHttpRequestlocalStorage
    • Node.js:processfsmodule

二、核心差异对比表

维度原生对象宿主对象
定义来源ECMAScript 规范宿主环境(如浏览器、Node.js)
是否可模拟可通过 polyfill 模拟(如旧浏览器)部分可模拟(如 jsdom 模拟 DOM)
类型标签[object 类型名](如 [object Array]自定义标签(如 [object HTMLDocument]
典型用途实现语言核心功能(如数据结构、异步)操作外部资源(如 DOM、文件系统)

三、问题

1. 问:window 是原生对象吗?为什么?

    • 不是window 是浏览器宿主环境提供的全局对象,用于封装浏览器功能(如 DOM 操作、BOM 接口)。
    • 虽然 window 包含部分原生对象(如 window.Array),但其本身由宿主环境创建,而非 ECMAScript 规范直接定义。

2. 问:如何判断一个对象是原生对象还是宿主对象?

    • 方法1:检查类型标签(部分情况有效):
      Object.prototype.toString.call([]); // "[object Array]"(原生)  
      Object.prototype.toString.call(document); // "[object HTMLDocument]"(宿主)  
      
    • 方法2:验证是否存在于所有 JavaScript 环境:
      • 若在浏览器和 Node.js 中均存在(如 Promise),则为原生对象。
      • 若仅在特定环境存在(如 document),则为宿主对象。

3. 问:宿主对象与原生对象如何交互?

    • 继承关系:部分宿主对象继承原生对象(如 DOM 元素继承 Object)。
    • 方法调用:宿主对象可调用原生对象的方法(如 document.toString())。
    • 数据传递:原生对象可作为参数或返回值传递给宿主对象(如 Array 作为 fetch 的响应数据)。

4. 问:为什么 Node.js 中没有 windowdocument

    • windowdocument 是浏览器特有的宿主对象,用于操作浏览器界面和网页内容。
    • Node.js 作为服务器端环境,无浏览器界面,因此提供替代宿主对象(如 fshttp)处理文件和网络请求。

四、开发中的应用场景

1. 兼容性处理

  • 宿主对象(如 DOM API)可能存在浏览器兼容性问题,需用特性检测:
    if ('fetch' in window) {
      // 使用原生fetch(现代浏览器)
    } else {
      // 引入polyfill或降级方案
    }
    

2. 环境判断

  • 通过宿主对象存在性判断当前环境:
    function isBrowser() {
      return typeof window !== 'undefined';
    }
    

3. 跨端开发注意事项

  • 避免直接依赖特定宿主对象(如 window),需封装环境无关的接口:
    const storage = typeof localStorage !== 'undefined' ? localStorage : null;