JavaScript 原型与原型链
前言JavaScript 的原型机制是实现方法共享和继承的核心基础。其核心分为构造函数的prototype原型对象和实例的__proto__对象原型通过层级关联形成原型链。以下从四大模块系统梳理原型与原型链的完整机制。一、原型对象 prototype概念prototype是构造函数的专属属性本质是一个普通对象用于存储可被所有实例共享的属性和方法。核心作用共享方法节省内存将公共方法定义在原型上所有实例共享同一函数地址避免重复创建。实现原型继承子类可通过绑定父类原型复用父类逻辑。代码示例function Star(name, age) { this.name name; // 实例独有属性 this.age age; } // 公共方法挂载到原型 Star.prototype.sing function() { console.log(${this.name}会唱歌); }; const ldh new Star(刘德华, 18); ldh.sing(); // 输出刘德华会唱歌作用1. constructor每一个函数的prototype对象默认自带一个constructor属性指向函数本身指向该原型的构造函数指向我的爸爸1.判断引用类型对象数组自定义对象const arr [1,2,3]; const obj {}; const date new Date(); console.log(arr.constructor Array); // true 是数组 console.log(obj.constructor Object); // true 是对象 console.log(date.constructor Date); // true 是日期对象2.可修复原型链指向继承/重写原型时必备当 我们手动重写构造函数的原型对象时 constructor 会丢失必须手动修复否则会导致类型判断错误function Person() {} // 错误直接覆盖原型constructor 会指向 Object Person.prototype { constructor: Person, // 手动修复指向 sayHi() { console.log(你好); } }; const p new Person(); console.log(p.constructor Person); // false错误 console.log(p.constructor Object); // true注意点构造函数和原型方法中的this均指向实例对象。避免直接覆盖原型对象否则需手动修复constructor指向二、对象原型 __proto__概念所有实例对象通过__proto__属性关联其构造函数的原型对象prototype形成访问共享成员的通道。原型 共享的方法仓库new 造一个新对象并把他连上原型__proto__ 指向原型的路线__proto__存在 → 所以对象能共享原型的属性 / 方法new每次都会造一个全新的空对象 ** → 所以两个new出来的对象不是同一个核心验证function Star() {} const ldh new Star(); console.log(ldh.__proto__ Star.prototype); // true console.log(ldh.__proto__.constructor Star); // true关键规则实例化后修改原型对已创建的实例无效需遵循先改原型后实例化。特例Object.create(null)创建的对象无__proto__。是俩个杠记忆口诀对象必有__proto__指向构造函数原型。原型必有constructor回指构造函数本身。三、原型继承实现原理子类原型指向父类实例复用父类属性手动修复constructor并扩展子类方法。完整示例// 1. 定义【父构造函数】Person公共属性 function Person() { // 实例属性所有继承 Person 的实例都会拥有这些属性 this.eye 2; this.head 1; } // ------------------------------ // 2. 定义【子构造函数】Woman // ------------------------------ function Woman() { // 子构造函数内部可以写自己的属性 } // 3. 【原型继承核心】 // 让 Woman 的原型 指向 Person 的实例 // 实现属性继承 方法共享节省内存 Woman.prototype new Person(); // 4. 【关键修复】修正 constructor 指向 // 因为直接替换了 prototypeconstructor 会变成 Person必须手动指回自己的构造函数 Woman Woman.prototype.constructor Woman; // 5. 给子构造函数 Woman 添加【独有原型方法】 Woman.prototype.bear function () { console.log(生女宝宝); }; // 6. 实例化 Woman const girl new Woman(); console.log(girl, 女); console.log(girl.__proto__); // 现在能正常看到 eye、head、bear 方法 console.log(Woman.prototype); // 与 girl.__proto__ 一致 // ------------------------------ // 7. 定义【子构造函数】Man同理 // ------------------------------ function Man() { } // 原型继承 Person Man.prototype new Person(); // 修复 constructor 指向 Man.prototype.constructor Man; // 实例化 Man const man1 new Man(); console.log(man1, 男);注意点避免直接在子类原型上修改父类引用类型属性需深拷贝或重新赋值。四、原型链定义通过__proto__逐级向上查找形成的链式结构终点为Object.prototype.__proto__即null。查找规则优先查找实例自身属性。若无沿__proto__向上查找至顶层原型。如果还么有就查找原型对象的原型Object 的原型对象依次类推一直找到Object 为止null__proto__对象原型的意义就在于对象成员查找机制提供一个方向或者说一条路线可以使用instanceof运算符用于检测构造函数的prototype 属性是否出现在某个实例对象的原型链上记忆口诀1.只要是对象就有 __proto__,指向该对象的原型对象2.只要是原型对象就有constructor指向构造函数这个隐式属性指向它的原型instanceof 原理判断前者是不是等与后者console.log(Object.prototype) console.log(Object.prototype.__proto__) //null console.log(Man1 instanceof Object) //true console.log(Array instanceof Object) //true 万物皆对象总结原型对象prototype共享方法constructor标记来源。对象原型__proto__关联实例与构造函数原型。原型继承子类原型绑定父类实例修复constructor。原型链基于__proto__的层级查找机制。通过理解这四大模块可系统掌握 JavaScript 的原型设计思想。