• 问题引入:在看《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 为何不加"()"?的更多相关文章

  1. C++ inline(内联什么时候使用)

    (1)什么是内联函数?内联函数是指那些定义在类体内的成员函数,即该函数的函数体放在类体内. (2)为什么要引入内联函数?当然,引入内联函数的主要目的是:解决程序中函数调用的效率问题.另外,前面我们讲到 ...

  2. C++内联函数与宏定义

    用内联取代宏: 1.内联可调试: 2.可进行类型安全检查或自动类型转换: 3.可访问成员变量. 另外,定义在类声明中的成员函数自动转化为内联函数. 文章(一) 内联函数与宏定义 在C中,常用预处理语句 ...

  3. C++内联函数、函数模板之于头文件

    一.基本说明 C++标准中提到,一个编译单元是指一个.cpp文件以及它所include的所有.h文件,.h文件里的代码将会被扩展到包含它的.cpp文件里,然后编译器编译该.cpp文件为一个.obj文件 ...

  4. C++中的内联函数和C中的宏定义的区别

    在C++中内联函数: 内联函数即是在函数的声明和和定义前面加上“inline”关键字,内联函数和常规函数一样,都是按照值来传递参数的,如果参数为表达式,如4.5+7.5,则函数将传递表达式的值(这里为 ...

  5. CSS 的三种样式 内联 内部 外部

    CSS:层叠样式表的缩写 就是 Cascading Style Sheets Cascading Style Sheets : 层叠样式表 优先级问题 :遵守就近原则  内联> 内部>外部 ...

  6. spring boot 与 thymeleaf (3): 设置属性、条件、遍历、局部变量、优先级、内联语法

    前面记录了 thymeleaf 基本表达式, 这里继续看一下其他功能. 一. 设置属性值 这里的controller, html框架 还是沿用上一篇的部分. html: <div class=& ...

  7. C/C++之宏、内联函数和普通函数的区别

    内联函数的执行过程与带参数宏定义很相似,但参数的处理不同.带参数的宏定义并不对参数进行运算,而是直接替换:内联函数首先是函数,这就意味着函数的很多性质都适用于内联函数,即内联函数先把参数表达式进行运算 ...

  8. c++ 内联函数 (讲解的TM真好)

    1.  内联函数 在C++中我们通常定义以下函数来求两个整数的最大值: 复制代码 代码如下: int max(int a, int b) {  return a > b ? a : b; } 为 ...

  9. __inline定义的内联函数和宏的区别

    转自:http://blog.csdn.net/lw370481/article/details/7311668 函数与宏 #define TABLE_COMP(x) ((x)>0?(x):0) ...

随机推荐

  1. MAC下配置gradle用eclipse 打包android程序

    1.下载gradle binhttp://gradle.org/gradle-download/ 2.配置gradle,http://www.douban.com/note/311599602/htt ...

  2. 好记心不如烂笔头之jQuery学习,第一章

    jQuery对象和DOM对象的转换: 1.jquery对象是对象数组,于是乎: var $cr = $('#cr'); var cr = $cr[0]; 2.使用jquery的自带函数: var $c ...

  3. listen和accept函数

    listen函数是用来设置监听连接的句柄和队列 当listen函数执行完成以后,服务端就已经可以接受客户端来的新连接了,新连接完成以后listen会把客户端的ip,port和连接句柄放在监听队列里面, ...

  4. Linux下杀僵尸进程办法

    1) 检查当前僵尸进程信息 # ps -ef | grep defunct | grep -v grep | wc -l 175 # top | head -2 top - 15:05:54 up 9 ...

  5. oracle连接错误

    公司用的数据库,动不动会出现一些问题.但是都是大家比较常见的.所以,贴出来给大家看看1,oracle启动数据库时报错:SQL> startup;ORA-01078: failure in pro ...

  6. tar备份工具

    一.tar命令的基本格式 在UNIX.Linux系统中,有许多命令可以用于备份数据,其中最常见的命令是tar命令..tar是UNIX和Linux系统中的打包工具,可以将多个文件或目录打包(也称为归档) ...

  7. 计算机网络中的TCP/UDP协议到底是怎么回事(二)

    上一篇博客阐述了TCP/IP五层网络结构模型以及一些关于TCP.UDP的基础知识,这篇博客会接着写一些关于TCP拥塞控制的算法以及对TCP中常有的疑问进行解答. TCP拥塞控制 首先了解几个概念,为下 ...

  8. C#中的预处理器指令详解

    这篇文章主要介绍了C#中的预处理器指令详解,本文讲解了#define 和 #undef.#if.#elif.#else和#endif.#warning和#error.#region和#endregio ...

  9. KVO监听数组的变化

    #import "ViewController.h" @interface ViewController () @property(nonatomic,strong)NSMutab ...

  10. 问题集-- SQL 约束名不能重复

    今天看书整理笔记的时候,无意发现一个问题,记录下来: 前段时间做练习曾经创建过一个tbl_student的表,         create table tbl_student(            ...