js的2种继承方式详解


Posted in Javascript onMarch 04, 2014

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();
Javascript 相关文章推荐
增强用户体验友好性之jquery easyui window 窗口关闭时的提示
Jun 22 Javascript
使用javascript:将其它类型值转换成布尔类型值的解决方法详解
May 07 Javascript
javascript实现原生ajax的几种方法介绍
Sep 21 Javascript
JavaScript判断访问的来源是手机还是电脑,用的哪种浏览器
Dec 12 Javascript
js中switch case循环实例代码
Dec 30 Javascript
浅谈javascript对象模型和function对象
Dec 26 Javascript
JavaScript中实现继承的三种方式和实例
Jan 29 Javascript
简单介绍jsonp 使用小结
Jan 27 Javascript
jQuery 获取select选中值及清除选中状态
Dec 13 Javascript
React Native 集成jpush-react-native的示例代码
Aug 16 Javascript
create-react-app 修改为多入口编译的方法
Aug 01 Javascript
Node.js开发之套接字(socket)编程入门示例
Nov 05 Javascript
Seajs的学习笔记
Mar 04 #Javascript
文本域中换行符的替换示例
Mar 04 #Javascript
为jquery的ajaxfileupload增加附加参数的方法
Mar 04 #Javascript
Document.location.href和.replace的区别示例介绍
Mar 04 #Javascript
LABjs、RequireJS、SeaJS的区别
Mar 04 #Javascript
js的Boolean对象初始值示例
Mar 04 #Javascript
js动态拼接正则表达式的两种方法
Mar 04 #Javascript
You might like
150kHz到30Mhz完全冲浪手册
2020/03/20 无线电
PHP随机数生成代码与使用实例分析
2011/04/08 PHP
PHP 命令行工具 shell_exec, exec, passthru, system详细使用介绍
2011/09/11 PHP
php Hex RGB颜色值互换的使用
2013/05/10 PHP
php array_merge函数使用需要注意的一个问题
2015/03/30 PHP
php微信扫码支付 php公众号支付
2019/03/24 PHP
js 操作符实例代码
2009/10/24 Javascript
改变javascript函数内部this指针指向的三种方法
2010/04/23 Javascript
悄悄用脚本检查你访问过哪些网站的代码
2010/12/04 Javascript
jQuery UI的Dialog无法提交问题的解决方法
2011/01/11 Javascript
JS中类或对象的定义说明
2014/03/10 Javascript
jQuery中:submit选择器用法实例
2015/01/03 Javascript
jQuery插件zTree实现删除树节点的方法示例
2017/03/08 Javascript
Vue.js实战之Vuex的入门教程
2017/04/01 Javascript
javascript闭包功能与用法实例分析
2017/04/06 Javascript
js按条件生成随机json:randomjson实现方法
2017/04/07 Javascript
跟老齐学Python之玩转字符串(1)
2014/09/14 Python
python密码错误三次锁定(实例讲解)
2017/11/14 Python
python入门前的第一课 python怎样入门
2018/03/06 Python
浅谈python中np.array的shape( ,)与( ,1)的区别
2018/06/04 Python
pymongo中聚合查询的使用方法
2019/03/22 Python
python基于itchat模块实现微信防撤回
2019/04/29 Python
浅谈Python编程中3个常用的数据结构和算法
2019/04/30 Python
Python如何实现爬取B站视频
2020/05/20 Python
Python如何输出整数
2020/06/07 Python
linux系统下pip升级报错的解决方法
2021/01/31 Python
HTML5逐步分析实现拖放功能的方法
2020/09/30 HTML / CSS
Vilebrequin欧洲官网:法国豪华泳装品牌(男士沙滩裤)
2018/04/14 全球购物
Grow Gorgeous美国官网:只要八天,体验唤醒毛囊后新生的茂密秀发
2018/06/04 全球购物
SKECHERS斯凯奇中国官网:来自美国的运动休闲品牌
2018/11/14 全球购物
惠普香港官方商店:HP香港
2019/04/30 全球购物
AP澳洲中文网:澳洲正品直邮,包税收件无忧
2019/07/12 全球购物
教师节活动主持词
2014/04/02 职场文书
企业党的群众路线教育实践活动学习心得体会
2014/10/31 职场文书
JavaScript 反射学习技巧
2021/10/16 Javascript
vscode远程免密登入Linux服务器的配置方法
2022/06/28 Servers