关于原型链和面向对象
来源:3-14 通信类
陈枫William
2017-09-14
虽然以前看过面向对象和原型链,也用过,但是看了视频后感觉知识又有了一个新的升华。
关于继承这里,其实还有一个可以优化的地方:使用最后一种完美方案,还存在一个问题就是使用组合方式的确解决了属性会被实例共用的问题,但是每个实例创建的时候相当于把父类的属性都复制了一遍,这样内存开销是不是会比较大?有没有什么方式可以最小限度地避免在子类的实例中复制过多的父类属性?我想到的是把部分父类构造函数的属性,转移到父类的原型对象上,这样所有实例都共用一个属性。不知道这个思路是否可行,有没有明显缺点?
2回答
-
陈枫William
提问者
2017-09-15
老师您好!由于昨天晚上我是用手机看的视频,所以没有用电脑进行尝试,我今天尝试了一下,这个思路是行得通的。
在父类 Super 中,有一个实例属性 friend ,在子类中指定了 this 上下文后,会为子类的实例创建一个 名为 friend 的数组 ['William', 'Janny'];
在父类的原型上,有属性 name 和方法 say,这两个在子类中执行父类函数时,不会重新创建,在子类的实例上使用 this.name 或者 this.say 时,会从子类的原型上去获得, 在子类实例上,调用 this.name = 'Sub2',this.say = function(){},后,不会影响到原型上的属性和方法,所以sub3可以正常使用这两个属性和方法。
这样做的话,我们就节省了 name 属性, say 方法的内存空间。
如果不用这种方法,每个实例都会创建一个独立的 name 和 say,占用独立的内存空间,如果有100个实例,就是200个内存空间。
如果用了这个方法,只有在子类实例需要重载的地方,会重新创建对象,否则全部引用子类原型对象上的方法和属性。
请看如下代码:
function Super(){ this.friend = ['William', 'Janny']; } //值类型、以及方法,可以放在父类的原型中,这样在创建子类实例时,不会直接复制这些属性和方法,节省内存空间 Super.prototype.name = 'Super'; Super.prototype.say = function(){console.log(this.name, this.friend)} //调用父类构造函数,继承父类属性 function Sub(){ Super.call(this); this.age = '18'; } //以父类的实例为原型,创建子类的原型对象 Sub.prototype = Object.create(new Super()); Sub.prototype.constructor = Sub; const sub1 = new Sub(); sub1.friend.push('Rosy'); sub1.say(); // Super ["William", "Janny", "Rosy"] const sub2 = new Sub(); sub2.name = 'Sub2'; sub2.say = function(){console.log('hello, I\'am ' + this.name + ', my friends are ' + this.friend)}; sub2.say(); // hello, I'am Sub2, my friends are William,Janny const sub3 = new Sub(); sub3.say(); //Super ["William", "Janny"],sub3的 name 属性,来自原型对象,但是不受 sub2 的 name 属性影响 console.log(sub2.name === sub2.__proto__.name); // false console.log(sub3.name === sub3.__proto__.name); // true console.log(sub3.say === sub1.say); //true console.log(sub3.say === sub1.__proto__.say); //true012017-09-15 -
快乐动起来呀
2017-09-15
其实不用考虑内存的问题,如果把属性转到原型,如果是引用类型就出问题了,看看前几个例子就明白了
012017-09-15
相似问题
回答 2
回答 1