全部学科
Python全栈
python
NodeJS全栈
nodejs
小程序首页
📅 2026-05-16 7 分钟 ✍️ juanwangdev

JavaScript 构造函数与原型

构造函数与原型是 JavaScript 创建对象和实现共享方法的基础机制,理解它们是掌握原型链的关键。

构造函数

JavaScript
// 构造函数:用于创建同类对象
function Person(name, age) {
    // this 指向新创建的实例
    this.name = name;
    this.age = age;
}

// 使用 new 调用
const p1 = new Person('Tom', 25);
const p2 = new Person('Jerry', 30);

console.log(p1.name);  // 'Tom'
console.log(p2.name);  // 'Jerry'
console.log(p1.constructor === Person);  // true

new 操作符执行流程

JavaScript
// new 做了四件事:
function Person(name) {
    this.name = name;
}
const p = new Person('Tom');

// 等价于:
const p = Object.create(Person.prototype);  // 1. 创建空对象,继承原型
Person.call(p, 'Tom');                       // 2. 执行构造函数,绑定 this
return p;                                     // 3. 返回新对象(除非构造函数返回对象)

原型对象 prototype

JavaScript
// prototype:存储实例共享的方法和属性
function Person(name) {
    this.name = name;  // 实例属性(每个实例独立)
}

// 原型方法(所有实例共享)
Person.prototype.sayHello = function() {
    console.log('Hello, ' + this.name);
};
Person.prototype.species = 'human';  // 共享属性

const p1 = new Person('Tom');
const p2 = new Person('Jerry');

p1.sayHello();  // 'Hello, Tom'
p2.sayHello();  // 'Hello, Jerry'

// 方法共享,内存高效
console.log(p1.sayHello === p2.sayHello);  // true
console.log(p1.species === p2.species);    // true

实例属性 vs 原型属性

JavaScript
function Person(name, age) {
    // 实例属性:每个实例独立存储
    this.name = name;
    this.age = age;
}

Person.prototype.sayHello = function() {
    console.log(this.name);
};
Person.prototype.species = 'human';

const p1 = new Person('Tom', 25);

// 查看属性来源
console.log(p1.hasOwnProperty('name'));      // true(实例属性)
console.log(p1.hasOwnProperty('age'));       // true
console.log(p1.hasOwnProperty('sayHello'));  // false(原型属性)
console.log(p1.hasOwnProperty('species'));   // false

// 实例属性可覆盖原型属性
Person.prototype.age = 0;
const p2 = new Person('Jerry', 30);
console.log(p2.hasOwnProperty('age'));  // true(实例属性覆盖)
console.log(p2.age);                    // 30(实例优先)

constructor 属性

JavaScript
// prototype.constructor 指回构造函数
function Person(name) {
    this.name = name;
}
console.log(Person.prototype.constructor === Person);  // true

// 实例通过 constructor 找到构造函数
const p = new Person('Tom');
console.log(p.constructor === Person);                // true
console.log(p.__proto__.constructor === Person);       // true

// 重写 prototype 会丢失 constructor
Person.prototype = {
    sayHello: function() {
        console.log(this.name);
    }
};
console.log(Person.prototype.constructor === Person);  // false
console.log(Person.prototype.constructor === Object);  // true

// 手动修复 constructor
Person.prototype.constructor = Person;
console.log(Person.prototype.constructor === Person);  // true

原型重写

JavaScript
// 方式一:逐个添加(推荐,保留 constructor)
function Person(name) {
    this.name = name;
}
Person.prototype.sayHello = function() {};
Person.prototype.sayBye = function() {};

// 方式二:整体重写(需修复 constructor)
function Animal(type) {
    this.type = type;
}
Animal.prototype = {
    constructor: Animal,  // 必须手动修复
    speak: function() {
        console.log(this.type + ' speaks');
    },
    move: function() {
        console.log(this.type + ' moves');
    }
};

const dog = new Animal('dog');
dog.speak();  // 'dog speaks'
console.log(dog.constructor === Animal);  // true

最佳实践

JavaScript
// 推荐:实例属性放构造函数,方法放原型
function User(name, email) {
    // 实例属性
    this.name = name;
    this.email = email;
    this.friends = [];  // 可变数据放实例
}

// 共享方法放原型
User.prototype.getInfo = function() {
    return `${this.name}: ${this.email}`;
};
User.prototype.addFriend = function(friend) {
    this.friends.push(friend);
};

// 静态方法:直接定义在构造函数上(不参与原型链)
User.createGuest = function() {
    return new User('Guest', 'guest@example.com');
};

const guest = User.createGuest();
console.log(guest.getInfo());  // 'Guest: guest@example.com'

注意事项

  • 构造函数首字母大写(约定),用 new 调用
  • 原型方法中的 this 指向调用实例
  • 重写 prototype 后需修复 constructor
  • 可变数据(数组、对象)不要放在原型上
JavaScript
// 错误:忘记 new
const p = Person('Tom');  // this 指向全局对象或 undefined
console.log(p);           // undefined
console.log(window.name); // 'Tom'(严格模式下报错)

// 保护措施
function Person(name) {
    if (!(this instanceof Person)) {
        return new Person(name);
    }
    this.name = name;
}

// 或使用 new.target(ES6)
function Person(name) {
    if (!new.target) {
        return new Person(name);
    }
    this.name = name;
}

要点总结

  • 构造函数用 new 调用,this 指向新实例
  • prototype 存储共享方法,所有实例共用,节省内存
  • 实例属性放构造函数,共享方法放原型
  • prototype.constructor 默认指向构造函数,重写后需手动修复
  • 可变数据放实例,不可变数据和方法可放原型
  • 避免忘记 new,可添加保护检查

📝 发现内容有误?点击此处直接编辑

← 上一篇 JavaScript 原型链继承
下一篇 → JavaScript Generator 函数与异步生成器
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库