用js的eval函数模拟Web API中的onclick事件
在检查组内小伙伴提交的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事件的更多相关文章
- JS的eval函数解密反混淆
https://www.hhtjim.com/js-decryption-de-obfuscate-eval-function.html JS的eval函数解密反混淆
- Java 实现 JS的eval函数
JS的eval 函数, 给个表达式做参数, 返回表达式的值. Java的脚本引擎可以实现这个功能. 例子: 拼接一个字符串 \uxxxx, Unicode的十六进制编码, 然后把它打印出来. 即输 ...
- ASP.NET Web API中的JSON和XML序列化
ASP.NET Web API中的JSON和XML序列化 前言 阅读本文之前,您也可以到Asp.Net Web API 2 系列导航进行查看 http://www.cnblogs.com/aehyok ...
- 在 ASP.NET Core Web API中使用 Polly 构建弹性容错的微服务
在 ASP.NET Core Web API中使用 Polly 构建弹性容错的微服务 https://procodeguide.com/programming/polly-in-aspnet-core ...
- Entity Framework 6 Recipes 2nd Edition(9-3)译->找出Web API中发生了什么变化
9-3. 找出Web API中发生了什么变化 问题 想通过基于REST的Web API服务对数据库进行插入,删除和修改对象图,而不必为每个实体类编写单独的更新方法. 此外, 用EF6的Code Fri ...
- Web APi 2.0优点和特点?在Web APi中如何启动Session状态?
前言 曾几何时,微软基于Web服务技术给出最流行的基于XML且以扩展名为.asmx结尾的Web Service,此服务在.NET Framework中风靡一时同时也被.NET业界同仁所青睐,几年后在此 ...
- Asp.Net Web Api中使用Swagger
关于swagger 设计是API开发的基础.Swagger使API设计变得轻而易举,为开发人员.架构师和产品所有者提供了易于使用的工具. 官方网址:https://swagger.io/solutio ...
- Asp.Net MVC Web API 中Swagger教程,使用Swagger创建Web API帮助文件
什么是Swagger? Swagger 是一个规范和完整的框架,用于生成.描述.调用和可视化 RESTful 风格的 Web 服务.总体目标是使客户端和文件系统作为服务器以同样的速度来更新.文件的方法 ...
- 利用查询条件对象,在Asp.net Web API中实现对业务数据的分页查询处理
在Asp.net Web API中,对业务数据的分页查询处理是一个非常常见的接口,我们需要在查询条件对象中,定义好相应业务的查询参数,排序信息,请求记录数和每页大小信息等内容,根据这些查询信息,我们在 ...
随机推荐
- UVa 401 Palindromes(镜像回文字符串)
题意 给一个字符串 判定其是否为回文串和镜像串 回文串非常好推断 镜像串对于每个字符用数组保存它的镜像字符即可了 没有的就是空格 注意若字符串长度为奇数 中间那个字母必须是对称的才是镜 ...
- 图像处理之基础---boxfiter
http://blog.sina.com.cn/s/blog_7221228801019yg2.html DSP6000图像位移与变形典型算法 http://blog.csdn.net/anson20 ...
- Django创建数据表
Django中创建表. 用的django项目自带的sqlite数据库,创建完毕后将表注冊到jdango.admin,就能够在浏览器在管理了. 在django项目的models.py文件里: from ...
- SQLServer导出导出单表数据
1.SQLServer导出单表数据为TXT文件 数据库--任务--导出数据
- 系统队列中的Windows错误报告
- 滑动窗体的最大值(STL的应用+剑指offer)
滑动窗体的最大值 參与人数:767时间限制:1秒空间限制:32768K 通过比例:21.61% 最佳记录:0 ms|8552K(来自 ) 题目描写叙述 给定一个数组和滑动窗体的大小.找出全部滑动窗体里 ...
- 求两个list的交集和并集
两个list的并集,只需去除重复元素即可: 将两个list放入同一个set中即可: 两个list的交集: 1将其中一个list放入set, 2循环另一个list,每次向set塞值, 3判断set的总数 ...
- sphinx索引部分源码续——过程:连接到CSphSource对应的sql数据源,通过fetch row取其中一行,然后解析出field,分词,获得wordhit,最后再加入到CSphSource的Hits里
后面就是初始化一些存储结构,其中重点说下缓存出来的几个临时文件分别的作用.结尾时tmp0的存储的是被上锁的Index,有些Index正在被查询使用 故上锁.tmp1,即对应将来生成的spp文件,存储词 ...
- 377D
树形dp 就是求每个点到标记的点的最大距离 一个经典模型 有一个巧妙的方法,我们求出以这些关键点的直径,然后每个点到关键点的最大距离就是到直径两端的距离 #include<bits/stdc++ ...
- UVa 11401 Triangle Counting (计数DP)
题意:给定一个数 n,从1-n这些数中任意挑出3个数,能组成三角形的数目. 析:dp[i] 表示从1-i 个中任意挑出3个数,能组成三角形的数目. 代码如下: #pragma comment(link ...