js的2种继承方式详解 |
||||
本文标签:js继承,js类继承 js中继承可以分为两种:对象冒充和原型链方式 一、对象冒充包括三种:临时属性方式、call()及apply()方式 复制代码 代码如下: function Person(name){ this.name = name; this.say = function(){ alert(My name is +this.name); } } function F2E(name,id){ this.temp = Person; this.temp(name); delete this.temp; this.id = id; this.showId = function(){ alert(Good morning,Sir,My work number is +this.id); } } var simon = new F2E(Simon,9527); simon.say(); simon.showId(); 2.call()/apply()方式 实质上是改变了this指针的指向 复制代码 代码如下: function Person(name){ this.name = name; this.say = function(){ alert(My name is +this.name); } } function F2E(name,id){ Person.call(this,name); //apply()方式改成Person.apply(this,new Array(name)); this.id = id; this.showId = function(){ alert(Good morning,Sir,My work number is +this.id); } } var simon = new F2E(Simon,9527); simon.say(); simon.showId(); 缺点:先来看这么一张内存分配图:
在OO概念中,new实例化后,对象就在堆内存中形成了自己的空间,值得注意的是,这个代码段 。而成员方法就是存在这个代码段的,并且方法是共用的 。问题就在这里,通过对象冒充方式继承时,所有的成员方法都是指向this的,也就是说new之后,每个实例将都会拥有这个成员方法,并不是共用的,这就造成了大量的内存浪费 。并且通过对象冒充的方式,无法继承通过prototype方式定义的变量和方法,如以下代码将会出错: 复制代码 代码如下: function Person(name){ this.name = name; this.say = function(){ alert(My name is +this.name); } } Person.prototype.age = 20; Person.prototype.sayAge = function(){alert(My age is +this.age)}; function F2E(name,id){ Person.apply(this,new Array(name)); this.id = id; this.showId = function(){ alert(Good morning,Sir,My work number is +this.id); } } var simon = new F2E(Simon,9527); simon.sayAge(); //提示TypeError: simon.sayAge is not a function 二、原型链方式 复制代码 代码如下: function Person(){ this.name = Simon; } Person.prototype.say = function(){ alert(My name is +this.name); } function F2E(id){ this.id = id; this.showId = function(){ alert(Good morning,Sir,My work number is +this.id); } } F2E.prototype = new Person(); var simon = new F2E(9527); simon.say(); simon.showId(); alert(simon.hasOwnProperty(id)); //检查是否为自身属性 接下来按照上面的例子来理解以下js原型链概念:
原型链可以理解成:js中每个对象均有一个隐藏的__proto__属性,一个实例化对象的__proto__属性指向其类的prototype方法,而这个prototype方法又可以被赋值成另一个实例化对象,这个对象的__proto__又需要指向其类,由此形成一条链,也就是前面代码中的 复制代码 代码如下: F2E.prototype = new Person() 这句是关键 。js对象在读取某个属性时,会先查找自身属性,没有则再去依次查找原型链上对象的属性 。也就是说原型链的方法是可以共用的,这样就解决了对象冒充浪费内存的缺点 。 下面再来说缺点: 复制代码 代码如下: function Person(name){ this.name = name; } Person.prototype.say = function(){ alert(My name is +this.name); } function F2E(name,id){ this.id = id; this.showId = function(){ alert(Good morning,Sir,My work number is +this.id); } } F2E.prototype = new Person(); var simon = new F2E("Simon",9527); simon.say(); simon.showId(); function Person(name){ this.name = name; } Person.prototype.say = function(){ alert(My name is +this.name); } function F2E(name,id){ this.id = id; this.showId = function(){ alert(Good morning,Sir,My work number is +this.id); } } F2E.prototype = new Person(); //此处无法进行传值,this.name或者name都不行,直接写F2E.prototype = new Person(wood)是可以的,但是这样的话simon.say()就变成了My name is wood var simon = new F2E("Simon",9527); simon.say(); //弹出 My name is undefined simon.showId();
复制代码 代码如下: function Person(name){ this.name = name; } Person.prototype.say = function(){ alert(My name is +this.name); } function F2E(name,id){ Person.call(this,name); this.id = id; } F2E.prototype = new Person(); //此处注意一个细节,showId不能写在F2E.prototype = new Person();前面 F2E.prototype.showId = function(){ alert(Good morning,Sir,My work number is +this.id); } var simon = new F2E("Simon",9527); simon.say(); simon.showId(); |