js的2种继承方式详解

 更新时间:2014年03月04日 14:23:35   作者:  
这篇文章主要介绍了javascript的2种继承方式,分析对象冒充和原型链方式的不同,需要的朋友可以参考下

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

缺点:先来看这么一张内存分配图:

在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()没有参数,而是直接写成了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(){
          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();

相关文章

  • 判断颜色是否合法的正则表达式(详解)

    判断颜色是否合法的正则表达式(详解)

    下面小编就为大家带来一篇判断颜色是否合法的正则表达式(详解)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-05-05
  • 页面中iframe相互传值传参

    页面中iframe相互传值传参

    兼容IE和火狐JS父窗口调用iframe里面的对象、函数的方法
    2009-12-12
  • 微信小程序“摇一摇”的实例代码

    微信小程序“摇一摇”的实例代码

    微信小程序并没有提供摇一摇API接口,但是提供了一个重力感应的API,接下来我们可以用这个方法来模拟微信摇一摇功能,具体实现代码,大家参考下本文
    2017-07-07
  • 用JS写的简单的计算器实现代码

    用JS写的简单的计算器实现代码

    参加某公司的面试后,有一机试题目:用web技术开发一个B/S结构的公式解析器。于是想了想思路,神来一笔想先写个计算器程序做基础,于是便写了这个程序。
    2009-09-09
  • JS上传组件FileUpload自定义模板的使用方法

    JS上传组件FileUpload自定义模板的使用方法

    这篇文章主要为大家详细介绍了JS上传组件FileUpload自定义模板的使用方法,感兴趣的小伙伴们可以参考一下
    2016-05-05
  • js contains方法实现代码

    js contains方法实现代码

    IE有许多好用的方法,后来都被其他浏览器抄袭了,比如这个contains方法。如果A元素包含B元素,则返回true,否则false。唯一不支持这个方法的是IE的死对头firefox。
    2011-01-01
  • JavaScript实现基于十进制的四舍五入实例

    JavaScript实现基于十进制的四舍五入实例

    这篇文章主要介绍了JavaScript实现基于十进制的四舍五入的方法,实例分析了javascript针对数值判断与相关运算技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-07-07
  • JS面向对象之多选框实现

    JS面向对象之多选框实现

    这篇文章主要为大家详细介绍了JS面向对象之多选框实现,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-01-01
  • JavaScript前端实现压缩图片功能

    JavaScript前端实现压缩图片功能

    这篇文章主要介绍了JavaScript前端实现压缩图片功能,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-03-03
  • javascript实现二分查找法实现代码

    javascript实现二分查找法实现代码

    javascript实现二分查找法实现代码...
    2007-11-11

最新评论