初探内联方式的 onload="doSomething()"为何要加"()"?而js代码的 onload="doSomething" 和 addEventListener 为何不加"()"?
- 问题引入:在看《Jquery基础教程》第四版的时,P34页有这样一段话
引用函数与调用函数
这里在将函数指定为处理程序时,省略了后面的圆括号,只使用了函数名。如果带着圆括号,函数会被立即调用;没有圆括号,函数名就只是函数的标识符或函数的引用,可以用于在将来再调用函数。
这引发了我对于绑定事件方式的思考。我们都知道为元素绑定事件处理程序的时,内联方式要这样写 <body onload="doSomething();">...</body> ,或者javascript代码要这样写
window.onload=doSomething;//或下一行的方式
window.addEventListener('load',doSomething,false);
function doSomething(){
...
}
我们一直都是这样用,但是有没有思考过为什么内联方式的 onload="doSomething()" 要加"()"?我给它不加可以吗?,而js代码的 onload 和 addEventListener 为什么不加"()",我给它加上可以吗?
- 问题思考:如上面书里所说加"()"是调用函数,js代码执行到那一行时函数会被立即调用并执行。不加"()"是引用函数, window.onload 属性只是指向 doSomething 函数体(为什么说是指向而不是将简单的函数体赋值给onload属性待会验证),待将来触发了 onload事件,doSomething才会被加到任务队列等待主函数将它执行。
- 问题验证:
1.标准内联方式,控制台会如约输出"test"。
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body onload="doSomething()">
<script type="text/javascript">
function doSomething(){
console.log('test');
}
</script>
</body>
</html>
2.内联方式不加"()"
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body onload="doSomething">
<script type="text/javascript">
function doSomething(){
console.log('test');
}
</script>
</body>
</html>
结果控制台不输出也没提示出错,来打断点看看程序到底发生了什么,给主要代码每行都打上断点

然后重新运行程序,程序到第6行,暂停。

点击继续执行,程序并没有执行第9行的代码而是运行直接完毕。然后再看下 document.body.onload 属性输出是

所以这就意味着当 onload 事件触发时,去执行 function onload ,该函数内容是 doSomething 啊并不是 doSomething() ,所以 onload 事件触发后不会执行 doSomething 函数只是触发后进入 function onload 就结束了。
3.标准js绑定事件方式, window.onload 和 addEventListener 方式一样,这里用前者举例,也会如约输出"test"
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<script type="text/javascript">
window.onload=doSomething;
function doSomething(){
console.log('test');
}
</script>
</body>
</html>

4. js代码换成 doSomething() ,仍然完美输出"test"且没报错,来分析一下
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<script type="text/javascript">
window.onload=doSomething();
function doSomething(){
console.log('test');
}
</script>
</body>
</html>

第8行断点,因为还没执行所以 window.onload=null ,这没有什么疑问, window 对象本身就给这些属性赋值为 null 。继续,
.
来到了第10行断点,准备执行 console ,这时在看 window.onload 怎么还是 null ?莫慌继续看,

经过第10行断点,如约输出"test"没问题,查看 window.onload 还是 null ,直到运行完函数,最后查看 window.onload 依旧是 null ,这个时候会产生疑问是不是由于 doSomething 没有返回明显的值 window.onload 最后才会是null。测试一番

确实是这样的(注:测试过 return 1;return "str"; 都不行,只能 return 对象类型)。
这一系列测试足以说明以下代码完成的功能
window.onload=doSomething();
function doSomething(){
console.log('test');
}
其实就是调用函数并执行然后返回值赋值变量,和注册事件并没啥关系。
- 最后说说前面留的这个问题:window.onload属性只是指向doSomething函数体(为什么说是指向而不是将简单的函数体赋值给onload属性):

给 window.onclick 添加属性 b=1 , window.onchange.b 输出也是1,足以说明确实是指向而不是赋值
初探内联方式的 onload="doSomething()"为何要加"()"?而js代码的 onload="doSomething" 和 addEventListener 为何不加"()"?的更多相关文章
- C++ inline(内联什么时候使用)
(1)什么是内联函数?内联函数是指那些定义在类体内的成员函数,即该函数的函数体放在类体内. (2)为什么要引入内联函数?当然,引入内联函数的主要目的是:解决程序中函数调用的效率问题.另外,前面我们讲到 ...
- C++内联函数与宏定义
用内联取代宏: 1.内联可调试: 2.可进行类型安全检查或自动类型转换: 3.可访问成员变量. 另外,定义在类声明中的成员函数自动转化为内联函数. 文章(一) 内联函数与宏定义 在C中,常用预处理语句 ...
- C++内联函数、函数模板之于头文件
一.基本说明 C++标准中提到,一个编译单元是指一个.cpp文件以及它所include的所有.h文件,.h文件里的代码将会被扩展到包含它的.cpp文件里,然后编译器编译该.cpp文件为一个.obj文件 ...
- C++中的内联函数和C中的宏定义的区别
在C++中内联函数: 内联函数即是在函数的声明和和定义前面加上“inline”关键字,内联函数和常规函数一样,都是按照值来传递参数的,如果参数为表达式,如4.5+7.5,则函数将传递表达式的值(这里为 ...
- CSS 的三种样式 内联 内部 外部
CSS:层叠样式表的缩写 就是 Cascading Style Sheets Cascading Style Sheets : 层叠样式表 优先级问题 :遵守就近原则 内联> 内部>外部 ...
- spring boot 与 thymeleaf (3): 设置属性、条件、遍历、局部变量、优先级、内联语法
前面记录了 thymeleaf 基本表达式, 这里继续看一下其他功能. 一. 设置属性值 这里的controller, html框架 还是沿用上一篇的部分. html: <div class=& ...
- C/C++之宏、内联函数和普通函数的区别
内联函数的执行过程与带参数宏定义很相似,但参数的处理不同.带参数的宏定义并不对参数进行运算,而是直接替换:内联函数首先是函数,这就意味着函数的很多性质都适用于内联函数,即内联函数先把参数表达式进行运算 ...
- c++ 内联函数 (讲解的TM真好)
1. 内联函数 在C++中我们通常定义以下函数来求两个整数的最大值: 复制代码 代码如下: int max(int a, int b) { return a > b ? a : b; } 为 ...
- __inline定义的内联函数和宏的区别
转自:http://blog.csdn.net/lw370481/article/details/7311668 函数与宏 #define TABLE_COMP(x) ((x)>0?(x):0) ...
随机推荐
- Circle-Progress-View
https://github.com/jakob-grabner/Circle-Progress-View
- JAVA学习第五十七课 — IO流(十一)
一.管道流 PipedInputStream 和 PipedOutPutStream 输入和输出能够直接进行连接.结合线程使用 管道流,顾名思义,写一个读一个.连成一个管子 API文档:管道输入流应该 ...
- ACM-经典DP之Monkey and Banana——hdu1069
***************************************转载请注明出处:http://blog.csdn.net/lttree************************** ...
- VS2012无法安装cocos2d-x-2.1.4 解决方法及VS2012新建coco2d-x项目(一)
转自:http://www.cnblogs.com/wangpei/admin/EditPosts.aspx?opt=1 (注:此方法是可行,仅供参考,建议大家直接看我的 一见命令解决vs安装并创建c ...
- jQuery刷新div内容,并对刷新后元素绑定事件。$(document).on()
给id=zt的元素绑定点击事件 点击刷新id=ps_list中类容(内容中含有id=zt元素) 把zt的点击事件委托到了document上,这样就不用考虑事件是否能绑定到新加元素上 代码如下: $(d ...
- WPF之复杂形状控件
有的时候想将一张图片变成一个按钮.当然这里不是单纯讲图片作为按钮的背景. 这两者是有区别的: 前者图片即按钮,比如你有一个空心的圆圈,当你点击中间空心部分的时候是没有任何反应的因为它不是属于按钮的一部 ...
- Android进阶笔记18:选用合适的IPC方式
1. 相信大家都知道Android进程间通信方式很多,比如AIDL.Messenger等等,接下来我就总结一下这些IPC方式优缺点. 2. IPC方式的优缺点和适用场景 3. 附加:使用Intent实 ...
- 阿里云 OCS SDK for NodeJS介绍
阿里云 OCS SDK for NodeJS介绍 阿里云技术团队:熊亮 阿里云 SDK for NodeJS 是为 NodeJS 开发者提供使用阿里云各项服务的统一入口,由阿里云UED团队负责开发维护 ...
- 《MFC游戏开发》笔记十 游戏中的碰撞检测进阶:地图类型&障碍物判定
本系列文章由七十一雾央编写,转载请注明出处. http://blog.csdn.net/u011371356/article/details/9394465 作者:七十一雾央 新浪微博:http:// ...
- jQuery阻止事件冒泡的例子
下面给给各位朋友稍加整理了一jquery中阻止事件冒泡的一些例子,我们知道JQuery 提供了两种方式来阻止事件冒泡,但我们简单的利用它来做一些应用可能不深入或不理解,下面整理了更详细的方法,有兴趣的 ...