在检查组内小伙伴提交的tabToggler插件的js代码时,发现了onclick的如下用法:

                el.onclick = function(){
//按钮样式切换
for(var i=0;i<obj.btns.length;i++){
obj.btns[i].classList.remove("current");
}
this.classList.add("current");
//内容显示切换
for(var j = 0;j<obj.divs.length;j++){
obj.divs[j].style.display = 'none';
}
obj.divs[this.index].style.display = 'block';
console.log(this.index);
}

显然这个this指向事件源对象—eventTarget,最近一直在钻研闭包和this的我,看到这里觉得非常的怪,为什么这里的this可以指向eventTarget呢,而且在书写在html标签里的事件处理函数也可以在非闭包作用域下直接访问this(指向target),如下代码:

<div id="tab1" myonclick = "console.log(this.id);console.log(this)">Tab1</div>

打印结果:

这到底怎么实现的?按照需求一步一步分析就可以了,其实onclick的事件处理函数包括了两部分:

Part 1: 来自html标签内的onclick属性内的js代码;

Part 2: 来自己js脚本里的onclick方法

需求如下:

Part 1 里的onclick字符串可以被click事件执行,而且this作用域是eventTarget

问题:js里有什么机制能执行字符串形式的js代码?如何让代码作用域指向eventTarget?

答案:eval,且eval执行本身就有作用域的概念,让代码的作用域指向eventTarget就行了。

Part 2 里的onclick方法被click事件执行内部逻辑,而且this作用域是eventTarget;

综上,我们可以用eval和指定作用域的办法来扩展一个myonclick时间了,具体实现如下:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div id="tab1" myonclick = "console.log(this.id);console.log(this)">Tab1</div>
<div id="tab2">Tab2</div>
</body>
<script>
//扩展HTMLDivElement原型
HTMLElement.prototype.clickHandle = function(){
//1.检查dom标签里有myonclick属性
var _evalClickStr = this.getAttribute( "myonclick" );
//2.检查dom有无指定myonclick方法
if( !!this.myonclick && typeof this.myonclick === "function" ){
var _clickHandle = this.myonclick;
}
var nativeEventBind = this.addEventListener || this.attachEvent;
if( !!nativeEventBind ){
nativeEventBind( 'click',(function( e ){
//执行eavl代码串
eval( _evalClickStr );
//执行myonclick事件处理函数
_clickHandle.apply( this,e );
}).bind(this) );
}
else return;
} var tab1 = document.getElementById( "tab1" );
tab1.myonclick = function(){
console.log( this.id );
};
tab1.clickHandle(); </script>
</html>

核心设计要点:扩展了HTMLElement.prototype对象,在clickHandle方法里,指定了两部分onclick代码的执行上下文为HTMLElement元素本身。

用js的eval函数模拟Web API中的onclick事件的更多相关文章

  1. JS的eval函数解密反混淆

    https://www.hhtjim.com/js-decryption-de-obfuscate-eval-function.html JS的eval函数解密反混淆

  2. Java 实现 JS的eval函数

    JS的eval 函数, 给个表达式做参数, 返回表达式的值. Java的脚本引擎可以实现这个功能. 例子:   拼接一个字符串 \uxxxx, Unicode的十六进制编码, 然后把它打印出来. 即输 ...

  3. ASP.NET Web API中的JSON和XML序列化

    ASP.NET Web API中的JSON和XML序列化 前言 阅读本文之前,您也可以到Asp.Net Web API 2 系列导航进行查看 http://www.cnblogs.com/aehyok ...

  4. 在 ASP.NET Core Web API中使用 Polly 构建弹性容错的微服务

    在 ASP.NET Core Web API中使用 Polly 构建弹性容错的微服务 https://procodeguide.com/programming/polly-in-aspnet-core ...

  5. Entity Framework 6 Recipes 2nd Edition(9-3)译->找出Web API中发生了什么变化

    9-3. 找出Web API中发生了什么变化 问题 想通过基于REST的Web API服务对数据库进行插入,删除和修改对象图,而不必为每个实体类编写单独的更新方法. 此外, 用EF6的Code Fri ...

  6. Web APi 2.0优点和特点?在Web APi中如何启动Session状态?

    前言 曾几何时,微软基于Web服务技术给出最流行的基于XML且以扩展名为.asmx结尾的Web Service,此服务在.NET Framework中风靡一时同时也被.NET业界同仁所青睐,几年后在此 ...

  7. Asp.Net Web Api中使用Swagger

    关于swagger 设计是API开发的基础.Swagger使API设计变得轻而易举,为开发人员.架构师和产品所有者提供了易于使用的工具. 官方网址:https://swagger.io/solutio ...

  8. Asp.Net MVC Web API 中Swagger教程,使用Swagger创建Web API帮助文件

    什么是Swagger? Swagger 是一个规范和完整的框架,用于生成.描述.调用和可视化 RESTful 风格的 Web 服务.总体目标是使客户端和文件系统作为服务器以同样的速度来更新.文件的方法 ...

  9. 利用查询条件对象,在Asp.net Web API中实现对业务数据的分页查询处理

    在Asp.net Web API中,对业务数据的分页查询处理是一个非常常见的接口,我们需要在查询条件对象中,定义好相应业务的查询参数,排序信息,请求记录数和每页大小信息等内容,根据这些查询信息,我们在 ...

随机推荐

  1. Python爬虫开发【第1篇】【Scrapy框架】

    Scrapy 框架介绍 Scrapy是用纯Python实现一个为了爬取网站数据.提取结构性数据而编写的应用框架. Srapy框架,用户只需要定制开发几个模块就可以轻松的实现一个爬虫,用来抓取网页内容以 ...

  2. IOS报错:Unexpected ‘@’ in program

    IOS开发中出现此错误的原因: 1.宏定义重复. 我在OC与C++混编的时候,由于C++中使用到了interface,在工程中年将interface从定义为struct,当引用此接口时候出现Unexp ...

  3. 【iOS系列】- 通知NSNotification的使用

    [iOS系列]- 通知NSNotification的使用 1:属性 通知属性: - (NSString *)name; // 通知的名称 - (id)object; // 通知发布者(是谁要发布通知) ...

  4. POI异步导入Excel兼容xsl和xlsx

    项目架构:spring+struts2+hibernate4+oracle 需求:用户导入excel文件,导入到相应的数据表中,要求提供导入模板,支持xls和xlsx文件 思路分析: 1.提供一个下载 ...

  5. HTML的高富帅

    1,前端的内容(组成部分有以下三部分) HTML                         CSS                                JS 裸体的人 穿上好看的衣服 ...

  6. Hibernate 之 Persistence

    分享自:  http://blog.csdn.net/jnqqls/article/details/8276059 在我们之前的文章已经了解到,Hibernate的汉语解释叫做冬眠,而这个冬眠我个人理 ...

  7. 设计模式-(6)适配器 (swift版)

    用来解决接口适配问题的三种模式:适配器模式,桥接模式,外观模式. 一,概念 适配器模式,将一个类的结构转换成用户希望的另一个接口,使得原本接口不兼容的类能在一起工作.换句话说,适配器模式就是链接两种不 ...

  8. Oracle常用SQL与练习

    基本 数学函数 rownum相关 分页查询 (假设每页显示10条) 不包含排序: 包含排序: 时间处理 1. to_char和to_date基本使用 eg1: eg2: 2)months_betwee ...

  9. IOS UI 设计 技术

    AutoLayout AutoLayout是一种基于约束的,描述性的布局系统. 程序员—-(cgrect)—>frame(center+bounds)    =====>   程序员—(N ...

  10. python pep8 命令规范

    命名规范:总体原则,新编代码必须按下面命名风格进行,现有库的编码尽量保持风格.1 尽量单独使用小写字母‘l’,大写字母‘O’等容易混淆的字母.2 模块命名尽量短小,使用全部小写的方式,可以使用下划线. ...