以前在做Ext3开发的时候,一直用使用Ext.extend()来做类的继承,在以后写代码,都习惯了使用Ext.extend类似功能的代码来做类继承,但是遇到一个问题一直无法解决,如下面的代码:
MyClass1 = function() {}; MyClass1.prototype = { say: function() { alert('MyClass1 say hello world!'); } }; MyClass2 = Ext.extend(MyClass1, { say: function() { MyClass2.superclass.say.call(this); alert('MyClass2 say hello world!'); } });
每次子类需要调用超类方法,都要像下面这样写:
MyClass2.superclass.say.call(this);
这种写法有几个弊端:
- 类名要内置到函数代码模块中,如果一旦修改类名,就非常麻烦
- 每次的调用都要写一长串代码,有时候为了省事复制粘贴,忘记改类名,就会出错
- 有时候需要传参,使用call与apply调用用法不统一
所以,很长一段时间在想如何改进super的调用?能做到java那样,如:
public MyClass2 extends MyClass1{ public void say() { super.say(); System.out.println('MyClass2 say hello world!'); } }
自己试了好几种方法,总是不能完美解决,就放弃了一段时间,再后来也没有多想这事。
Ext4出来之后,看了一些资料,发现Ext4 Class非常强大,完美的解决我想的问题,其实,那时候挺兴奋,想研究以下源码的,打开代码库,发现Ext对类的支持过于强大(对我而言),结构异常复杂,那时候也由于重心没在这块,所以,就先放下没有继续研究。今天终于静下心来,用心阅读了Ext4 Class相关的源码(Ext的开发者很厉害,不得不佩服)。
Ext使用callParent就能调用到父类的方法,非常简单,用法如下:
MyClass2 = Ext.define({ say: function() { this.callParent(); // 调用父类的say() // 如果要为父类方法传参,只需要像下面这样写 //this.callParent(arguments); //this.callParent([param1, param2]); alert('say: hello world!'); } });
我把其中和类继承相关的代码剥离出来,重新编码,其他有关Config,Statics等特性全部移除,代码变简单了很多,也容易懂了很多。下面是应用的例子,Class的源码和例子都使用了requirejs,附件中是class.js的源码:
require(['class/Class'], function(Class) { var MyCls1 = Class.define({ say: function() { alert('MyCls1 say: hello world!'); // 输出'MyCls1 say: hello world!' } }); new MyCls1().say(); var MyCls2 = Class.define({ extend: MyCls1, say: function() { this.callParent(); alert('MyCls2 say: hello world!'); // 输出'MyCls1 say: hello world!' // 输出'MyCls2 say: hello world!' } }); new MyCls2().say(); var MyCls3 = Class.define({ extend: MyCls2, say: function() { this.callParent(); alert('MyCls3 say: hello world!'); // 输出'MyCls1 say: hello world!' // 输出'MyCls2 say: hello world!' // 输出'MyCls3 say: hello world!' } }); new MyCls3().say(); Class.override(MyCls2, { constructor: function(config) { this.name = config.name; }, say: function() { this.callParent(); alert('the new method MyCls2 say: hello world! by ' + this.name); // 输出'MyCls1 say: hello world!' // 输出'the new method MyCls2 say: hello world! by max' // 输出'MyCls3 say: hello world!' } }); new MyCls3({ name: 'max' }).say(); });
例子html页面
<!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Test Unit</title> <script type="text/javascript" src="../src/lib/requirejs.js"></script> <script type="text/javascript"> require.config({ baseUrl: '../src' }); </script> <script type="text/javascript" src="unit/Class.js"></script> </head> <body> </body> </html>
原创文章,转载请注明出处http://zhangdaiping.iteye.com
相关推荐
在深入理解JavaScript继承之前,我们需要掌握几个核心概念:父类(也称作超类)是指被继承的类,子类是通过继承父类得到的类,抽象类通常不用于实例化,而是作为其他类继承的基础,基类是提供给其他类继承的类,派生...
当我们在一个子框架中使用`window.parent`调用父框架的方法或属性时,IE和火狐的处理方式理论上应该是相同的。然而,实际应用中可能遇到的问题在于,不同浏览器对于未定义或者不存在的属性的处理策略不同。 在给定...
Animal.call(this, name); // 调用父构造函数 } Dog.prototype = Object.create(Animal.prototype); // 设置原型链 Dog.prototype.constructor = Dog; // 修复constructor属性 var dog = new Dog('Fido'); dog....
SuperType.call(this, name); // 调用父类构造函数 this.age = 25; } ``` #### 三、寄生式组合继承 **寄生式组合继承**结合了上述两种继承方式的优点,既可以在子类实例中拥有自己的属性,又可以共享父类的...
在JavaScript中,继承是实现面向对象编程的关键部分,尽管过度继承应该避免,但适当使用继承可以有效复用代码。由于JavaScript本身并不直接支持传统的继承概念,开发者通常通过模拟实现。本文将探讨三种主要的...
### JavaScript继承的三种方法实例详解 #### 一、概述 在JavaScript中,虽然原生语言层面没有提供传统意义上的“类”这一概念,但它通过构造函数和原型链等机制实现了类的功能,尤其是继承这一核心概念。继承是...
箭头函数是 ES6 引入的新特性之一,在箭头函数中,`this` 的值不是由函数调用的方式决定的,而是继承自定义箭头函数时所在的作用域: ```javascript var obj = { test: function() { var arrowFunc = () => { ...
在 JavaScript 中实现面向对象编程,通常会使用构造函数、原型链、以及类语法(ES6 之后引入)。`this` 在这些场景中起到关键作用,尤其是在创建实例和继承时。 例如,构造函数用于初始化新创建的对象: ```...
Parent.call(this, name); } Child.prototype.sayHello = function() { console.log('Hi'); } let child = new Child('child'); console.log(child.name); // child child.sayHello(); // Hi ``` 3. 组合继承 ...
**原理**: 构造函数继承是通过在子类构造函数内部调用父类构造函数(通常使用`call`或`apply`方法)来实现属性和方法的继承。 - **核心概念**: 通过这种方式,子类可以继承父类的所有属性和方法,并且可以在子类...
在B的`print`方法中,通过`this.prototype.print.call(this)`调用了A的`print`方法。 然而,这种做法在多层继承时会出现问题,因为`this.prototype`始终指向B.prototype,而不是A.prototype。当增加C类时: ```...
但在JavaScript中,由于没有类的概念,而是使用构造函数来创建对象,因此继承通常是通过构造函数之间的一种关系来实现的。 首先,介绍一种常见的继承方式——对象伪装或构造继承。这种方法的基本思路是将父类的构造...
JavaScript中的链式调用是一种常见的编程技巧,尤其在处理对象属性和方法时,可以使代码更加简洁、易读。链式调用的核心思想是通过在每次方法调用后返回对象自身,使得可以连续调用多个方法而无需重复指定对象名。在...
EXT.js提供了`this.callParent()`和`this.superclass.methodName.call(this)`两种方式来实现这一点。 - **避免副作用**:重写方法时要确保不会意外影响其他代码,尤其是当你重写的是核心库的方法。 - **测试**:确保...
Person.call(this, name, age); // 使用call调用父类构造函数 this.grade = grade; } // 设置Student的原型为Person的实例 Student.prototype = Object.create(Person.prototype); // 需要手动修正constructor...
JavaScript中的继承是面向对象编程的重要概念,它允许创建新的对象类,这些类可以从现有类继承属性和方法。本文将深入探讨JavaScript中常见的两种继承实现方式:`prototype`方式和`apply`方式,并分析它们的优缺点。...
- **使用`.call()`、`.apply()`、`.bind()`方法**: 这些方法可以显式指定`this`的值。其中,`.call()`和`.apply()`会立即执行函数,并允许传递参数;`.bind()`则返回一个新的函数,其`this`值被固定。 - `.call()`:...
- `Test_invoke_super_range.java`:这看起来是测试类,用于测试如何在某个范围(可能是继承链的一个部分)内调用超类的方法。 - `source.js`:虽然JavaScript不支持"super"关键字以相同的方式调用超类(JavaScript...