首頁 >web前端 >js教程 >js的2種繼承方式詳解_javascript技巧

js的2種繼承方式詳解_javascript技巧

WBOY
WBOY原創
2016-05-16 16:57:13853瀏覽

js中继承可以分为两种:对象冒充和原型链方式

一、对象冒充包括三种:临时属性方式、call()及apply()方式
1.临时属性方式

复制代码 代码如下:

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();

缺点:先来看这么一张内存分配图:
js的2種繼承方式詳解_javascript技巧

在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的2種繼承方式詳解_javascript技巧

原型鏈可以理解成:js中每個物件都有一個隱藏的__proto__屬性,一個實例化物件的__proto__屬性指向其類別的prototype方法,而這個prototype方法又可以被賦值成另一個實例化對象,這個物件的__proto__又需要指向其類,由此形成一條鏈,也就是前面程式碼中的

複製程式碼 程式碼如下:

F2E.prototype = new Person()

這句話是關鍵。 js物件在讀取某個屬性時,會先尋找自身屬性,沒有則再去依序查找原型鏈上物件的屬性。也就是說原型鏈的方法是可以共用的,這樣就解決了物件冒充浪費記憶體的缺點。

下面再來來說缺點:
缺點顯而易見,原型鏈方式繼承,就是實例化子類時不能將參數傳給父類,也就是為什麼這個例子中function Person()沒有參數,而是直接寫成了this.name=”Simon」的原因。下面的程式碼將無法達到預期的效果:

複製程式碼 程式碼如下:
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(){
this     this.showId = function(){
this     this.showId = function(){
this .id);
     }
}
F2E.prototype = new Person();

var simon = new F2E("Simon",9527);
var simon = new F2E("Simon",9527);
simon.say( );
simon.showId();

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

     alert('My name is ' this.name);
}

function F2E(name,id){
  this.showId = function(){
          alert('Good morning,Sir,My work number is ' this.id);
     }
}
);  //此處無法進行傳值,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;
}
}
.prototype.say = function(){
     alert('My name is ' this.name);
}

function F2E(name,id){
  ,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();
陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn