您的位置:首页 > Web前端 > JavaScript

js学习笔记之继承

2017-08-18 09:50 260 查看
学习来源:http://www.cnblogs.com/xiaohuochai/p/5721552.html

先理解 prototype(显示原型)  _proto_(隐式原型) constructor之间的关系

1. __proto__是每个实例对象都有的一个属性,而prototype是函数(包括构造函数)才会有的属性。

2. __proto__指向的是当前对象的原型对象,而prototype指向的是以当前函数作为构造函数构造出来的对象的原型对象,虽然都指向原型对象。



当你new fn() 的时候,产生的实例的__proto__指向fn.prototype,两者是同一个东西。

function Foo() {} 

var myfoo = new Foo();

myfoo.__proto__ === Foo.prototype

显式原型的作用:用来实现基于原型的继承与属性的共享。

隐式原型的作用:构成原型链,同样用于实现基于原型的继承。举个例子,当我们访问obj这个对象中的x属性时,如果在obj中找不到,那么就会沿着__proto__依次查找。

开始讲继承:

function Person( name ) {  this.name = name; }

Person.prototype.showName = function () { };

1.原型链实现继承

function Worker( age) { this.age = age; }

Worker.prototype = new Person( ' jack ' );           //构造函数的原型和父级实例对象相同

var w1 = new Worker( 18 );                                //实例对象的原型和构造函数的原型相同  

w1.showName ( );        // jack  

这个方法实现的原理就是原型属性会被所有实例共享。从上面两句话来看,实例对象的原型和构造函数的原型相同 ,即w1 .__proto__ ===  Worker.prototype,

而构造函数的原型和父级实例对象相同,即实例对象的原型就是父级实例对象了,那w1 new出来的实例自然拥有Person的所有属性和方法。

Worker通过原型继承了Person,在new Worker的时候,w1 如果在自身找不到相应的属性和方法,w1中有个隐藏的属性__proto__指向构造函数的prototype对

象,在这里是Person对象实例,就从Person对象实例找,再找不到,Person对象里面也有一个隐藏的属性__proto__,
指向Person构造函数的prototype对象,

这就构成原型链,沿着_proto_往上找,以此类推,直到Object.prototype作为实例对象的话,其原型对象是null。 找不到就报错了,所以继承会导致原型链延长。

这种方式的缺点是:

1)所有子类共享父类实例,如果某一个子类修改了父类,其他的子类在继承的时候,会造成意想不到的后果。

2)第二个缺点是在构造子类实例的时候,不能给父类传递参数。

继承应该是继承方法而不是属性,为子类设置父类实例属性应该是通过在子类构造函数中调用父类构造函数进行初始化。

2.构造函数实现继承

function Worker( age, name) { this.age = age;  Person.call (this,  name);  }

var w1 = new Worker( 18,  ' lily ' );

w1.name;              // lily 

w1.showName ( );          //undefined

这种方法又叫构造函数伪装,调用Person的构造函数,将它的this指向为Worker。相当于在Worker的构造函数中执行this.name = name; 而此时的this,是指

Worker,这样就拥有了name属性,此时可以在子类型构造函数中向父类构造函数传递参数。

这种方法的缺点是父类的prototype中的函数不能复用。showName, showSex 不在Person的构造函数中,所以访问不到。但是如果把方法也在构造函数中定义,

无法传递子类自身需要的参数,那方法复用一说就无从谈起。

3.原型+构造函数实现继承

function Worker( age, name) { this.age = age;  Person.call (this,  name);  }                  // 通过构造函数的方式 用来继承属性

Worker.prototype = new Person( ' jack ' );                                  // 通过原型的方式 用来继承方法

var w1 = new Worker( 18,  ' lily ' );

Worker.prototype.showJob = function () { };                                
//子类通过原型 添加自己的方法

改进了上述两种方式的缺点,但是这种方式也有缺点,那就是占用的空间更大了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: