安全实现属性“借用”需用call/apply在子构造函数中以子实例this调用父构造函数,确保引用类型属性独立;再结合原型链继承方法,避免共享与污染。

安全地实现属性“借用”,关键不是把属性复制过去,而是让子对象在初始化时,用自己的 this 执行父构造函数,从而获得一份独立的、属于自身的属性副本——尤其是对引用类型(如数组、对象)而言。
为什么不能只靠原型链“继承”属性?
原型链上的属性是共享的。比如父构造函数中定义了 this.friends = ['小明', '小红'],子类通过 Sub.prototype = new Super() 建立原型链后,所有子实例都会共用同一个 friends 数组。一个实例 push 一个新成员,另一个实例立刻可见——这不是借用,是共享,且极易引发意外修改。
用 call/apply 在子构造函数中“借用”初始化逻辑
把父构造函数当成普通函数调用,显式传入子实例的 this,让它在子实例自身上创建属性:
function Student(name, age, grade) { Person.call(this, name, age); this.grade = grade; }- 这样每次创建
new Student(),都会执行一次Person,生成独立的name、age和friends等属性 - 引用类型不再共享,修改
student1.friends不会影响student2.friends
组合使用:原型链 + 构造函数借用
单用构造函数借用无法访问父类原型上的方法;单用原型链又导致属性共享。两者结合才是安全、完整的“借用”:
- 用
Person.call(this, ...)借用属性初始化(解决共享与传参问题) - 用
Student.prototype = Object.create(Person.prototype)借用原型方法(避免污染constructor,且不执行父构造函数) - 补上
Student.prototype.constructor = Student修正构造器指向
注意 this 的绑定必须可靠
借用的前提是 this 指向正确的新建实例:
- 确保子函数是通过
new调用的,否则this可能为undefined或全局对象 - 避免在箭头函数或事件回调中直接调用
Person.call(this, ...),此时this可能已丢失 - 必要时可用
bind预绑定,或改用 class 语法(其super()内部已保障 this 安全)

















