JavaScript中new关键字被忽略也能运行?这属于特殊边缘情况吗?
JS中
Date()带new和不带new的核心差异 先明确本质区别:new绝对不是语法糖
两种写法的返回值和执行逻辑完全符合ECMAScript规范定义,没有任何语法糖的关系:
- 带
new调用Date:Date作为构造函数执行,返回存储了对应时间信息的Date实例对象,你传入的日期参数会被正常解析,实例支持getFullYear()、getTime()等所有Date原型方法。 - 不带
new直接调用Date:Date作为普通函数执行,所有传入的参数都会被直接忽略,永远返回当前时间的本地格式化字符串,和new Date().toString()的输出完全一致。
你观察到版本2“看起来能正常运行”完全是测试场景巧合:要么是你测试时选的日期刚好是当天,要么是字符串逐位比较的结果碰巧和实际时间顺序一致,这种正确完全不可靠。
关于隐式类型转换
你看到日期对象之间可以直接做逻辑比较,本质是JS的隐式类型转换机制:Date原型重写了valueOf()方法,返回对应时间的毫秒级时间戳,当两个Date对象做大小比较时,JS会自动调用valueOf()拿到时间戳再比较,这个行为是规范定义的可靠行为,但前提是你操作的确实是Date实例,而非字符串。
如果是不带new得到的字符串做比较,JS会按照字符的Unicode编码逐位对比,不同浏览器的Date字符串输出格式存在差异,很容易出现不符合预期的结果。
潜在坑点汇总
- 参数失效问题:不带
new的写法不会解析你传入的日期参数,所有变量得到的都是代码执行时刻的当前时间,只要选择非当天的日期立刻会出逻辑错误。 - 方法调用报错:字符串无法调用任何Date原型的方法,后续如果要做
getMonth()、toISOString()等操作会直接抛出异常。 - 运算逻辑异常:字符串参与算术运算时会触发拼接逻辑,比如
start_date + 86400000不会得到明天的时间,只会得到字符串拼接的结果。 - 跨浏览器兼容性问题:不同浏览器的
Date()返回的字符串格式存在细微差异,字符串比较的结果无法保证统一。
规范写法
版本1是唯一符合规范的正确写法,所有涉及日期解析、操作、比较的场景都应该使用new Date()构造实例。如果要做日期比较,更稳妥的写法是主动提取时间戳再对比,同时补充合法性校验:
$('input#foo-create-submit').on('click', function(e){ let start_date = new Date($('#id_start_date').val()); let end_date = new Date($('#id_end_date').val()); // 先校验日期合法性 if (isNaN(start_date.getTime()) || isNaN(end_date.getTime())) { alert('请输入合法的日期格式'); return false; } // 提取时间戳比较,避免隐式转换意外 let start_ts = start_date.getTime(); let end_ts = end_date.getTime(); if (start_ts > end_ts) { alert('开始时间不能晚于结束时间'); return false; } /* 自定义逻辑写在这里 ... */ });
内容的提问来源于stack exchange,提问作者Homunculus Reticulli
相关产品推荐
相关产品推荐

