对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)); / / 附魔,另一个对象
总结
你不需要总结。