zoukankan      html  css  js  c++  java
  • 再起航,我的学习笔记之JavaScript设计模式26(解释器模式)

    解释器模式

    概念介绍

    解释器模式(Interpreter):给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。

    获取元素在页面中的路径

    我们都知道获取一个元素很简单通过document.getElementById方法我们可以很轻易的获取到文档中ID为某个字段的元素,那么如果我们想要获取元素在页面中的路径我们又改怎么办呢?
    我们可以想象一下,页面就是一个很大的文档树。从最开始的html开始到同级的head,body再到body下的子元素。最后再定位到我们按钮,比如下面这个简单的文档树。

    <html>
        <head></head>
        <body>
            <div></div>
            <div><input type="button" /></div>
        </body>
    </html>
    

    如果我们想获取按钮的位置,我们可以这样理解html>head|body>div2>input。
    我们一层一层的定位知道最后确定我们按钮的所在位置。

    解释器

    我们刚刚相当于定义了一组语言规则,现在我们要做的就是使用解释器来完成我们刚刚定义的规则,这就是解释器模式。
    下面我们就开始实现我们的解释器:
    首先我们需要写一个方法去获取兄弟元素的名称

    function getSublingName(node){
    		
    	//如果存在兄弟元素
    	if(node.previousSibling){
    	
    		//返回的兄弟元素名称字符串
    		var name='',
    		//紧邻兄弟元素中相同名称的元素个数
    		count=1,
    		//原始节点名称
    		nodeName=node.nodeName,
    		//前一个兄弟元素
    		sibling=node.previousSibling;
    
    		//如果存在前一个兄弟元素
    		while(sibling){
    			
    			//如果节点为元素,并且节点类型与前一个兄弟元素相同,并且前一个兄弟元素名称存在
    			if(sibling.nodeType==1&&sibling.nodeType===node.nodeType&&sibling.nodeName){
    				//如果节点名称和前一个兄弟元素名称相同
    				if(nodeName==sibling.nodeName){
    					//节点名称后面添加技数
    					name+= ++count;
    				}else{
    					//重复相同紧邻节点名称节点个数
    					count=1;
    					//追加新的节点名称
    					name+='|'+sibling.nodeName.toUpperCase();
    				}
    			}
    			//向前获取一个兄弟元素
    			sibling=sibling.previousSibling;
    		}
    		return name
    	}else{
    		//如果不存在兄弟元素返回‘’
    		return '';
    	}
    }
    

    有了这个方法我们处理每一层的元素节点就方便很多了,下面我们开始实现我们的解释器

    //元素位置解释器
    var Interpreter=(function(){
    	
    	
    	//node目标节点,wrap容器节点
    	return function(node,wrap){
    		//路径数组
    		var path=[],
    		//如果不存在容器节点,默认为document
    		wrap=wrap||document;
    		//如果当前(目标)节点等于容器节点
    		if (node===wrap) {
    			//容器节点为元素
    			if (wrap.nodeType==1) {
    				//路径数组中输入容器节点名称
    				path.push(wrap.nodeName.toUpperCase());
    			}
    			//返回最终路径数组结果
    			return path;
    		}
    		//如果当前节点的父节点不等于容器节点
    		if (node.parentNode!==wrap) {
    			//对当前节点的父节点执行遍历操作
    			path=arguments.callee(node.parentNode,wrap);
    			
    		}else{
    			//如果容器节点为元素
    			if(wrap.nodeType==1){
    				//路径数组中输入容器节点名称
    				path.push(wrap.nodeName.toUpperCase());
    			}
    		}
    		//获取元素的兄弟元素名称的统计
    		var sublingNames=getSublingName(node);
    		
    		//如果节点为元素
    		if(node.nodeType==1){
    			//输入当前节点元素名称及其前面兄弟元素名称统计
    			path.push(node.nodeName.toUpperCase()+sublingNames);
    		}
    		//返回最终路径数组结果
    		return path;
    	}
    })();
    

    好的现在我们的解释器就完成了,下面我们测试一下
    首先我们创建一个简单的页面

    <!DOCTYPE html>
    <html>
    	<head>
    		<meta charset="UTF-8">
    		<title></title>
    	</head>
    	<body>
    <div></div>
      <div id="container">
      	<div>
      		<div>
      			<ul>
      				<li><span id="span1">1</span></li>
      				<li><span id="span2">2</span></li>
      			</ul>
      		</div>
      	</div>
      	<div>
      		<div>
      		<ul>
      				<li><span id="span3">3</span></li>
      				<li><input type="button" id='btn' value="获取我的位置" /></li>
      		</ul>
      		</div>
      	</div>
      </div>
    	</body>
    </html>
    

    页面创建好了我们来测试一下

    document.getElementById('btn').addEventListener('click',function(){
    	var path=Interpreter(this);
    	console.log(path.join('>'));
    })
    

    好了现在我们通过解释器就能很轻易地获取元素在文档中的位置了

    总结

    解释器即是对客户提出的需求,经过解析而形成的一个抽象解释程序。而是否可以应用解释器模式的一条重要准则是能否更根据需求解析出一套完整的语法规则,无论语法规则简单或是复杂都是必须的。因为解释器要按照这套规则才能实现相应的功能。

    也谢谢大家看到这里:)如果你觉得我的分享还可以请点击推荐,分享给你的朋友让我们一起进步~

    好了以上就是本次分享的全部内容,本次示例参考自JavaScript设计模式一书,让我们一点点积累一点点成长,希望对大家有所帮助。

    欢迎转载,转载请注明作者,原文出处。

  • 相关阅读:
    2020软件工程作业02
    2020软件工程作业01
    为什么需要平衡二叉树?
    手机号码和邮箱等联系地址,为什么不明文显示?
    请把重要的事看轻 ——2017年终总结
    万事皆空:随缘而定
    微服务:微服务架构模式译文说明
    Mysql 查询—按位运算
    解决:spring security 登录页停留时间过长 跳转至 403页面
    excel模板解析—桥接模式:分离解析模板和业务校验
  • 原文地址:https://www.cnblogs.com/chen-jie/p/Javascript-Interpreter.html
Copyright © 2011-2022 走看看