现在的位置: 首页 > 综合 > 正文

JS OO 的继承机制

2013年10月11日 ⁄ 综合 ⁄ 共 2540字 ⁄ 字号 评论关闭

作者:stroll
来自:无忧脚本  作者还没有授权,呵呵
原帖地址:http://be10.ods.org/51js/viewthread.php?tid=9958

这篇文章是研究关于 JS OO 的继承机制,但绝对不是以前的那种哦,而是探讨新的方式。。如果你对OO感兴趣,就让我们继续吧!

也许你一直对 Script5.5 里面的 call apply 等方法很有想法?他到底是怎么工作的?我也一直很好奇,就是没时间研究。
今天就花些时间一起研究一下?呵呵~~~

记得以前我也介绍过关于 JS OO 的实现方式

这是父类 A 的代码
function A(){
    this.doA = function(){
        alert("doA");
    }
}

对于 call apply 的方式 IE5.5 以上
function B(){
    A.call(this);
}

对于 prototype 方式 IE 5.0
function B(){

}
B.prototype = new A();

只要使用以上方式,B 类 的 对象 就可以使用 A 类的方法了。。由于 call apply 现在对我们来说是未知数,我们就暂时不管他,先从 prototype 这个SB开刀。。

prototype 是什么意思呢? Script 手册上说是返回 【返回对象类型原型的引用】。晕~~什么叫原型啊?我也不懂~呵呵

不过结合他所说的 【用 prototype 属性提供对象的类的一组基本功能。对象的新实例“继承”赋予该对象原型的操作。】
我们就可以明白

类名.prototype.方法名 = xxxx 和 在类内部定义 this.方法名 = xxxx 是完全等价的

明白了这些,就让我们继续了解 类名.prototype = new 父类名() 的工作原理吧? 不过就此打住,我不想再对这个实现方式说什么了。为什么?因为我觉得他并不是有效且明确的继承方式。。嘿嘿,我发现更好更容易明白的方式来继承。

在此之前先让我们来了解一些 函数机制

function C(){
    this.do1 = function(){
        this.do2 = function(){
            alert("do2");
        }
    }
}
var o = new C();
o.do1();
o.do2();    // 结果是 do2

可见【类的 属性/方法 是可以在运行期间添加的】(一观众上台,二话不说抡起砖块就砸:“拷,这谁不知道啊,用你说!浪费老子大半天时间!!”)
别瞧不起这个简单的原理,他可是有效实现类继承的前提。。。(当!“那还不快说,这么多废话!” 小逛摸了摸头上的包继续开说~~)

让我们看看下面这段代码:
function P(){
    this.do2 = function(){
        alert("do2");
    }
}

function C(){
    P();
}

var o = new C();
o.do2();    // 结果 是 do2

看出些什么了吧?嗯嗯,台下不少聪明的听众已经开始自行实现 call apply 了。。
如果是稍微比我聪明点,但却还不能理解call apply工作原理的请往下看。。

首先再跟大家介绍一位靓妹: constructor,她能够返回 创建该对象的函数。比如:
function C1(value){
    this.data = value
    this.create = function(value){
        return new this.constructor(value);    // 等价 return new C1(value)
    }
    this.say = function(){
        alert("C1 say " + this.data);
    }
}
var o = new C1("你好");
var o2 = o.create("你叫我啊?");
o2.say();    // 结果为 C1 say 你叫我啊?

还有一位帅哥。。 arguments 他是返回函数的参数集合,
arguments.length 返回参数个数
arguments[i] 可以获取指定下标的参数
function F(){
    alert(arguments.length);
    if(arguments.length > 0)
        alert("arg[0] = " + arguments[0]);
}

F(1,2,3);
// 结果是
3
arg[0] = 1

说到这里大家应该能领略 constructor 的漂亮 和 arguments 的帅气了吧? 接着我们让 prototype+constructor+arguments联手构造我们的 call 吧。。

Function.prototype.call = function(sonFun){
    if(sonFun instanceof Object == false){    // 如果 sonFun 不是 函数
        alert("call 方法第一个参数需要有效函数!");
        return;
    }
    sonFun.constructor.prototype.___base = this;    // 定义 sonFun 的属性 __base 为当前调用 call 的函数
    if(arguments.length == 1){    // 只有一个参数
        sonFun.___base();
    }else{
        var aoEval = new Array();
        for(var i=1; i<arguments.length; i++){
            aoEval[aoEval.length] = "arguments["+i+"]"
        }

        aoEval = "sonFun.___base(" + aoEval.join(",") + ")";    // sonFun.__base(arguments[0], ...,arguments[i])
        //alert(aoEval)
        eval(aoEval);
    }
}

function C1(value){
    this.data = value
    this.say = function(){
        alert("C1 say " + this.data);
    }
}

function C2(value){
    C1.call(this, value);
}

var o = new C2("我是 call 制造的说~~");
o.say()
 

抱歉!评论已关闭.