JS原型与原型链|对象继承与实例底层原理
JS原型与原型链对象继承与实例底层原理原型是JavaScript面向对象的底层实现机制。JS没有传统语言的静态类依靠原型完成属性、方法共享与继承。实例方法复用、class语法、instanceof类型判断全部构建在原型体系之上。读懂原型与原型链才能看懂对象实例底层逻辑分辨各种继承方案优缺点排查对象属性访问相关bug是JS从语法基础迈向底层进阶的重要分水岭。一、原型核心原理概述每一个函数都自带prototype显式原型每一个对象实例都自带__proto__隐式原型。实例的 __proto__ 指向构造函数的 prototype。核心关系实例.__proto__ 构造函数.prototype原型的核心价值多个实例共用原型上的方法不需要每个实例复制一份函数节省内存开销。// 构造函数 function Person(name) { this.name name; } // 在原型上挂载共享方法 Person.prototype.sayHi function() { console.log(你好我是${this.name}) } const p1 new Person(小明) const p2 new Person(小红) p1.sayHi() p2.sayHi() // p1 和 p2 使用同一个 sayHi 函数内存只存一份 console.log(p1.sayHi p2.sayHi) // true二、new 关键字底层执行流程使用 new 创建对象实例浏览器内部自动执行4步逻辑1. 创建一个空普通JS对象 {}2. 将空对象的 __proto__ 指向构造函数的 prototype3. 绑定this执行构造函数内部代码为新对象添加实例属性4. 如果构造函数没有手动返回对象类型则自动返回新建的实例对象function Car(brand) { this.brand brand } const car1 new Car(比亚迪) console.log(car1.__proto__ Car.prototype) // true三、原型链查找机制读取对象属性、方法时会触发原型链向上查找赋值属性不会触发原型链。优先在对象自身查找找到直接返回自身找不到沿着 __proto__ 向上访问原型对象持续向上查找直到 Object.prototypeObject.prototype.__proto__ 等于 null到达链尾整条链找不到返回 undefinedconst obj {} // obj - Object.prototype - null console.log(obj.toString) // toString 来自 Object原型注意给对象做属性赋值只会给当前对象新增属性不会修改原型对象上面的属性。四、继承实现方案方案一原型链继承将子类构造函数prototype指向父类实例实现继承。function Animal(type) { this.type type } Animal.prototype.eat function() { console.log(动物进食) } function Dog(){} Dog.prototype new Animal(犬科) Dog.prototype.constructor Dog // 修正构造器指向 const dog new Dog() dog.eat()缺点父类引用类型属性被全部实例共享无法向父构造函数传参。方案二组合继承传统工程经典方案借用构造函数 原型继承结合解决原型链继承缺陷。function Animal(type) { this.type type } Animal.prototype.eat function() { console.log(动物进食) } function Dog(type) { Animal.call(this, type) // 借用父构造函数生成实例独有属性 } Dog.prototype new Animal() Dog.prototype.constructor Dog const dog new Dog(犬科) console.log(dog.type) dog.eat()方案三ES6 class extends 继承class只是原型的语法糖底层依旧基于原型机制简化手写继承代码。class Animal { constructor(type) { this.type type } eat() { console.log(动物进食) } } class Dog extends Animal { constructor(type) { super(type) // 调用父类构造函数必须写在this访问之前 } } const dog new Dog(犬科) dog.eat()五、constructor 构造器属性prototype原型对象自带constructor默认指向对应的构造函数用来标记实例由哪个函数创建。function User(){} const u new User() console.log(u.constructor User) // true开发踩坑如果直接完整覆盖prototype对象constructor属性会丢失需要手动重置。六、三种类型检测方式与区别instanceof沿着原型链做判断检查构造函数prototype是否出现在实例原型链上仅适合引用类型。Object.prototype.toString.call()精准检测JS内置类型可以区分数组、普通对象等。typeof适合原始类型判断null返回object无法区分数组与普通对象。console.log(dog instanceof Dog) // true console.log(Object.prototype.toString.call([])) // [object Array] console.log(typeof null) // object七、原型工程实践规范企业规范实例独有的属性写在构造函数this上多个实例共享的方法挂载prototype节约内存。原型上尽量不要存放数组、对象这类引用类型会出现实例之间互相污染。class是语法糖底层依旧原型不要当成传统静态类。业务尽量避免直接操作 __proto__优先使用Object.getPrototypeOf / Object.setPrototypeOf。八、开发高频避坑总结prototype属于函数__proto__属于实例对象二者不要混淆。只有读取属性才走原型链赋值不会向上修改原型。instanceof结果可以被人为修改原型伪造不能作为100%可靠类型判断。原型链层级不要过深层级过多会增加属性查找性能开销。class继承子类constructor内部super必须前置调用否则this无法初始化直接报错。九、写在最后原型与原型链是JavaScript面向对象底层根基。JS依靠原型实现属性共享与继承class、实例、instanceof全部建立这套体系之上。弄懂原型链才能够读懂内置对象方法、各类继承写法、框架组件继承逻辑突破JavaScript底层进阶门槛。
上一篇/下一篇内容由系统自动关联
返回资讯列表 →