You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为什么含new关键字的JavaScript代码在Chrome DevTools与JSFiddle输出不同

问题分析

相关测试代码如下:

function foo() {
    this.baz = "baz"
    console.log(this.bar + " " + baz);
}

var bar = "bar";
var baz = new foo();
console.log(baz.baz)

核心差异根源

两个执行环境的作用域隔离规则不同,导致foo函数内对baz变量的查找结果不一致:

  • JSFiddle的执行逻辑

    JSFiddle默认会把用户编写的JS代码包裹在window.onload(或DOMContentLoaded)的回调函数中执行,你声明的var bar、var baz都不是全局变量,而是这个回调函数的局部变量:

    1. 变量提升阶段:回调作用域内先声明foo函数、bar、baz变量,三者初始值均为undefined
    2. 执行bar = "bar"完成赋值
    3. 执行var baz = new foo()时,先运行构造函数foo:
      • this指向新创建的实例,实例自身没有bar属性,所以this.bar是undefined
      • 查找baz变量时,向上追溯到回调作用域的baz,此时new foo()还没有执行完成,返回值还没赋值给baz,所以baz是undefined
    4. 最终输出undefined undefined,和你看到的结果一致。
  • Chrome Sources面板的执行逻辑

    Sources面板运行的代码默认直接暴露在全局作用域下,你用var声明的bar、baz都会挂载到window对象上成为全局属性。
    你看到baz是{baz:"baz"}对象的原因是当前页面全局作用域下已经存在一个提前声明的baz对象(可能是页面内置变量、你之前运行代码遗留的变量),构造函数foo执行时找到的就是这个已存在的对象,转成字符串输出就是[object Object]。
    如果你打开无痕模式的新标签页运行这段代码,得到的结果会和JSFiddle一致。

补充说明

你代码里的核心易错点:var baz = new foo()的执行顺序是先运行new foo(),再把返回值赋值给baz,构造函数运行过程中baz还没完成赋值,所以正常情况下读取到的永远是提升后的初始值undefined。

内容的提问来源于stack exchange,提问作者ArunM

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 23:27:04