// 定义了一个构造函数Father function Father(uname, age) { this.uname = uname; this.age = age; } // 然后在Father的原型上面挂载了一个叫say的方法 Father.prototype.say = function () { console.log("我在Father的原型上面") } // 定义了一个叫Son的构造函数 function Son(uname, age) { // 这里可以理解为 "直接调用" 了上面的构造函数 // 也就相当于Son构造函数有了 this.uname = uname 和 this.age = age // 但是this指向的是Father构造函数, 所以用call改变this指向为当前的this Father.call(this, uname, age) } // 在这里new一下Son这个构造函数 // const zs = new Son("张三", 18); // 这里打印的属性肯定是没有问题的 // console.log(zs.uname, zs.age); // 张三 18 // 这里直接调用方法, 结果提示没有这个函数(方法) // zs.say(); // 因为zs这个实例对象说白了就是一个对象,它的原型肯定只有constructor指向(谁造出来的) // Son.prototype = Father.prototype; // 这里把Father的原型赋值给Son // const zs = new Son("张三", 18); // 把上面的new Son注释掉,从新new一下,在原型赋值之后 // zs.say(); // 打印结果 我在Father的原型上面 // 这样的话,就相当于 Son 构造函数不仅有了Father的属性, 通过有了Father原型上的方法 // zs上面没有say , 就会到原型 Son 上面找 // 但是这时候在 Son的原型上面再挂载一个方法 // Son.prototype.sing = function () { // console.log("我会唱陈奕迅的一丝不挂哈哈") // } // 然后new 一下Father 的构造函数 // const xm = new Father("小明", 20) // xm.sing() // 打印结果为 我会唱陈奕迅的一丝不挂哈哈 // 说明两个的原型是相互影响的,虽然也能达到 属性和方法的继承,但是有瑕疵 // 解决方案 // 直接把Son的原型指向Father的实例 (没有携带任何参数) // new Father() 相当于一个实例对象, 对象上肯定有Father 的属性和方法 // 但是因为没有传递任何参数, 所以Son的原型上的属性 this.uname = undefined, this.age = undefined , 但是方法是没有问题的... (说的是Son的原型上) Son.prototype = new Father(); // 这时候再 实例化一个对象 const zs = new Son("张三", 18); console.log(zs.uname) // 张三 zs.say(); // 我在Father的原型上面 // 说明 Son同时拥有的Father 的属性和方法 // 小结 // 1. Son 中 调用 Father 函数, 并且用call使this指向为Son的实例对象,相当于Son有了Father的属性// (属性继承) // 2. 把Father的实例对象(new Father()), 赋值给Son的原型,Son的原型就同时拥有了Father的属性和方法 // 但是因为new的时候没有传递参数,所以Son的原型中的属性的值都是undefined(注意是Son的原型,不是它本身) // 但是方法是没有毛病的,因此实现了方法的继承 // 3. 构建Son的实例对象的时候,因为Son的本体上面就有this.uname和this.age,所以,不会再去Son的原型上面找,原型上面的属性的值 undefined 就不会影响到实例对象了 // 由此我们就实现了 属性和方法的同时继承,又叫 组合继承
原文:https://www.cnblogs.com/liuyuexue520/p/12780684.html