注册会员 登录
Project1 返回首页

i I snow https://rpg.blue/?243868 [收藏] [复制] [分享] [RSS]

日志

JavaScript的面向对象

热度 1已有 138 次阅读2016-4-10 11:15 |个人分类:

本文参考《JavaScript设计模式与开发实践》(曾探,中国工信出版集团)以及网络上资源,看看就行,别信以为真

JavaScript(下面简写成JS吧)作为一个动态类型类型,面向对象的实现,依靠的是原型委托的方式;
至于什么动态类型、多态、原型就不说了,就说说一些不好弄明白的地方吧:

1.this与this的指向
JS的this和C++的this区别蛮大的,它是按层级获取当前环境的对象来进行指向的,所以就是说可以对其进行保存和赋予:
一般来说局部函数、返回函数想要保留函数体的this指向可以直接赋值:
var original = function(){
var thisKeep = this;
var callback = function(){
func(thisKeep);
};
callback();
};
返回函数的保存则是利用了闭包,后面说
赋值就是call、apply了

2.Function.prototype.call 与 Function.prototype.apply
这两个是Function对象的原型方法,可以改变Function中的this的指向
上面的original 还可以这么写:
var original = function(){
var callback = function(){
func(this);
};
callback.call(this);
};
call和apply二者区别只是参数的传入方式稍有差距而已,利用apply可以实现环境bind
Function.prototype.bind = function(context){
var self = this;
return function(){
return self.apply(context,arguments);
}
};//这个是无参数形式的bind

3.作用域与闭包
变量在声明时决定了他的作用域以及生命周期,对于函数的局部变量一般在函数执行完成后就会销毁:
var funcplus = function(){
var a=1;
return function(){
a++;
console.log(a);
}
};
var objectFun = funcplus ();

objectFun (); //2
objectFun (); //3
objectFun (); //4

这个时候a的值并不会销毁,类似于类变量的形式,var objectFun = funcplus ()其实就类似于一个Function对象的实例化,而funcplus 这个函数就是一个闭包,实例化(JS中应该是返回一个原型的引用)的时候a的执行环境会被记录并可以被外界访问;

闭包可以封装变量、延续局部变量的寿命,MV中动态载入图像文件的时候就是利用这一点

4.函数的传递与自执行
函数作为一种特殊的数据,可以被当做参数,也可以当做返回值,常见的形式就是回调、迭代、bind等
匿名函数一般需要自执行,这样也方便进行闭包处理:

var Type = {};

for(var i=0,type;type = ['Null','String','Boolean','Number','Array','Object','Function'][i++];){
(function(type){
Type['is'+type] = function(obj){
return Object.prototype.toString.call(obj) === '[object '+type+']';
}
})(type)
};
这里实现简单的数据类型判别:
Type.isString('dddd');
Type.isArray([]);

设计模式,并不针对结构,只针对意图,也就是说模式实现意图的一些较好的方式
下面说说几个设计的模式:
1.单例模式
参看RMMV,有很多对象想要实现的便是这种全局仅此一个实例,但是MV的Manager利用的是全局变量,而一堆$data更是如此,无原型的绑定,操作起来十分费力,而Game_系列则更应该都是单例,然后并没有。
单例实现方式有很多,充分利用JS的特性的单例模式应该如下:
var getSingle = function(func){
var resobj;
return function(){
return resobj || (resobj = func.apply(this,arguments));
}
};

2.发布订阅模式
参看RMMV的Input模块,在玩家输入时,其实并不是马上得到响应,而是等到下一个Input.Update时才会反应,有没有一种办法让Input主动去通知Scene进行反应呢?就是这个意图,出现了这种模式:

这种理念和回调是一致的,不是Scene一直去询问Input,而是Input在接受了Dom中的Event触发的按键、点击后直接通知Scene:
大致实现:

var Input = {};
Input.listenClient = [];
Input.listen = function(fn){
this.listenClient.push(fn);
}
Input.trigger = function(){
for(var i=0,fn;fn=this.listenClient[i++];){
fn.apply(this,arguments);
}
}

而Scene注册方法——使用下面这种形式即可:
Input.listen(function(){
.....
})

Input触发使用trigger(args),将参数传给所有的订阅者执行相应的操作

3.装饰者模式
JS的插件脚本中想要修改本来的原型,通用的方法就是:
var old_func = func || function(){};
func = function(){
...//do something before
old_func();
...//do somthing after
}
这里会有一些小问题:①old_func这个新的变量会变得让人不爽,②this有可能被劫持,比如你修改Manger系列的一些全局函数,当然可以这样这个修改防止问题:(假设这个func是Manger的函数)
func = function(){
...//do something before
old_func.apply(Manger,arguments);
...//do somthing after
}

下面提供一种办法装饰原函数实现脚本书写:
Function.prototype.before = function(func){
var _self_ = this;
return function(){
func.apply(this,arguments);
return _self_ .apply(this,arguments);
}
}

Function.prototype.after= function(func){
var _self_ = this;
return function(){
var res = _self_ .apply(this,arguments);
func.apply(this,arguments);
return res;
}
}

这样修改函数就变成了:(JQ的感觉对不对)
func = (func || function(){}).before(function(){
;//Do something before
}).after({
;//Do something after
});

当然有人说这样污染了Function的原型,那自己写一个装饰函数,传入先后的函数:(未实际试验)
 var fix = function(funobj){
return function(){
funobj.before.apply(this,arguments);
var res = funobj.original.apply(this,arguments);
funobj.after.apply(this,arguments);
return res;
}
}

func = fix({original:(func||function(){}),
before:function(){
;//Do something before
},after:function(){
;//Do something after
}});

4.享元模式(对象池)
我们现在要做一个弹幕游戏……恩(或者做粒子效果=。=),或者我们有很多NPC都长一个样子,是不是载入图片就卡爆了呢,显然没有…ImageManager里面提供了解决的办法:
ImageManager._cache  //图片信息的缓存
剩下的参看ImageManager的loadNormalBitmap函数即可

这种思路在使用大量相似对象、并且对象的大多数状态都一致,只是一些属性根据应用场景变化而变化
你们做一个MV的粒子效果试试,大概就是这样的模式。




1

鸡蛋

鲜花

刚表态过的朋友 (1 人)

评论 (0 个评论)

facelist doodle 涂鸦笔

您需要登录后才可以评论 登录 | 注册会员

拿上你的纸笔,建造一个属于你的梦想世界,加入吧。
 注册会员
找回密码

站长信箱:[email protected]|手机版|小黑屋|无图版|Project1游戏制作

GMT+8, 2022-1-28 19:21

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

返回顶部