继承(来自视频)
面向对象三大特性:封装 继承 多态
一、使用函数将代码封装,使得复用性更高
使用函数封装带来的问题:
1.全局变量污染
2.代码结构不够清晰,维护不方便
使用对象进行封装后的优势
1.暴露在全局的只有一个对象名 不会造成全局变量污染
2.使用对象将代码进行功能模块的划分,有利于日后的维护
二、在JavaScript中,继承就是当前对象可以使用其他对象的方法和属性。
继承类型:
1.混入式继承
for in
使用for in遍历对象1的属性,将所有的属性添加到另外一个对象2上
这时候就可以称 对象2 继承自 对象1
for(var k in obj){ o[k] = obj[k]; }
2.原型继承
利用原型中的成员可以被和其相关的对象共享这一特性,可以实现继承
这种实现继承的方式,就叫做原型继承
* 利用对象的动态特性,为原型对象添加成员
* 直接替换原型对象
1.替换前的对象,在替换之后,所有的成员都丢失
2.替换原型对象的时候,需要手动去指定原型对象的construtor属性
* 利用混入给原型对象添加成员
1.给原型对象中添加成员(通过对象的动态特性) 不是严格意义上的继承
function Person(name, age){ this.name = name; this.age = age; } Person.prototype.sayHello = function () { console.log("我想死你了"); } var p = new Person("里斯",50); p.sayHello(); // 这里的p对象就是继承原型
2.直接替换原型对象
function Person(name, age){ this.name = name; this.age = age; } Person.prototype.sayHi = function () { console.log("Hey man"); } var parent = { sayHello : function () { console.log("我想你死了"); } } Person.prototype = parent; var p = new Person("冯巩",50); p.sayHello(); //p.sayHi(); 替换之后,sayHi方法不复存在 //p对象继承了原型对象(parent对象) //注意:使用替换原型的方式实现继承的时候,原有原型中的成员就会丢失
3.利用混入的方式给原型对象添加成员
function Person(name, age){ this.name = name; this.age = age; } Person.prototype.sayHi = function () { console.log("Hey man"); } var parent = { sayHello : function () { console.log("我想你死了"); } } for(var k in parent){ Person.prototype[k] = parent[k]; } var p = new Person("冯巩",50); p.sayHello(); //也是实现了继承 p继承自原型对象
3.经典继承(不推荐)
var 对象1 = Object.create(对象2);
这个时候,创建出来的对象1继承自对象2
Object.create方法存在兼容性问题
如何解决?
1.检测浏览器是否支持Object.create方法,如果不支持,直接手动给Object添加create方法
2.自定义函数,在函数内部判断浏览器是否支持Object.create方法,如果不支持,则手动创建对象返回,否则直接调用
如何解决?
1.检测浏览器是否支持Object.create方法,如果不支持,直接手动给Object添加create方法
2.自定义函数,在函数内部判断浏览器是否支持Object.create方法,如果不支持,则手动创建对象返回,否则直接调用
function create(obj){ if(Object.create){ return Object.create(obj); }else{ function F(){ } F.prototype = obj; return new F(); } }
《JavaScript语言精粹》作者提出了一个方式来实现继承
function jicheng(obj){ var o = {}; o.__proto__ = obj; return o; } var o = jicheng({name:"张三"}); console.log(o);
三、多态
多态是在强类型语言中比较常用,JavaScript中没有相应的体现
继承的应用:
var arr = [1, 2, 3]; //开发人员A想要的sayHello Array.prototype.sayHello =function () { console.log("来呀,互相伤害啊"); } //开发人员B想要的sayHello Array.prototype.sayHello =function () { console.log("我是一个数组,很高兴认识你,呵呵") } //如果直接修改内置对象的原型,会影响整个开发团队 arr.sayHello();/*我是一个数组,很高兴认识你,呵呵*/ //扩展内置对象(就是给内置对象新增成员 Array.prototype) // var str = "+++abc+++"; // console.log(str.trim("+")); //作业:扩展String内置对象,强化trim功能 //如何安全的扩展一个内置对象 function MyArray() { //我自己的属性 this.name = "我是一个数组"; this.sayHello = function () { console.log("我的sayHello方法"); } } var arr = new Array(); //继承之后,我的数组中就有了原生数组对象的所有的属性和方法 MyArray.prototype = arr; MyArray.prototype.safdaf =function () { /*添加属性???*/ } //myArr这个对象就继承自arr var myArr = new MyArray(); myArr.push(100); myArr.push(2,3,4,5) console.log(myArr); //长度为5 var arr = new Array(); function BdeArray(){ this.sayhello=function () { } } BdeArray.prototype = []; var arr = new BdeArray(); var arr = new MyArray();