JavaScript 是基于原型的语言,对象通过原型链共享属性和方法。理解原型是理解 this、继承、new 的基础。
1. 三个关键对象
每个函数都有 prototype 属性(原型对象);每个对象都有内部属性 [[Prototype]](可通过 __proto__ 或 Object.getPrototypeOf 访问)。函数的 prototype 用作 new 出来的实例的原型:
function Person(name) {
this.name = name;
}
Person.prototype.sayHi = function() {
return "你好," + this.name;
};
const p = new Person("张三");
p.sayHi(); // 你好,张三
p.__proto__ === Person.prototype; // true
方法放在 prototype 上而不是构造函数里,所有实例共享同一份方法,节省内存。
2. 原型链
访问对象的属性时,先找自身,找不到就沿着 [[Prototype]] 向上查找,直到 Object.prototype,再往上是 null:
p.sayHi // Person.prototype 上找到
p.toString // Person.prototype 没有 → Object.prototype 上找到
p.notExist // 一路找到 null,返回 undefined
3. new 的过程
new 做了四件事:创建空对象、把它的原型指向构造函数的 prototype、以它为 this 执行构造函数、返回它(构造函数返回对象时以返回值为准):
function myNew(Constructor, ...args) {
const obj = Object.create(Constructor.prototype); // 1+2
const result = Constructor.apply(obj, args); // 3
return result instanceof Object ? result : obj; // 4
}
4. ES6 class 与原型的关系
class 只是原型机制的语法糖,本质不变:
class Animal {
constructor(name) { this.name = name; }
eat() { return this.name + "在吃"; }
}
class Dog extends Animal {
bark() { return this.name + "汪汪"; }
}
typeof Animal; // "function"
Dog.prototype.__proto__ === Animal.prototype; // true,实现继承
class 的 extends 做了两件事:子类原型指向父类原型(方法继承),并在构造时自动调用 super()(属性继承)。
5. 常见误区
不要修改内置对象的原型(如给 Array.prototype 加方法),会污染全局并破坏 for…in;instanceof 检查的是原型链而非类型本身,跨 iframe 的对象 instanceof 会失效,此时用 Array.isArray 这样的专用方法。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END








暂无评论内容