对Javascript系列的深入理解(46):代码重用模式(建议)详细说明

对Javascript系列的深入理解(46):代码重用模式(建议)详细说明
介绍

本文中介绍的四种代码重用模式都是最佳实践,建议在编程过程中使用。

模式1:原型继承

原型继承的目的是使父对象作为子对象的原型,以达到继承的目的。

复制代码代码如下所示:

函数对象(o){

函数f(){

}

f.prototype = O;

返回新的f();

}

要继承的父对象

var父= {

姓名:爸爸

};

新对象

var子对象(父类);

测试

console.log(孩子的名字); / /爸爸
父/ /构造函数

功能人(){

属性

this.name = 亚当;

}

在原型中添加新属性

(person.prototype.getname =功能){

返回this.name;

};

创建一个新的人

Var Papa =新人();

继承

var =对象(Papa);

Console.log((孩子。getName)); / /亚当
父/ /构造函数

功能人(){

属性

this.name = 亚当;

}

在原型中添加新属性

(person.prototype.getname =功能){

返回this.name;

};

继承

var =对象(人,原型);

console.log(typeof的孩子。getName); / / 功能

console.log(typeof的孩子的名字); / / 定义
同时,ecmascript5也提供类似的方法称为object.create继承对象,使用如下:

复制代码代码如下所示:

功能* / / *使用新的ECMAscript 5提供

VaR的孩子= object.create(母);

VaR的孩子= object.create(父母,{

年龄:{ 2 }值: / / ecma5描述符

});

console.log(child.hasownproperty(年龄)); / /真的
您还可以更精细地定义第二个参数的属性:

复制代码代码如下所示:

首先,我们定义一个新对象

无功的人= object.create(空);

然后配置设置,创建属性

/ /属性设置为可写,可枚举,可配置

var

可写的:真的,

枚举:真,

配置:真

};

(对象。defineproperty) / /常用的添加新的属性(ecmascript5支持)

现在,为了方便起见,我们定制包函数。

无功defineprop =功能(obj,关键值){

config.value =价值;

object.defineproperty(obj,关键配置);

}

DefineProp(男,'car ','delorean);

DefineProp(男,'dob ','1981);

DefineProp(男,'beard,假);
因此,继承可以完成。

复制代码代码如下所示:

VaR的驱动object.create(人);

DefineProp(司机,'topspeed ','100mph);

driver.topspeed / / 100mph
但有一个需要注意的是,由object.create原型(空)是不确定的,即没有toString和价值方法,所以警报(人)都是错误的,但警报(人,车)是没有问题的。

模式2:复制所有属性以继承

这种方法的继承是将父对象的所有属性复制到子对象,而普通子对象可以使用父对象的数据。

先看一个浅拷贝的例子:

复制代码代码如下所示:

浅拷贝

函数扩展(父、子){

var i;

孩子=孩子| | { };

为(我在父){

如果(parent.hasownproperty(I)){

子{ } =父{ };

}

}

返回的孩子;

}

var爸爸=名称:亚当};

扩展(爸爸);

console.log(孩子的名字); / /亚当

var爸爸{ {

计数:{ 1, 2, 3 },

读:{纸:真}

};

扩展(爸爸);

Kid.counts.push(4);

Console.log((爸爸计数。toString)); / / 1,2,3,4

console.log(dad.reads =孩子读); / /真的
最后一行代码,您可以看到父亲和孩子的阅读是相同的,也就是说,他们使用相同的引用,这是浅拷贝引起的问题。

让我们再看一遍深拷贝。

复制代码代码如下所示:

深度复制

功能extenddeep(父母,子女){

var i,

tostr = object.prototype.tostring,

天文学={对象数组};

孩子=孩子| | { };

为(我在父){

如果(parent.hasownproperty(I)){

如果(typeof母{我} = 'object){

孩子{我} =(tostr.call(母{我})=天文学){ } { };

extenddeep(母{我},{我孩子});

{人}

子{ } =父{ };

}

}

}

返回的孩子;

}

var爸爸{ {

计数:{ 1, 2, 3 },

读:{纸:真}

};

VaR的孩子= extenddeep(爸爸);

Kid.counts.push(4);

Console.log((孩子。计数。toString)); / / 1,2,3,4

Console.log((爸爸计数。toString)); / / 1,2,3

console.log(dad.reads =孩子读); / /假

kid.reads.paper = false;
深度复制后,两个值不相等,bin!

模式3:混合(混合)

混合是将一个或多个(或所有)属性(或方法)复制到另一个对象,并给出一个例子:

复制代码代码如下所示:

函数混音(){

var,道具,子= { };

对(阿根廷= 0;精氨酸< arguments.length;精= 1){

对于(参数中的支持{ } }){

如果(参数{精}。hasownproperty(道具)){

子参数;

}

}

}

返回的孩子;

}

var蛋糕=混合(

{卵:2,大:真},

{黄油:1,加盐:真},

{:3杯面粉},

{糖:'sure!}

);

Console.dir(蛋糕);
混合函数复制所有的参数,通过为子对象产生一个新的对象的子属性。

那么我们怎样才能混合一些属性呢这个怎么样事实上,我们可以利用多余的参数来定义需要的混合属性,如混合(孩子,家长,1、2),所以我们只能配合方法和方法在孩子孩子上的代码:

复制代码代码如下所示:

/汽车

var =函数(设置){

方法:设置。model'no模型提供的| |;

this.colour =设置。colour'no颜色提供| |;

};

/ /混合

VaR mixin =函数(){ };

mixin.prototype = { {

推动:函数(){

console.log('drive前进);

},

drivebackward:函数(){

console.log('drive落后);

}

};
2 /参数定义的对象是混合(接收)和混合对象(给予)

功能扩展(receivinbj,givinbj){

如果提供了方法中指定的名称,则为额外参数3。

如果(参数{ 2 }){

For (VaR I = 2, len = arguments.length; I < len; i++) {

receivinbj。原型{参数{我} } = { givinbj。原型参数{我} };

}

}

如果没有指定第三参数,或所有参数,那么

{其他

对于(在givinbj。原型的VaR方法名){

接收/内部检查对象不包含混合名称,如何不包含混合

如果(!receivinbj原型{ }){语句。

receivinbj {语句} = givinbj。原型。原型{语句};

}

}

}

}

汽车 / /混合属性值,但混合with'driveforward'and'drivebackward * /

增加(汽车,混合,'driveforward ','drivebackward);

创建一个新的对象车

VAR车=新车({模型:'ford护航,颜色:蓝' });

测试是否成功/混合方法

vehicle.driveforward();

vehicle.drivebackward();
这种方法使用得更灵活。

模式4:借款方式

一个对象借用另一个对象的一个或两个方法,两个对象之间没有直接的连接,没有太多的解释,直接在代码中解释。

复制代码代码如下所示:

var = {

名称:'object,

表示:函数(问候){

返回迎接+,+ this.name;

}

};

测试

Console.log (one.say ('hi')); / / Hi, object

var

名称:还有一只对象

};

console.log(one.say.apply(2,{你好' })); / / 你好,另一个对象

将分配给变量,这将引用全局变量。

VAR说= one.say;

console.log(说('hoho ')); / / 呵呵,不确定

输入回调函数回调

一个= { { var

然而另一个对象的名字,

方法:函数(回调){

返回回调('hola);

}

};

console.log(yetanother.method(的说)); / / 喂,未定义

函数绑定(O,m){

返回函数(){

返回m.apply(O,{ }。slice.call(参数));

};

}

无功twosay =绑定(2,1。说);

console.log(twosay('yo ')); / / 哟,另一个对象
5 / / ECMAscript function.prototype添加绑定()方法,使它易于使用(应用)和电话()。

如果(typeof function.prototype.bind = 'undefined){

function.prototype.bind =功能(thisarg){

这个=,

array.prototype.slice片=,

args = slice.call(参数1);

返回函数(){

返回fn.apply(thisarg,args.concat(slice.call(参数)));

};

};

}

无功twosay2 = one.say.bind(2);

console.log(twosay2('bonjour ')); / / 你好,另一个对象

无功twosay3 = one.say.bind(2,'enchant);

Console.log((twosay3)); / / 附魔,另一个对象
总结

你不需要总结。

tag:模式代码重用详细说明建议系列

相关内容