在 JavaScript 中,使用 new
关键字调用函数(构造函数)与直接执行函数有本质区别,不是简单的函数执行。主要区别如下:
1. new
操作符的完整执行过程
function MyClass(name) {
this.name = name;
}
const obj = new MyClass("John"); // 不是简单执行函数!
实际发生的步骤:
创建新对象:创建一个空的纯 JavaScript 对象
{}
绑定原型:将新对象的原型指向构造函数的
prototype
属性
obj.__proto__ = MyClass.prototype
绑定
this
:将构造函数内的this
指向这个新对象执行函数体:像普通函数一样执行构造函数代码(此时
this
指向新对象)返回对象:
如果构造函数未返回对象 → 自动返回新创建的对象
如果返回非对象 → 仍返回新创建的对象
如果返回对象 → 则替代新对象(实际返回该对象)
2. 与直接执行的对比
特性 | new MyClass() |
MyClass() |
---|---|---|
this 指向 |
指向新创建的实例对象 | 严格模式:undefined 非严格模式:全局对象(如 window ) |
返回值 | 自动返回新对象(除非构造函数返回对象) | 返回函数的显式返回值(无返回则为 undefined ) |
原型链 | 自动连接构造函数的原型 | 无原型链建立 |
副作用 | 安全创建实例 | 可能污染全局变量(非严格模式) |
3. 关键区别示例
function Person(name) {
this.name = name;
}
// ✅ 正确用法:new 操作符
const p1 = new Person("Alice");
console.log(p1.name); // "Alice"(实例属性)
// ❌ 直接调用(非严格模式)
const p2 = Person("Bob");
console.log(p2); // undefined(函数无返回值)
console.log(window.name); // "Bob"(污染全局!)
// ❌ 直接调用(严格模式)
"use strict";
const p3 = Person("Chris"); // 抛出错误:Cannot set property 'name' of undefined
4. 特殊情况的返回值
function A() { return { flag: true }; }
function B() { return 42; } // 返回原始值会被忽略
console.log(new A()); // { flag: true }(返回对象)
console.log(new B()); // {}(返回原始值无效,仍生成新对象)
总结:
new
是构造调用:创建新对象 + 绑定原型链 + 绑定this
+ 返回实例直接执行是普通调用:单纯执行函数代码,无对象创建和原型绑定
💡 最佳实践:构造函数首字母大写(如
Person
),提醒调用者必须使用new
。现代 JS 可用 class 语法避免混淆。