访问者模式(Visitor): 针对于对象结构中的元素,定义在不改变该对象的前提下访问结构中元素的新方法
我们来看下面这段代码,这段代码,我们封装了一个绑定事件的方法,接着我们调用这个方法,通过点击页面上的元素,改变元素的样式。
- var bindEvent = function(dom, type, fn) {
- if (dom.addEventListener) {
- dom.addEventListener(type, fn, false);
- } else if (dom.attachEvent) {
- dom.attachEvent('on' + type, fn);
- } else {
- dom['on' + type] = fn;
- }
- }
- var test = document.getElementById('test');
- bindEvent(test, 'click',
- function() {
- this.style.backgroundColor = 'red';
- });
我们分别在谷歌和IE以及低版本的IE浏览器下看一看
我们发现在谷歌和高版本IE下我们的效果正常,到了IE8却提示this.style为空或不为对象,这是为什么呢?
现在我们调整一下代码,我们把绑定样式的代码去掉增加下面这段代码,再执行一下
- alert(this === window);
我们发现在低版本的IE下返回的true(在IE7,IE8下不知道为什么alert没反应,我暂时还没找到原因,如果有知道的请告知,万分感谢。)
这样就解释了为什么我们之前的代码在低版本的IE下会抛异常,因为我们的this指向的是window而不是元素本身,所以我们如果想要获取事件对象,需要通过window.e
这个时候我们就可以通过访问者模式来解决事件回调函数中对该元素的访问问题。
- function bindIEEvent(dom,type,fn){
- dom.attachEvent('on'+type,function(e){
- fn.call(dom,e);
- });
- };
访问者模式的实现核心其实就是调用了一次call方法,我们知道call和apply的作用就是更改函数执行时的作用域,这正是访问者模式的精髓所在
我们再来试试
- bindIEEvent(test,'click',function(e){
- this.style.backgroundColor='red';
- });
我们看到现在在低版本的IE下就没问题了
注意!这个方法在谷歌和IE8以上版本会抛对象不支持attachEvent属性或方法异常
我们还可以通过访问者模式创建一个对象访问器,像操作数组那样处理一个对象,我们来看看具体实现
- //创建访问器
- var Visitor = (function() {
- return {
- //截取方法
- splice: function() {
- var args = Array.prototype.splice.call(arguments, 1);
- return Array.prototype.splice.apply(arguments[0], args);
- },
- //追加数据方法
- push: function() {
- var len = arguments[0].length || 0;
- var args = this.splice(arguments, 1);
- arguments[0].length = len + arguments.length - 1;
- return Array.prototype.push.apply(arguments[0], args);
- },
- //删除最后一次添加成员
- pop: function() {
- return Array.prototype.pop.apply(arguments[0]);
- }
- }
- })();
我们调用一下试试
- var a = new Object();
- console.log(a.length);
- Visitor.push(a, 1, 2, 3, 4);
- console.log(a.length);
- Visitor.push(a, 4, 5, 6);
- console.log(a);
- console.log(a.length);
- Visitor.pop(a);
- console.log(a);
- console.log(a.length);
- Visitor.splice(a, 2);
- console.log(a);
访问者模式解决数据与数据的操作方法之间的耦合,将数据的操作方法独立于数据,使其可以自由化演变。因此访问者更适合于那些数据稳定,但是数据的操作方法易便的环境下。因此当操作环境改变时,可以自由修改操作方法以适应操作环境,而不用修改原数据,实现操作方法的拓展。同时对于同一个数据它可以被多个访问对象所访问,这极大增加了操作数据的灵活性。
也谢谢大家看到这里:)如果你觉得我的分享还可以请点击推荐,分享给你的朋友让我们一起进步~
好了以上就是本次分享的全部内容,本次示例参考自JavaScript设计模式一书,让我们一点点积累一点点成长,希望对大家有所帮助。
来源: http://www.cnblogs.com/chen-jie/p/JavaScript-Visitor.html