原型模式实现OOP的再研究

2019-09-21 22:42 来源:未知

复制代码 代码如下:

复制代码 代码如下:

function A()
{
this.v1 = 10;
}
A.prototype.print = function()
{
alert(this.v1);
}
function B()
{
}
B.prototype = new A();
new B().print();

运作这段代码输出是10,看起来好疑似类B承继了类A的艺术print,并发生了精确的出口,实际上的实施流程是在类B生成的靶子中,不可能间接得到方法print,于是在它的prototype属性中研究对应的方法,这一个方案的出发点很好,类B中设有就调用类B的,不然调用它的prototype属性(类A)中的同名方法。可是有时大家必要子类的点子调用父类同名的主意,举例类B改为

复制代码 代码如下:

function B()
{
this.v2 = 15;
}
B.prototype = new A();
B.prototype.print = function()
{
this.prototype.print.call(this);
alert(this.v2);
}
new B().print();

当中,this.prototype.print正是类A对应的print方法,输出是10和15,好像消除了难点,实际上不然,大家再持续一层

复制代码 代码如下:

function C()
{
this.v3 = 20;
}
C.prototype = new B();
C.prototype.print = function()
{
this.prototype.print.call(this);
alert(this.v3);
}
new C().print();

我们期望的输出依次是10, 15, 20, 可是很倒霉,那样写的结果是系统会沦为死循环
因为在实行那几个法辰时,

复制代码 代码如下:

C.prototype.print = function()
{
this.prototype.print.call(this);
alert(this.v3);
}

将会循环的调用以下办法,直到货仓溢出

复制代码 代码如下:

B.prototype.print = function()
{
this.prototype.print.call(this);
alert(this.v2);
}

无可争辩的写法此时理应成为

复制代码 代码如下:

B.prototype.print = function()
{
A.prototype.print.call(this);
alert(this.v3);
}
C.prototype.print = function()
{
B.prototype.print.call(this);
alert(this.v3);
}

而是在后续关系发生了改变的景况下,供给改变比较多的对父类的引用,那亦不是极品的措施,在其实使用中,能够虚构动用_super来取代父类的称号,_this来替代本身的称谓,然后用三个正式的点子将他们替换到[super].prototype或者[this].prototype,进而未有歧义的调用钦赐的措施,那才是javascript的OOP的真正建设方案,相关的代码如下:

复制代码 代码如下:

/*
在利用OOP承接体系时, 首先要定义类, 最终实施extendsOf开始化类, 使用_super引用父类, 如, 使用_this援用笔者的措施,
例如:
function Extend2()
{
_super();
}
Extend2.prototype.setValue = function(value)
{
_super.setValue(value);
alert("Extend2:" + value);
}
Extend2.extendsOf(Extend1);

类承接树的根为Object. 注意: 全部应用了转义的分子函数都不能够不定义在extendsOf方法调用从前.
对象足以设定贰个自行运维的开头化代码, 以下划线初阶, 名称与对象名称一致, 如
Object._Object = function() {...}
假设指标的开始化代码荒诞不经, 将活动物检疫索父对象的开始化代码, 直到方方面面招来完毕

复制代码 代码如下:

Function.FRBlock = / *("([^"^\]|\")*"|'([^'^\]|\')*'|/([^/^\]|\.)*/) */;
Function.FRSpace = /s+/g;
Function.FRSign = / ?(^|;|:|<|>|?|,|.|/|{|}|[|]|-|+|=|(|)|*|^|%||) ?/g;
Function.FRRefer = /_(super|this)(.[^(]+)?(([^)]*))/;
Function.prototype.FCompile = function(name)
{
//检查是类的构造函数依然类的性质, name参数为空表示是构造函数
if (name)
{
//类的属性不是函数达成, 直接赋值到子类后退出
if (typeof this.prototype[name] != "function")
{
window[this.FClassName].prototype[name] = this.prototype[name];
return;
}
var s = this.prototype[name].toString();
}
else
{
var s = this.toString();
}
var b = "";
var r;
//过滤空白字符
while (r = Function.FRBlock.exec(s))
{
s = RegExp.rightContext;
b += RegExp.leftContext.replace(Function.FRSpace, " ").replace(Function.FRSign, "$1") + r[1];
}
b += s.replace(Function.FRSpace, " ").replace(Function.FRSign, "$1");
var i = b.indexOf("(");
var j = b.indexOf(")", i);
if (!name)
{
this.FClassName = b.substring(9, i);
}
var cn = this.FClassName;
var arg = b.substring(i + 1, j);
s = b.substring(j + 2, b.length - 1);
b = "";
//举行调用转义, 将_super,_this替换为钦点的主意
for (var n = 0; r = Function.FRRefer.exec(s); n++)
{
if (r[2])
{
if (!name && !n)
{
b = this.FSuperClass.FClassName + ".apply(this,arguments);";
}
r[2] = ".prototype" + r[2];
}
else if (r[1] == "this")
{
//JS函数不区分参数的反差, 构造函数不允许递归调用本身
throw "Constructor call mustn't be "_this();" in a constructor";
}
else if (name || RegExp.leftContext)
{
throw "Constructor call must be the first statement in a constructor";
}
else
{
r[2] = "";
}
s = RegExp.rightContext;
b += RegExp.leftContext + (r[1] == "this" ? cn : this.FSuperClass.FClassName) + r[2] + (r[3] ? ".call(this," + r[3]

  • ")" : ".apply(this,arguments)");
    }
    if (n)
    {
    b += s;
    }
    else if (name)
    {
    //未有针对性_this,_super的调用, 不用编写翻译
    window[cn].prototype[name] = this.prototype[name];
    return;
    }
    else
    {
    //未有对父类构造函数的调用时, 自动抬高
    b = this.FSuperClass.FClassName + ".apply(this,arguments);" + s;
    }
    //编译结果赋值
    if (name)
    {
    eval(cn + ".prototype." + name + "=function(" + arg + "){" + b + "}");
    }
    else
    {
    eval(cn + "=function(" + arg + "){" + b + ";if(this.constructor==" + cn
  • ")" + cn + "._" + cn + ".apply(this,arguments);}");
    window[cn].FClassName = cn;
    }
    }
    Function.prototype.extendsOf = function(superClass)
    {
    this.FSuperClass = superClass;
    //编写翻译类的方方面面函数
    this.FCompile();
    for (var name in this.prototype)
    {
    this.FCompile(name);
    }
    var clazz = window[this.FClassName];
    clazz.FSuperClass = superClass;
    //复制父类中子类未有落实的函数和属性
    var prototype = clazz.prototype;
    for (var name in superClass.prototype)
    {
    if (!prototype[name])
    {
    prototype[name] = superClass.prototype[name];
    }
    }
    //复制初阶化方法, 形式如Object._Object
    for (var c = this; ; c = c.FSuperClass)
    {
    if (c["_" + c.FClassName])
    {
    clazz["_" + clazz.FClassName] = c["_" + c.FClassName];
    return;
    }
    }
    }
    /*
    内置Object类为OOP提供的支撑
    */
    Object.FClassName = "Object";
    Object._Object = Function.Instance;
    Object.prototype.instanceOf = function(clazz)
    {
    for (var c = this.constructor; c; c = c.FSuperClass)
    {
    if (c === clazz)
    {
    return true;
    }
    }
    return false;
    }

你或者感兴趣的小说:

  • JavaScript设计方式之原型格局(Object.create与prototype)介绍
  • 深远理解JavaScript体系(42):设计形式之原型方式详解
  • JS面向对象基础讲授(工厂形式、构造函数方式、原型情势、混合格局、动态原型方式)
  • js面向对象之广大创设对象的二种艺术(工厂方式、构造函数格局、原型情势)
  • javascript原型方式用法实例详解
  • javascript组合使用构造函数情势和原型形式实例
  • 详解js发生对象的3种为主格局(工厂格局,构造函数形式,原型情势)
  • JavaScript 设计格局安全沙箱格局
  • JavaScript设计形式之观望者格局(揭橥者-订阅者形式)
  • JavaScript 设计方式之组成情势深入分析
  • JavaScript设计方式之原型格局分析【ES5与ES6】
TAG标签:
版权声明:本文由990888藏宝阁发布于关于计算机,转载请注明出处:原型模式实现OOP的再研究