摘要:第二个问题是在创建子类型的实例时,不能向超类型的构造函数中传递参数。实际上,应该说是没有办法在不影响所有对象实例的情况下,给炒类型的构造函数传递参数。借用构造函数伪造对象或经典继承即在子类型构造函数的内部调用超类型构造函数。
继承
许多 OO 语言支持两种继承方式:接口继承和实现继承。接口继承只继承方法签名,而实现继承则继承实际的方法。如前所述,由于函数没有签名,在 ECMAScript 中无法实现接口继承。 ECMAScript 只支持实现继承,而且其实现继承主要是依靠原型链来实现。
原型链基本思想是:利用原型让一个引用类型继承另一个引用类型的属性和方法。
构造函数、原型和实例的关系:每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针。
jsfunction SuperType() { this.property = true; } SuperType.prototype.getSuperValue = function() { return this.property; }; function SubType() { this.subproperty = false; } //继承了 SuperType SubType.prototype = new SuperType(); SuperType.prototype.getSubValue = function() { return this.subproperty; } var instance = new SubType(); alert(instance.getSuperValue());//true
别忘记默认的原型
确定原型和实例的关系
jsalert(instance instanceof Object); //true alert(instance instanceof SuperType); //true alert(instance instanceof SubType); //true
jsalert(Object.prototype.isPrototypeOf(instance));//ture alert(SuperType.prototype.isPrototypeOf(instance));//ture alert(SubType.prototype.isPrototypeOf(instance));//ture
谨慎地定义方法
给原型添加方法的代码一定要放在替换原型的语句之后。
jsfunction SuperType() { this.property = true; } SuperType.protype.getSuperValue = function() { return this.property; } function SubType() { this.subproperty = false; } //继承了 SuperType SubType.prototype = new SuperType(); //添加新方法 SubType.prototype.getSubValue = function() { return this.subproperty; }; //重写超类型中的方法 SubType.prototype.getSuperValue = function() { return false; }; var instance = new SubType(); alert(instance.getSuperValue());//false
jsfunction SuperType() { this.property = true; } SuperType.prototype.getSuperValue = function() { return this.property; } function SubType() { this.subproperty = false; } //继承了 SuperType SubType.prototype = new SuperType(); //使用字变量添加新方法,会导致上一行代码无效 SubType.prototype = { getSubValue : function() { return this.subproperty; }, someOtherMethod = function() { return false; } }; var instance = new SubType(); alert(instance.getSuperValue()); //error 原型链被切断(现在的原型包含的是 Object 的实例)。
4.原型链的问题
最主要的问题来自包含引用类型值的原型。前面已经介绍过包含引用类型值的原型属性会被所有实例共享,这也是为什么要在构造函数中而不在原型对象中定义属性的原因。
第二个问题是:在创建子类型的实例时,不能向超类型的构造函数中传递参数。实际上,应该说是没有办法在不影响所有对象实例的情况下,给炒类型的构造函数传递参数。
即在子类型构造函数的内部调用超类型构造函数。函数只不过是在特定环境中执行代码的对象,所以可通过 apply() 或 call() 方法也可以在(将来)新创建的对象上执行构造函数。
jsfunction SuperType() { this.colors = ["red","blue","green"]; } function SubType() { //继承了 SuperType SuperType.call(this); } var instance1 = new SubType(); instance1.colors.push("black"); alert(instance1.colors); //"red,blue,green,black" var instance2 = new SubType(); alert(instance2.colors); //"red,blue,green"
传递参数
js function SuperType(name) { this.name = name; } function SubType() { //继承了 SuperType,同时还传递了参数 SuperType.call(this,"PaddingMe"); //实例属性 this.age = 25; } var instance = new SubType(); alert(instance.name); //"PaddingMe" alert(instance.age); //25组合继承(伪经典继承)
即将原型链和借用构造函数的方法组合在一起,思路为使用原型链实现对原型属性和方法的继承,而通过借用构造函数来实现对实例属性的继承。
js function SuperType(name) { this.name = name; this.colors = ["red","blue","green"]; } SuperType.prototype.sayName = function() { alert(this.name); } function SubType() { //继承属性 SuperType.call(this,name); this.age = age; } SubType.prototype = new SuperType(); SubType.prototype.constuctor = SubType(); SubType.prototype.sayAge = function() { alert(this.age); } var instance1 = new("PaddingMe",25); instance1.colors.push("black"); alert(instance1.colors); //"red,blue,green,black" instance1.sayName; //"PaddingMe" instance1.sayAge; //25 var instance2 = new("hw",26); alert(instance2.colors); //"red,blue,green" instance2.sayName; //"hw" instance2.sayAge; //26原型式继承
js function object(o) { function F(){} F.prototype = o; return new F(); } var person = { name : "PaddingMe"; friends :["hw","wjj","hz"]; } var antherPerson = object(person); antherPerson.name = "Hhb"; antherPerson.friends.push("zxp"); var yetAntherPerson = object(person); yetAntherPerson.name = "Linda"; yetAntherPerson.friends.push("him"); alert(person.friends)//"hw,wjj,hz,zxp,him"
ECMAScirpt 5 中新增 Object.create() 方法规范化了原型式继承。有两个参数,一个用作新对象原型的对象和(可选的)一个为新对象定义额外属性的对象。
在传入一个参数情况下,Objetc.create() 和 object() 方法的行为相同。
js var person = { name : "PaddingMe"; friends :["hw","wjj","hz"]; } var antherPerson = Object.create(person); antherPerson.name = "Hhb"; antherPerson.friends.push("zxp"); var yetAntherPerson = Object.create(person); yetAntherPerson.name = "Linda"; yetAntherPerson.friends.push("him"); alert(person.friends)//"hw,wjj,hz,zxp,him"
第二个参数与 `Object.defineProperties() 方法的第二个参数格式相同: 每个属性都是通过自己的描述符定义的。
js var person = { name : "PaddingMe"; friends :["hw","wjj","hz"]; } var anthorPerson = Object.create(person, { name: { value:"hehe"; } }) alert(anthorPerson.name);//"hehe"寄生式继承
即创建一个仅用于封装继承构成的函数,该函数在内部以某种方式来增强对象,最后再像真地是它做了所有工作一样返回对象。
js function createAnother(original) { var clone = object(original); //通过调用函数创建一个新对象 clone.sayHi = function() { //以某种方式来增强这个对象 alert("hi"); }; return clone; //返回这个对象 } var person = { name : "PaddingMe"; friends :["hw","wjj","hz"]; } var anthorPerson = createAnother(person); anthorPerson.sayHi();//"hi"寄生组合式继承
jsfunction SuperType(name) { this.name = name; this.colors = ["red","blue","green"]; } SuperType.prototype.sayName = function() { alert(this.name); } function SubType(name,age) { SuperType.call(this,name); //第二次调用SuperType(); this.age = age; } SubType.prototype = new SuperType(); // 第一次调用SuperType(); SubType.prototype.constuctor = SubType; SubType.prototype.sayAge = function(){ alert(this.age); }
所谓寄生组合式继承,即通过借用构造函数来继承属性,通过原型链的混成形式来继承方法。基本思路为:不必为了指定子类型的原型而调用超类型的构造函数,我们所需要的无非是超类型原型的一个副本而已。本质上,就是使用寄生式继承来继承超类型的原型,然后再将结构指定给子类型的原型。寄生组合式继承的基本模式:
js function inheritPrototype(subType,superType){ var prototype = object(superType.prototype); //创建对象 prototype.constructor = subType; //增强对象 subType.prototype = prototype; // 指定对象 }
jsfunction SuperType(name) { this.name = name; this.colors = ["red","blue","green"]; } SuperType.prototype.sayName = function() { alert(this.name); } function SubType(name,age) { SuperType.call(this,name); //第二次调用SuperType(); this.age = age; } inheritPrototype(SubType,SuperType); SubType.prototype.sayAge = function(){ alert(this.age); }
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/85501.html
摘要:子类继承自父类的方法可以重新定义即覆写,被调用时会使用子类定义的方法什么是多态青蛙是一个对象,金鱼也是一个对象,青蛙会跳,金鱼会游,定义好对象及其方法后,我们能用青蛙对象调用跳这个方法,也能用金鱼对象调用游这个方法。 1、专用术语 面向对象编程程序设计简称:OOP,在面向对象编程中常用到的概念有:对象、属性、方法、类、封装、聚合、重用与继承、多态。 2、什么是对象? 面向对象编程的重点...
摘要:实际上,可以将其理解为某种形式的继承。如果上下文是,则使用全局对象代替。例如的第个参数是上下文,后续是实际传入的参数序列中允许更换上下文是为了共享状态,尤其是在事件回调中。 公开记录学习JS MVC,不知道能坚持多久= =。以《基于MVC的JavaScript web富应用开发》为主要学习资料。接上一篇类的学习,发现实在是看晕了,有些例子是能看懂在干嘛,但是不知道为什么这样做,有的甚至...
摘要:继承原型链如果构造函数或对象的原型指向构造函数或对象,的原型再指向构造函数或对象,以此类推,最终的构造函数或对象的原型指向的原型。 继承 原型链 如果构造函数或对象A的原型指向构造函数或对象B,B的原型再指向构造函数或对象C,以此类推,最终的构造函数或对象的原型指向Object的原型。由此形成了一条链状结构,被称之为原型链。按照上述的描述,在B中定义的属性或方法,可以在A中使用并不需要...
摘要:即另外,注意到构造函数里的属性,都没有经过进行初始化,而是直接使用进行绑定。并且在模式下,构造函数没有使用进行调用,也会导致报错。调用构造函数千万不要忘记写。 1. 基础 JavaScript不区分类和实例的概念,而是通过原型来实现面向对象编程。Java是从高级的抽象上设计的类和实例,而JavaScript的设计理念,听起来就好比Heros里的Peter,可以复制别人的能力。JavaS...
摘要:例例通过原型链来检测对象所调用的方法是否存在,存在在哪个原型对象上除了在对象对象中存在外,其他方法都是通过原型链的方法在上找到并调用。 前言 学习了解JavaScript对象的继承机制 JavaScript Object 概念 Object是js的基本数据结构的一种,属于引用类型。 对象的创建方法 对象字面量写法 构造函数,通过构造函数来创建对象实例 Object()构造函数 cre...
阅读 725·2021-10-14 09:43
阅读 2045·2021-09-30 09:48
阅读 3417·2021-09-08 09:45
阅读 1072·2021-09-02 15:41
阅读 1857·2021-08-26 14:15
阅读 743·2021-08-03 14:04
阅读 2931·2019-08-30 15:56
阅读 3052·2019-08-30 15:52