【分享】js的事件机制应该比较诡异

凌晨4点5杀老大爷 2017-05-10 11:51:51
<!doctype html>
<html>
<script>
console.log(window.b);
test2();
function test1(a)
{
console.log("test1");
console.log(window.b);
test2();
}
function test2()
{
console.log("test2");
console.log(window.b);
}

</script>
<body>
<div id="b" onclick="test1('b')">AAAAAA</div>
<div id="c" >AAAAAA</div>
<div id="b" >BBB</div>
</body>
</html>


执行结果如下:

感觉在js的事件方法底层中将Dom的id做了一次私有变量的映射,事件方法执行完毕后就访问不要了,这是最近偶尔发现的情况,希望有大牛能给彻底科普科普,亲测主流浏览器都如此。
发现这个问题发了个博客,估计没啥人看,所以发到这里分享下。
原博客:http://blog.csdn.net/asa_jim/article/details/71516213
...全文
279 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
文盲老顾 2017-05-10
  • 打赏
  • 举报
回复
首先,js的执行顺序是按照加载顺序运行的,在对象未加载前是无法访问的 所以第一个 console.log(window.b); 时,没有 window.b 对象 其次,js 操作的内容其实是一个 html dom 对象,而所有具有id和name的html控件,会被自动初始化到全局变量中
xiaojunjor 2017-05-10
  • 打赏
  • 举报
回复
引用 14 楼 Asa_Jim 的回复:
[quote=引用 12 楼 xiaojunjor 的回复:] [quote=引用 6 楼 Asa_Jim 的回复:] [quote=引用 5 楼 xiaojunjor 的回复:] [quote=引用 4 楼 Asa_Jim 的回复:] [quote=引用 2 楼 xiaojunjor 的回复:] 楼上+1,补充补充基础知识吧
搞清楚了 onload之后确实是可以始终访问到了 window.onload= function(){ console.log("onload"); console.log(window.b); }[/quote] 推荐你找一本书看一下,通过ID获取DOM元素这不是什么标准用法,兼容性也很差 另外通过name获取也不像你随便测试几行代码那么简单 通过iframe的name获取,form的name获取,表单元素的那么获取他们都是有特殊性存在的[/quote] 欢迎推荐,巩固巩固基础知识[/quote] 这个我看的书比较少,你可以查一查,我只看了JS权威指南和head first js,权威指南挺好的,可以看一看
  • 打赏
  • 举报
回复
引用 12 楼 xiaojunjor 的回复:
[quote=引用 6 楼 Asa_Jim 的回复:] [quote=引用 5 楼 xiaojunjor 的回复:] [quote=引用 4 楼 Asa_Jim 的回复:] [quote=引用 2 楼 xiaojunjor 的回复:] 楼上+1,补充补充基础知识吧
搞清楚了 onload之后确实是可以始终访问到了 window.onload= function(){ console.log("onload"); console.log(window.b); }[/quote] 推荐你找一本书看一下,通过ID获取DOM元素这不是什么标准用法,兼容性也很差 另外通过name获取也不像你随便测试几行代码那么简单 通过iframe的name获取,form的name获取,表单元素的那么获取他们都是有特殊性存在的[/quote] 欢迎推荐,巩固巩固基础知识
  • 打赏
  • 举报
回复
引用 10 楼 superwfei 的回复:
看8楼,我有提供name的例子,针对表单的用name
我的意思是不能像id 一样直接用window["elementName"] 来访问
xiaojunjor 2017-05-10
  • 打赏
  • 举报
回复
引用 6 楼 Asa_Jim 的回复:
[quote=引用 5 楼 xiaojunjor 的回复:] [quote=引用 4 楼 Asa_Jim 的回复:] [quote=引用 2 楼 xiaojunjor 的回复:] 楼上+1,补充补充基础知识吧
搞清楚了 onload之后确实是可以始终访问到了 window.onload= function(){ console.log("onload"); console.log(window.b); }[/quote] 推荐你找一本书看一下,通过ID获取DOM元素这不是什么标准用法,兼容性也很差 另外通过name获取也不像你随便测试几行代码那么简单 通过iframe的name获取,form的name获取,表单元素的那么获取他们都是有特殊性存在的
  • 打赏
  • 举报
回复
引用 8 楼 superwfei 的回复:

<!doctype html>
<html lang="en">
 <head>
  <meta charset="UTF-8">
  <meta name="Generator" content="EditPlus®">
  <meta name="Author" content="">
  <meta name="Keywords" content="">
  <meta name="Description" content="">
  <script>
  // 在页面加载之始,浏览器加载内容时即开始构造html dom对象,window、document等都在这个过程中产生
  alert(window)
  alert(document)
  // 未加载的内容未必没有对象,比如document.title在初始之始就已经构造出来,但是空值
  alert(document.title)
  </script>
  <title>Document</title>
  <script>
  // 当页面上部分特殊标签加载后,对应的html dom则进行赋值
  alert(document.title)
  </script>
 </head>
 <body>
  <script>
  // id 为 frm1 的控件未加载
  alert(window['frm1'])
  alert(document.forms.length)
  </script>
  <form id="frm1">
  <script>
  // id 为 frm1 的控件已加载
  // 且该控件类型为 form ,追加到 document.forms 中
  alert(window['frm1'])
  alert(document.forms.length)
  // frm1 表单中没有加载任何表单控件,长度为0
  alert(document.forms[0].elements.length)
  </script>
  <input type="radio" name="rdo" id="rdo1" />
  <script>
  // 表单内容根据 name 更新至 document.forms 中
  alert(document.forms[0].elements.length)
  alert(document.forms[0].elements['rdo'])
  </script>
  <input type="radio" name="rdo" id="rdo2" />
  <script>
  // 表单内容根据 name 更新至 document.forms 中
  alert(document.forms[0].elements.length)
  alert(document.forms[0].elements['rdo'])
  </script>
  </form>
 </body>
</html>
没什么诡异的地方
一开始我忽略了必须在加载后才能访问到window.b的问题,我比较好奇的是可以通过window.id这种形式去访问dom,js底层必然有个地方存放每个对应的dom和dom上绑定的事件和属性的数据,了解这个机制可以更深入方便造轮子。
文盲老顾 2017-05-10
  • 打赏
  • 举报
回复
看8楼,我有提供name的例子,针对表单的用name
  • 打赏
  • 举报
回复
引用 1 楼 superwfei 的回复:
首先,js的执行顺序是按照加载顺序运行的,在对象未加载前是无法访问的 所以第一个 console.log(window.b); 时,没有 window.b 对象 其次,js 操作的内容其实是一个 html dom 对象,而所有具有id和name的html控件,会被自动初始化到全局变量中
我试了下 name =xx的dom 在window中访问不到 把window 对象 打印出来也看不到window.b
文盲老顾 2017-05-10
  • 打赏
  • 举报
回复

<!doctype html>
<html lang="en">
 <head>
  <meta charset="UTF-8">
  <meta name="Generator" content="EditPlus®">
  <meta name="Author" content="">
  <meta name="Keywords" content="">
  <meta name="Description" content="">
  <script>
  // 在页面加载之始,浏览器加载内容时即开始构造html dom对象,window、document等都在这个过程中产生
  alert(window)
  alert(document)
  // 未加载的内容未必没有对象,比如document.title在初始之始就已经构造出来,但是空值
  alert(document.title)
  </script>
  <title>Document</title>
  <script>
  // 当页面上部分特殊标签加载后,对应的html dom则进行赋值
  alert(document.title)
  </script>
 </head>
 <body>
  <script>
  // id 为 frm1 的控件未加载
  alert(window['frm1'])
  alert(document.forms.length)
  </script>
  <form id="frm1">
  <script>
  // id 为 frm1 的控件已加载
  // 且该控件类型为 form ,追加到 document.forms 中
  alert(window['frm1'])
  alert(document.forms.length)
  // frm1 表单中没有加载任何表单控件,长度为0
  alert(document.forms[0].elements.length)
  </script>
  <input type="radio" name="rdo" id="rdo1" />
  <script>
  // 表单内容根据 name 更新至 document.forms 中
  alert(document.forms[0].elements.length)
  alert(document.forms[0].elements['rdo'])
  </script>
  <input type="radio" name="rdo" id="rdo2" />
  <script>
  // 表单内容根据 name 更新至 document.forms 中
  alert(document.forms[0].elements.length)
  alert(document.forms[0].elements['rdo'])
  </script>
  </form>
 </body>
</html>
没什么诡异的地方
  • 打赏
  • 举报
回复
引用 1 楼 superwfei 的回复:
首先,js的执行顺序是按照加载顺序运行的,在对象未加载前是无法访问的 所以第一个 console.log(window.b); 时,没有 window.b 对象 其次,js 操作的内容其实是一个 html dom 对象,而所有具有id和name的html控件,会被自动初始化到全局变量中
我的例子 说明了,dom加载之后可以使用window.id 这种方式来达到document.getElementById() 的效果,如果有多个dom 是同名id,则返回的是个dom数组
  • 打赏
  • 举报
回复
引用 5 楼 xiaojunjor 的回复:
[quote=引用 4 楼 Asa_Jim 的回复:] [quote=引用 2 楼 xiaojunjor 的回复:] 楼上+1,补充补充基础知识吧
搞清楚了 onload之后确实是可以始终访问到了 window.onload= function(){ console.log("onload"); console.log(window.b); }
xiaojunjor 2017-05-10
  • 打赏
  • 举报
回复
引用 4 楼 Asa_Jim 的回复:
[quote=引用 2 楼 xiaojunjor 的回复:] 楼上+1,补充补充基础知识吧
眼高手低+1[/quote] 额。。。 不是很懂你要表达的诡异地方在哪,输出undefined和输出DOM元素的原因1#已经说了 也许是我没看明白你的问题所在
  • 打赏
  • 举报
回复
引用 2 楼 xiaojunjor 的回复:
楼上+1,补充补充基础知识吧
眼高手低+1
  • 打赏
  • 举报
回复
引用 1 楼 superwfei 的回复:
首先,js的执行顺序是按照加载顺序运行的,在对象未加载前是无法访问的 所以第一个 console.log(window.b); 时,没有 window.b 对象 其次,js 操作的内容其实是一个 html dom 对象,而所有具有id和name的html控件,会被自动初始化到全局变量中
请按照我的代码再仔细研究研究,不要妄下结论
xiaojunjor 2017-05-10
  • 打赏
  • 举报
回复
楼上+1,补充补充基础知识吧

87,993

社区成员

发帖
与我相关
我的任务
社区描述
Web 开发 JavaScript
社区管理员
  • JavaScript
  • 无·法
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧