javascript继承—继承的实现原理(1)
打算针对js的继承写一系列文章,详细的分析js里继承原理,实现方式,各种继承方式的优缺点,以及最优继承方案,还有多继承的问题等….
面向对象的编程的核心是封装、继承和多态,js可以看作是一种面向对象的语言,而面向对象的扩展性最核心的部分是多态,多态的必要条件有三个,首先就是继承,其次父类的引用指向子类,最后是方法重写。对于js来说,由于其创建对象的方式多种多样,因此,需要对父类的多种属性和方法实现很好的继承,就必须找到一个比较完善的方法。本篇文章首选介绍三种最基本的继承方式,并分析这几种继承方式的缺陷。
介绍js继承前,大家先需要js里类的各种属性以及js创建对象的几种模式有所了解。
js类的属性可以参考: javascript中类的属性研究 这篇文章。
js创建对象的方式可以参考:javascript创建对象的三种模式 这篇文章。
第一种方式:对象冒充
对象冒充,是指将父类的属性和方法一起传给子类作为特权属性和特权方法。
function Person(name,age){
this.name = name;
this.age = age;
this.sayHi = function(){
alert('hi');
}
}
Person.prototype.walk = function(){
alert('walk.......');
}
function Student(name,age,grade){
this.newMethod = Person;
this.newMethod(name,age);
delete this.newMethod;
this.grade = grade;
}
var s1 = new Student('xiaoming',10,3);
console.log(s1.name,s1.age,s1.grade);//xiaoming 10 3
//s1.walk();//s1.walk is not a function
可见Student类只继承了Person类的特权属性和方法,并没有继承Person类的共有属性和方法。
第二种方式:call或apply
使用call或apply改变对象的作用域来实现继承,让父类的this等于新创建的子类的对象(因为call和apply继承实现机制是一样的,就是传参方式不同,call传多个参数用逗号隔开,apply用数组),本文主要介绍call来实现继承。
function Person(name,age){
this.name = name;
this.age = age;
this.sayHi = function(){
alert('hi');
}
}
Person.prototype.walk = function(){
alert('walk.......');
}
function Student(name,age,grade){
Person.call(this,name,age);
this.grade = grade;
}
var s1 = new Student('xiaoming',10,3);
console.log(s1.name,s1.age,s1.grade);//xiaoming 10 3
//s1.walk();//s1.walk is not a function
同第一种问题一样,没有继承共有属性和方法。call改变了Person中this的作用域,使其指向了Student。对于call方法举例如下:
function Person(){
this.name ='xiaoming';
}
Person.call(this);
alert(window.name);
此例将Person中this的作用域扩大到window上,使得Person中的name属性变为一个全局变量。
第三种方式:prototype
使用prototype属性实现继承,让父类的prototype赋给子类的prototype,也可以将父类的实例赋给子类的prototype,这里先介绍将父类的原型赋给子类的原型这种方式,并探讨这种方式的缺陷。在以后会着重介绍prototyp这种继承方式。
function Person(name,age){
this.name = name;
this.age = age;
this.sayHi = function(){
alert('hi');
}
}
Person.prototype.walk = function(){
alert('walk.......');
}
function Student(name,age,grade){
this.grade = grade;
}
Student.prototype = Person.prototype;
var s1 = new Student('xiaoming',6,3);
s1.walk();//walk.......
console.log(s1.name,s1.age,s1.grade);//xiaoming 6 3
console.log(s1.constructor); // Person(name,age)
Student.prototype.study = function(){
alert('I am study');
}
var p1 = new Person();
p1.study();//I am study
主要缺陷:不能继承父类的特权属性和特权方法,子类的构造函数变成了Person(name,age),直接导致修改子类的原型方法时,父类也跟着修改了,耦合度太高了。
如果将父类的实例指向子类的原型会出现什么情况呢?
function Person(name,age){
this.name = name;
this.age = age;
this.sayHi = function(){
alert('hi');
}
}
Person.prototype.walk = function(){
alert('walk.......');
}
function Student(name,age,grade){
this.grade = grade;
}
Student.prototype = new Person();
var s1 = new Student('xiaoming',6,3);
s1.walk();//walk.......
console.log(s1.name,s1.age,s1.grade);//undefined undefined 3
console.log(s1.constructor); // Person(name,age)
Student.prototype.study = function(){
alert('I am study');
}
var p1 = new Person();
//p1.study();// p1.study is not a function
虽然s1仍然指向父类的构造函数,但修改子类的共有方法并不会对父类有所影响,但是存在一个更为严重的问题是,子类没法继承父类的特权属性和特权方法。
总结:几种继承方式各有各的缺陷,那么如何实现完美的继承呢。也许将其中的某两种继承方式结合起来才行。在以后会接着介绍call和prototype结合实现js的继承功能。
javascript继承—继承的实现原理(1)的更多相关文章
- JavaScript原型继承工作原理
原型继承的定义 当你阅读关于JS原型继承的解释时,你时常会看到以下这段文字: 当查找一个对象的属性时,JavaScript 会向上遍历原型链,直到找到给定名称的属性为止.——出自JavaScript秘 ...
- 前端知识体系:JavaScript基础-原型和原型链-理解 es6 中class构造以及继承的底层实现原理
理解 es6 中class构造以及继承的底层实现原理 原文链接:https://blog.csdn.net/qq_34149805/article/details/86105123 1.ES6 cla ...
- 再谈javascript原型继承
Javascript原型继承是一个被说烂掉了的话题,但是自己对于这个问题一直没有彻底理解,今天花了点时间又看了一遍<Javascript模式>中关于原型实现继承的几种方法,下面来一一说明下 ...
- TDD测试驱动的javascript开发(3) ------ javascript的继承
说起面向对象,人们就会想到继承,常见的继承分为2种:接口继承和实现继承.接口继承只继承方法签名,实现继承则继承实际的方法. 由于函数没有签名,在ECMAScript中无法实现接口继承,只支持实现继承. ...
- 彻底理解Javascript原型继承
彻底理解Javascript原型继承 之前写过一篇Javascript继承主题的文章,这篇文章作为一篇读书笔记,分析的不够深入. 本文试图进一步思考,争取彻底理解Javascript继承原理 实例成员 ...
- [转]Javascript原型继承
真正意义上来说Javascript并不是一门面向对象的语言,没有提供传统的继承方式,但是它提供了一种原型继承的方式,利用自身提供的原型属性来实现继承.Javascript原型继承是一个被说烂掉了的话题 ...
- [ JavaScript ] JavaScript 实现继承.
对于javascript中的继承,因为js中没有后端语言中的类式继承.所以js中的继承,一般都是原型继承(prototype). function P (name){ this.name = name ...
- 【编程题与分析题】Javascript 之继承的多种实现方式和优缺点总结
[!NOTE] 能熟练掌握每种继承方式的手写实现,并知道该继承实现方式的优缺点. 原型链继承 function Parent() { this.name = 'zhangsan'; this.chil ...
- JavaScript 的继承与多态
本文先对es6发布之前javascript各种继承实现方式进行深入的分析比较,然后再介绍es6中对类继承的支持以及优缺点讨论.最后介绍了javascript面向对象编程中很少被涉及的“多态”,并提供了 ...
随机推荐
- 惠普4431s 笔记本配置
hp-4431s驱动精灵硬件检测报告 版本:2015.3.26.1363(8.1.326.1363)================================================== ...
- c# winform 引用sqlite.dll 运行报错解决方法
错误信息 : 未能加载文件或程序集“System.Data.SQLite, Version=1.0.81.0, Culture=neutral, PublicKeyToken=db937bc2d44 ...
- 如何在Dreamweaver中使用zen coding
在我发表上一篇<Zen Coding: 一种快速编写HTML/CSS代码的方法>之后,有网友表示不知道怎么在Dreamweaver上使用zen coding插件.OK,今天我就写一篇详细的 ...
- lua基金会【五岁以下儿童】I/O文件操作
--[[ lua操作相关文件I/O ]]-- --件,假设该文件不存在的话, --lua会帮助我们在你规定的文件夹下创建这个文件,前提是该文件夹要存在 --[[ 同一时候我们应该掌握写入文件的模式: ...
- POJ 2756 Autumn is a Genius 采用string大数减法
标题意味着小神童.加减可以计算. 只是说这个小神童的学科知识,究竟有多神,自己给自己找. 最后,因为数据是非常非常巨大的,我听说关闭50k结束了50000数字总和,可以想见他神教. 这似乎也是考试题目 ...
- STL源代码分析——STL算法merge合并算法
前言 因为在前文的<STL算法剖析>中.源代码剖析许多.不方便学习.也不方便以后复习,这里把这些算法进行归类.对他们单独的源代码剖析进行解说.本文介绍的STL算法中的merge合并算法. ...
- Coco2d-x android win7 Python 游戏开发环境的搭建
1:我用的电脑配置 win7 3 核 内存8G 桌面.一直想学习Coco2d 游戏开发,所以,一个星期后,需要找到,最终建立了一个良好的环境 2:我使用的版本号版本号,至于建筑android开发环境略 ...
- Entity Framework笔记(一)
最近在看MVC方面的资料,看了几个教程都在使用Entity Framework做数据持久化.之前也听说过这个东西,在微软的网站上看过一个演示视频,但都没怎么去仔细研究.MVC的东西太庞大了,先慢慢熟悉 ...
- SAP HANA开发中常见问题- 基于SAP HANA平台的多团队产品研发
大家都知道SAP HANA项目打包成Delivery Unit(缩写为DU).依照"官方"的开发模式,特别是整个团队仅仅使用一个HANA Instance进行项目开发,因为HANA ...
- Rust这个新的语言
Rust这个新的语言 Rust初步(七):格式化 摘要: 在Rust中,如果要进行屏幕输出,或者写入到文件中,需要对数据进行格式化.这一篇总结一下它所支持的几种格式化方式. 这篇文章参考了以下官方文档 ...