在检查组内小伙伴提交的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元素本身。

最新文章

  1. Knockout.js随手记(1)
  2. 手势-webview与scrollView重复手势处理
  3. 数据库测试DbUnit
  4. 7 Types of Regression Techniques you should know!
  5. 基于jQuery的宽屏可左右切换的焦点图插件
  6. IPhone 设备状态、闪光灯状态
  7. 关于新feature对应的增加一个新的测试单子(QA)和文档单子(Doucmentation)的步骤
  8. linux 简单命令
  9. security Export/import
  10. unix c 10
  11. 体系结构复习2——指令级并行(分支预測和VLIW)
  12. JS 多个参数的传递
  13. redhat6.4配置yum
  14. xtream 示例介绍
  15. Jmeter-----【mac电脑】配置web浏览器的代理抓取请求
  16. Apache Hadoop 2.9.2 完全分布式部署
  17. zookeeper在windows及linux(含多节点)环境下安装及其命令使用
  18. 悲观并发 乐观并发 Entity Framework Core中的并发处理
  19. Linux:Red Hat系统的安装
  20. Confluence 6 用户目录图例 - 使用 LDAP 授权的内部目录

热门文章

  1. Kemans算法及其Python 实现
  2. Random-随机生成电话号
  3. 加密壳之ACProtect之OEP的处理
  4. Android 怎样在java/native层改动一个文件的权限(mode)与用户(owner)?
  5. 树莓派 mongodb 安装&amp;报错处理
  6. [IT学习]GIT 学习
  7. 卸载ubuntu自带openJDK,更改成自己的JDK版本
  8. Lightoj 1017 - Brush (III)
  9. uboot中关于LCD的代码分析【转】
  10. YTU 2960: 改错题--小鼠标,你要干什吗?