es5创建对象与继承

创建对象7种方法

 

继承的六种实现方式

1.原型链继承:可以让子类共享父类的方法,其关键实现就是让一个原型对象指向另一个类型的实例

 1         function Parent(){
 2             this.colors = ['blue','green'];
 3         }
 4         Parent.prototype.addColor = function(c){
 5             this.colors.push(c);
 6         }
 7         function Child(){
 8         }
 9         Child.prototype = new Parent();
10 
11         const c = new Child();
12         c.addColor('gray');
13 
14         const other = new Child();
15         console.log(other.colors); //['blue', 'green', 'gray']

问题:父类中如果有引用类型的成员,所有子类都共享这些成员。(上面代码第15行)

 

2. 借用构造函数:在子类构造函数中调用父类的构造函数,并把父类函数的上下文指定为子类本身,以此解决引用类型成员共享问题。

 1         function Parent(){
 2             this.colors = ['blue','green'];
 3             this.addColor = function(c){
 4                 this.colors.push(c);
 5             }
 6         }
 7         function Child(){
 8             Parent.call(this);
 9         }
10         const c = new Child();
11         c.addColor('gray');
12 
13         const other = new Child();
14         console.log(other.colors); //['blue', 'green']

问题:同一个逻辑的方法(例如上面第3行的addColor),会在内存中被创建多次,浪费内存空间。

 

3.组合继承(原型链继承+构造函数继承),可解决两种继承的缺点,是es5时代最常用的继承实现方法,思路就是使用原型链实现对原型属性和方法的继承,而通过借用构造函数来实现对实例属性的继承

 1         function Parent(){
 2             this.colors = ['blue','green'];
 3         }
 4         Parent.prototype.addColor = function(c){
 5             this.colors.push(c);
 6         }
 7         function Child(){
 8             Parent.call(this);
 9         }
10         // 继承方法
11         Child.prototype = new Parent()
12         //上面整个原型对象都被覆盖了,而new Parent的实例是没有构造函数成员的
13         Child.prototype.constructor = Parent
14         const c = new Child();
15         c.addColor('gray');
16 
17         const other = new Child();
18         console.log(other.colors); //['blue', 'green']

 缺点: 需要调用两次构造函数

 

4. 原型式继承:借助原型可以基于已有的对象字面量创建新对象,同时还不必因此创建自定义类型。

 1         function obj(o){
 2             function F(){};
 3             F.prototype = o;
 4             return new F();
 5         }
 6         const person = {
 7             name: 'Jiang',
 8             friends: ['Shelby', 'Bob']
 9         }
10         const zhangsan = obj(person); 

在es6中,直接使用Object.create()方法代替上面的obj函数。

缺点: 子类型会共享父类型的引用成员 

 

5. 寄生式继承: 在原型式继承的基础上,给新创建的对象增加了成员(属性或方法)

 1         function obj(o){
 2             const newO = Object.create(o);
 3             newO.say = function(){
 4                 console.log(`my name is ${this.name}`);
 5             }
 6             return newO;
 7         }
 8         const person = {
 9             name: 'Jiang',
10             friends: ['Shelby', 'Bob']
11         }
12         const zhangsan = obj(person); 
13         zhangsan.say(); // my name is Jiang

缺点: 子类型会共享父类型的引用成员

 

6. 寄生组合式继承:不必为了指定子类型的原型而调用父类的构造函数,需要的无非就是父类原型的一个副本,在实现上使用寄生式继承来继承父类的原型,再将结果指定给子类型的原型

 1 function Parent(name) {
 2   this.name = name
 3   this.colors = [‘red’, ‘blue’, ‘green’]
 4 }
 5 Parent.prototype.sayName = function () {
 6   console.log(this.name)
 7 }
 8 function Child(name, job) {
 9   // 继承属性
10   Parent.call(this, name)
12   this.job = job
13 }
14 // 继承
15 Child.prototype = Object.create(Parent.prototype)
16 // 修复constructor
17 Child.prototype.constructor = Child
18 var instance = new Child(‘Jiang’, ‘student’)
19 instance.sayName()

ES6新增了一个Object.setPrototypeOf,可以直接创建关联,而且不用手动添加constructor属性,使用该方法时,第15步-17步可简写为Object.setPrototypeOf(Child.prototype, Parent.prototype)

 

posted @ 2018-05-31 09:27  我是格鲁特  阅读(154)  评论(0编辑  收藏  举报