一 原型链继承 原型链继承的原理:直接让子类的原型对象指向父类实例,当子类实例找不到对应的属性和方法时,就会往它的原型对象,也就是父类实例上找,从而实现对父类的属性和方法的继承。 原型链继承的缺点 1、所有的child实例原型都指向同一个fat实例,因此对child实例修改某个父类引用类型会影响所有的child实例; 二 构造函数继承 构造函数继承:在子类的构造函数中执行父类的构造函数,并为其绑定子类的this。让父类的构造函数把成员的属性和方法都挂在子类的this上,这样既避免了共用一个原型实例,又能像父类构造函数传参。 构造函数继承的缺点 继承不到父类上的属性和方法 三 组合式继承 组合式继承的缺点 每次创建子类实例都执行了两次构造函数(fat.call()和new fat()),虽然不影响继承,但是在子类创建时 原型中会存在两份相同的属性和方法。 四 寄生式组合继承 为了解决构造函数被执行两次的问题,我们将指向父类实例 变成转向父类原型,减少一次构造函数的执行 但是这种方法也存在一个问题,就是子类和父类的原型都指向同一个对象,如果我们对子类原型操作就会对父类原型产生影响。比如给子类Child.prototype新增一个getName方法,那么父类fat.prototype也增加或是被覆盖一个getName方法。为了解决这个问题 我们给fat.prototype做一个浅拷贝; 到这里我们就完成了es5里的继承,有空更新es6的继承方法 class介绍 来自阮一峰 es6中的继承: end… 散会
ES5中的继承
// 父类 function fat () { this.name = 'zaq' } // 父类上的原型方法 fat.prototype.getName = function() { return this.name } // 子类 function child () {} // 子类的原型对象方法指向父类 子类中找不到的属性方法就会向父类找 child.prototype = new fat() // 不影响继承 顺便绑一下constructor child.prototype.constructor = child // child实例就可以访问父类及其原型上的属性和方法了 const Child = new child() Child.name // 'zaq' Child.getName() // 'zaq'
2、创建子类时无法向父类传参,没有实现super()的功能function fat () { this.name = 'zaq' } fat.prototype.getName = function() { return this.name } function child () {} child.prototype = new fat() child.prototype.constructor = child // const Child1 = new child(); const Child2 = new child(); Child1.name = 'lsq' console.log(Child1.name) // lsq // 本来父类name属性是zaq 然后现在== console.log(Child2.name) // lsq
function fat (name) { this.name = name } fat.prototype.getName = function() { return this.name } function Child () { fat.call(this, 'zaq') } const child1 = new Child() const child2 = new Child() child1.name = 'xyc' console.log(child1.name) // xyc console.log(child2.name) // zaq
child1.getName() // Uncaught TypeError: child1.getName is not a function
既然原型链继承和构造函数继承都有各自的缺点但是又能互补,那何不将两者结合起来使用;function fat (name) { this.name = name } fat.prototype.getName = function() { return this.name } // 构造函数继承 function Child () { fat.call(this, 'zaq') } // 原型链继承 Child.prototype = new fat() Child.prototype.constructor = Child const child1 = new Child() const child2 = new Child() child1.name = 'lsq' console.log(child1.name) // lsq console.log(child2.name) // zaq child1.getName() // lsq
function fat (name) { this.name = name } fat.prototype.getName = function() { return this.name } // 构造函数继承 function Child () { fat.call(this, 'zaq') } // 原型链继承 Child.prototype = fat.prototype // 将指向父类实例转成转向父类原型 Child.prototype.constructor = Child const child1 = new Child() const child2 = new Child() child1.name = 'lsq' console.log(child1.name) // lsq console.log(child2.name) // zaq child1.getName() // lsq
function fat (name) { this.name = name } fat.prototype.getName = function() { return this.name } // 构造函数继承 function Child () { fat.call(this, 'zaq') } // 原型链继承 Child.prototype = Object.create(fat.prototype) // 将指向父类实例转成转向父类原型 Child.prototype.constructor = Child const child1 = new Child(); const child2 = new fat(); child1.getName() // zaq child2.getName() // undefined
ES6中的继承
1、class可以理解为functon,由于class本质还是一个function,因此它也有一个prototype属性。当new一个class时,会把class的protortype属性赋值给这个新对象的_proto_属性上;
2、constructor是默认添加的方法,在new一个对象的时候,会自动调用该方法, constructor里定义自己的属性;
3、继承extends和super, class子类名 extends父类名 实现继承。当然,还得在constructor里写上super (父类的参数),意思就是在子类中获取父类的this指针,相当于fat.call(this),参考// 父类 class fat { constructor(props) { this.name = props || ''; } getName () { return this.name } } // 继承 class Child extends fat { constructor(props, attrs) { // props继承父类的属性,attrs自己私有的属性 super(props); // 相当于获取父类的this指向 this.rename = props.rename || '' this.attrs = attrs } // 子类自己的方法 getFatname () { return this.name } getAttrs () { return this.attrs } } // 通过new实例化一个构造函数 const child1 = new Child({ name: 'zaq', rename: 'zwj' }, 'mine attrs') child1.getName() // zaq child1.getRename() // zwj child1.getAttrs() // mine attrs
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算