js onclick匿名函数 一定要匿名函数吗?

javascript 匿名函数的理解(透彻版)
字体:[ ] 类型:转载 时间:
网上很多解释,我无法理解,我想知道原理。。。这篇文章应该可以透彻一点
代码如下: (function(){ //这里忽略jQuery所有实现 })(); (function(){ //这里忽略jQuery所有实现 })();
  半年前初次接触jQuery的时候,我也像其他人一样很兴奋地想看看源码是什么样的。然而,在看到源码的第一眼,我就迷糊了。为什么只有一个匿 名函数又没看到运行(当然是运行了……),就能有jQuery这么个函数库了?于是,我抱着疑问来到CSDN。结果相信现在很多人都很清楚了(因为在我之 后也不乏来者,呵呵~)。当一个匿名函数被括起来,然后再在后面加一个括号,这个匿名函数就能立即运行起来!真神奇哦!   嘿嘿!胡闹到此为止。在这一节,我们碰到的jQuery片段是一组立即运行的匿名函数。而这种用法在论坛上也曾引起过激辩——这段代码究竟属不 属于闭包呢?带着这个疑问,我们从基础开始,分析每个关键要素,寻找属于自己的答案。(没错,自己的答案!在我看来,所有理论只是形式,只要它有利于我们 的应用实现,就是可取的——黑猫白猫,抓到老鼠的就是好猫!)   要说匿名函数,我们首先要由函数本身说起。函数的定义如下: 函数是将唯一的输出值赋予给每一输入的“法则”。   当然,这只是数学上的定义。但是,在计算机编程语言中,函数的定义也八九不离十。因为,我们都知道,计算机中的函数,也类似数学定义中的描述,它是将输入的若干数据,经过代码设定的逻辑操作处理后,返回唯一的输出的一组代码组合块。——当然,特例是,输入的数据为空或输出的数据为空,或者两者都为空。   下面,我们先初步了解一下和匿名函数相关的概念。 函数声明(function 语句)   要使用一个函数,我们就得首先声明它的存在。而我们最常用的方式就是使用function语句来定义一个函数,如:
代码如下: function abc(){ // code to process } function abc(){ // code to process }   当然,你的函数也可以是带参数的,甚至是带返回值的。 view plaincopy to clipboardprint? function abc(x,y){ return x+y; } function abc(x,y){ return x+y; }
  但是,无论你怎么去定义你的函数,JS解释器都会把它翻译成一个Function对象。例如,你在定义上面的其中一个例子的函数号,再输入如下代码: alert(typeof abc);// "function"   你的浏览器就会弹出提示框,提示你abc是一个Function对象。那么Function对象究竟是什么呢? Function 对象   Function对象是JavaScript里面的固有对象,所有的函数实际上都是一个Function对象。关于这个方面的讨论,我们留到下一个专题节。我们先看看,Function对象能不能直接运用构造函数创建一个新的函数呢?答案是肯定的。例如:
代码如下: var abc = new Function("x","y","return x*y;"); alert(abc(2,3)); // "6" var abc = new Function("x","y","return x*y;"); alert(abc(2,3)); // "6"
  相信大家现在对如何声明一个函数应该是有所了解了。那么什么才是匿名函数呢? 声明匿名函数   顾名思义,匿名函数就是没有实际名字的函数。例如,我们把上面的例子中,函数的名字去掉,再判断一下他是不是一个函数:
代码如下: alert(typeof function(){});// "function" alert(typeof function(x,y){return x+y;});// "function" alert(typeof new Function("x","y","return x*y;"))// "function" alert(typeof function(){});// "function" alert(typeof function(x,y){return x+y;});// "function" alert(typeof new Function("x","y","return x*y;"))// "function"
  我们可以很容易地看到,它们全都是Function对象,换言之,他们都是函数,但是他们都有一个特点——没有名字。所以我们把他们称作“匿名函数”。然而,正因为他们没有“名字”,我们也没有办法找到他们。这就引申了如何去调用一个匿名函数的问题了。 匿名函数的调用   要调用一个函数,我们必须要有方法定位它,引用它。所以,我们会需要帮它找一个名字。例如:
代码如下: var abc=function(x,y){ return x+y; } alert(abc(2,3)); // "5" var abc=function(x,y){ return x+y; } alert(abc(2,3)); // "5"
  上面的操作其实就等于换个方式去定义函数,这种用法是我们比较频繁遇到的。例如我们在设定一个DOM元素事件处理函数的时候,我们通常都不会为他们定名字,而是赋予它的对应事件引用一个匿名函数。   对匿名函数的调用其实还有一种做法,也就是我们看到的jQuery片段——使用()将匿名函数括起来,然后后面再加一对小括号(包含参数列表)。我们再看一下以下例子:
代码如下: alert((function(x,y){return x+y;})(2,3));// "5" alert((new Function("x","y","return x*y;"))(2,3));// "6" alert((function(x,y){return x+y;})(2,3));// "5" alert((new Function("x","y","return x*y;"))(2,3));// "6"
  很多人或许会奇怪,为什么这种方法能成功调用呢?觉得这个应用奇怪的人就看一下我以下这段解释吧。   大家知道小括号的作用吗?小括号能把我们的表达式组合分块,并且每一块,也就是每一对小括号,都有一个返回值。这个返回值实际上也就是小括号中表达式的返回值。所以,当我们用一对小括号把匿名函数括起来的时候,实际上小括号对返回的,就是一个匿名函数的Function对象。因此,小括号对加上匿名函数就如同有名字的函数般被我们取得它的引用位置了。所以如果在这个引用变量后面再加上参数列表,就会实现普通函数的调用形式。   不知道以上的文字表述大家能不能看明白,如果还是理解不了的话,再看一下以下的代码试试吧。
代码如下: var abc=function(x,y){return x+y;};// 把匿名函数对象赋给abc // abc的constructor就和匿名函数的constructor一样了。也就是说,两个函数的实现是一样的。 alert((abc).constructor==(function(x,y){return x+y;}).constructor); var abc=function(x,y){return x+y;};// 把匿名函数对象赋给abc // abc的constructor就和匿名函数的constructor一样了。也就是说,两个函数的实现是一样的。 alert((abc).constructor==(function(x,y){return x+y;}).constructor);
  PS:constructor是指创建对象的函数。也就是函数对象所代表的函数体。   总之,将其(被小括号包含的匿名函数)理解为括号表达式返回的函数对象,然后就可以对这个函数对象作正常的参数列表调用了。(前面这里犯了个错 误,只有函数表达式还是不能直接调用函数的,去掉匿名函数括号必须要伴随将表达式赋值。也就是(function(){alert(1)})()应该是与 a=function(){alert(1)}()等价,不能连a=都去掉。) 闭包   闭包是什么?闭包是指某种程序语言中的代码块允许一级函数存在并且在一级函数中所定义的自由变量能不被释放,直到一级函数被释放前,一级函数外也能应用这些未释放的自由变量。   怎样?看得一头冒汗吧……没事,我也是(虽然是我是了解的,只是表达能力的问题)。让我们换个更加简单的方法说明:闭包,其实是一种语言特性,它是指的是程序设计语言中,允许将函数看作对象,然后能像在对象中的操作搬在函数中定义实例(局部)变量,而这些变量能在函数中保存到函数的实例对象销毁为止,其它代码块能通过某种方式获取这些实例(局部)变量的值并进行应用扩展。   不知道这么再解释后会否更加清晰,如果还是不明白,那么我们再简化一下:闭包,其实就是指程序语言中能让代码调用已运行的函数中所定义的局部变量。   现在我们看一个例子:
代码如下: var abc=function(y){ var x=y;// 这个是局部变量 return function(){ alert(x++);// 就是这里调用了闭包特性中的一级函数局部变量的x,并对它进行操作 alert(y--);// 引用的参数变量也是自由变量 }}(5);// 初始化 abc();// "5" "5" abc();// "6" "4" abc();// "7" "3" alert(x);// 报错!“x”未定义! var abc=function(y){ var x=y;// 这个是局部变量 return function(){ alert(x++);// 就是这里调用了闭包特性中的一级函数局部变量的x,并对它进行操作 alert(y--);// 引用的参数变量也是自由变量 }}(5);// 初始化 abc();// "5" "5" abc();// "6" "4" abc();// "7" "3" alert(x);// 报错!“x”未定义!
  看到这里,你能判断究竟jQuery的那个代码片段是否闭包了吗?   以我的理解来说吧。是否应用了闭包特性,必须确定该段代码有没有 最重要的要素:未销毁的局部变量。那么很显然,没有任何实现的匿名函数不可能应用了闭包特性。但如果匿名函数里面有实现呢?那也还得确定它的实现中有没有 用到那些未销毁的局部变量。所以如果问你那个开篇中的jQuery代码片段是应用了JS里的什么特性?那么它只是匿名函数与匿名函数的调用而已。但是,它 隐含了闭包的特性,并且随时可以实现闭包应用。因为JS天生就是有这个特性的!(这只是我的理解,我也想知道你的理解,欢迎交流!关于闭包,有机会还是独立再开一个专题吧!)
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具js中的匿名函数和闭包总结篇 - CSDN博客
js中的匿名函数和闭包总结篇
匿名函数就是没有名字的函数,闭包是可访问一个函数作用域里变量的函数。
一.匿名函数
function box() {
return 'Lee';
function () {
return 'Lee';
(function () {
alert('Lee');
(function (age) {
alert(age);
var box = function () {
return 'Lee';
alert(box());
function box () {
return function () {
return 'Lee';
alert(box()());
闭包是指有权访问另一个函数作用域中的变量的函数,创建闭包的常见的方式,就是在一个函数内部创建另一个函数,通过另一个函数访问这个函数的局部变量。
function box() {
var user = 'Lee';
return function () {
alert(box()());
var b = box();
alert(b());
使用闭包有一个优点,也是它的缺点:就是可以把局部变量驻留在内存中,可以避免使用全局变量。(全局变量污染导致应用程序不可预测性,每个模块都可调用必将引来灾难,所以推荐使用私有的,封装的局部变量)。
var age = 100;
function box() {
alert(age);
function box() {
var age = 100;
alert(box());
alert(box());
function box() {
var age = 100;
return function () {
var b = box();
alert(b());
alert(b());
PS:由于闭包里作用域返回的局部变量资源不会被立刻销毁回收,所以可能会占用更多的内存。过度使用闭包会导致性能下降,建议在非常有必要的时候才使用闭包。
作用域链的机制导致一个问题,在循环中里的匿名函数取得的任何变量都是最后一个值。
//循环里包含匿名函数
function box() {
var arr = [];
for (var i = 0; i & 5; i++) {
arr[i] = function () {
var b = box();
alert(b.length);
for (var i = 0; i & b. i++) {
alert(b[i]());
上面的例子输出的结果都是5,也就是循环后得到的最大的i值。因为b[i]调用的是匿名函数,匿名函数并没有自我执行,等到调用的时候,box()已执行完毕,i早已变成5,所以最终的结果就是5个5。
function box() {
var arr = [];
for (var i = 0; i & 5; i++) {
arr[i] = (function (num) {
var b = box();
for (var i = 0; i & b. i++) {
alert(b[i]);
改1中,我们让匿名函数进行自我执行,导致最终返回给a[i]的是数组而不是函数了。最终导致b[0]-b[4]中保留了0,1,2,3,4的值。
function box() {
var arr = [];
for (var i = 0; i & 5; i++) {
arr[i] = (function (num) {
return function () {
var b = box();
for (var i = 0; i & b. i++) {
alert(b[i]());
改1和改2中,我们通过匿名函数自我执行,立即把结果赋值给a[i]。每一个i,是调用方通过按值传递的,所以最终返回的都是指定的递增的i。而不是box()函数里的i。
由于IE的JScript对象和DOM对象使用不同的垃圾收集方式,因此闭包在IE中会导致一些问题。就是内存泄漏的问题,也就是无法销毁驻留在内存中的元素。
function box() {
var oDiv = document.getElementById('oDiv');
oDiv.onclick = function () {
alert(oDiv.innerHTML);
那么在最后应该将oDiv解除引用来避免内存泄漏。
function box() {
var oDiv = document.getElementById('oDiv');
var text = oDiv.innerHTML;
oDiv.onclick = function () {
alert(text);
oDiv = null;
PS:如果并没有使用解除引用,那么需要等到浏览器关闭才得以释放。
模仿块级作用域(私有作用域)
JavaScript没有块级作用域的概念。
function box(count) {
for (var i=0; i& i++) {}
function box(count) {
for (var i=0; i& i++) {}
以上两个例子,说明JavaScript没有块级语句的作用域,if () {} for () {}等没有作用域,如果有,出了这个范围i就应该被销毁了。就算重新声明同一个变量也不会改变它的值。
JavaScript不会提醒你是否多次声明了同一个变量;遇到这种情况,它只会对后续的声明视而不见(如果初始化了,当然还会执行的)。使用模仿块级作用域可避免这个问题。
(function () {
function box(count) {
(function () {
for (var i = 0; i& i++) {}
使用了块级作用域(私有作用域)后,匿名函数中定义的任何变量,都会在执行结束时被销毁。这种技术经常在全局作用域中被用在函数外部,从而限制向全局作用域中添加过多的变量和函数。一般来说,我们都应该尽可能少向全局作用域中添加变量和函数。在大型项目中,多人开发的时候,过多的全局变量和函数很容易导致命名冲突,引起灾难性的后果。如果采用块级作用域(私有作用域),每个开发者既可以使用自己的变量,又不必担心搞乱全局作用域。
(function () {
var box = [1,2,3,4]
alert(box)
在全局作用域中使用块级作用域可以减少闭包占用的内存问题,因为没有指向匿名函数的引用。只要函数执行完毕,就可以立即销毁其作用域链了。
JavaScript没有私有属性的概念;所有的对象属性都是公有的。不过,却有一个私有变量的概念。任何在函数中定义的变量,都可以认为是私有变量,因为不能在函数的外部访问这些变量。
function box() {
var age = 100;
而通过函数内部创建一个闭包,那么闭包通过自己的作用域链也可以访问这些变量。而利用这一点,可以创建用于访问私有变量的公有方法。
function Box() {
var age = 100;
function run() {
return '运行中...';
this.get = function () {
return age + run();
var box = new Box();
alert(box.get());
可以通过构造方法传参来访问私有变量。
function Person(value) {
var user =
this.getUser = function () {
this.setUser = function (value) {
但是对象的方法,在多次调用的时候,会多次创建。可以使用静态私有变量来避免这个问题。
静态私有变量
通过块级作用域(私有作用域)中定义私有变量或函数,同样可以创建对外公共的特权方法。
(function () {
var age = 100;
function run() {
return '运行中...';
Box = function () {};
Box.prototype.go = function () {
return age + run();
var box = new Box();
alert(box.go());
上面的对象声明,采用的是Box = function () {} 而不是function Box() {} 因为如果用后面这种,就变成私有函数了,无法在全局访问到了,所以使用了前面这种。
(function () {
var user = ''
Person = function (value) {
user = value
Person.prototype.getUser = function () {
return user
Person.prototype.setUser = function (value) {
user = value
使用了prototype导致方法共享了,而user也就变成静态属性了。所谓静态属性,即共享于不同对象中的属性。
之前采用的都是构造函数的方式来创建私有变量和特权方法。那么对象字面量方式就采用模块模式来创建。
var box = {
age : 100,
run : function () {
return '运行中...';
var box = function () {
var age = 100;
function run() {
return '运行中...';
go : function () {
return age + run();
上面的直接返回对象的例子,也可以这么写:
var box = function () {
var age = 100;
function run() {
return '运行中...';
go : function () {
return age + run();
字面量的对象声明,其实在设计模式中可以看作是一种单例模式,所谓单例模式,就是永远保持对象的一个实例。
增强的模块模式,这种模式适合返回自定义对象,也就是构造函数。
function Desk() {};
var box = function () {
var age = 100;
function run() {
return '运行中...';
var desk = new Desk();
desk.go = function () {
return age + run();
alert(box.go());
本文已收录于以下专栏:
相关文章推荐
javascript匿名函数的理解,js括号中括function 如(function(){})
(function(){
//这里忽略jQuery所有实现
匿名函数是指没有指定函数名称的函数,先来看下面的例子:想想看结果是什么?var a = function(t) { }
(1 + 2).toString();
alert(a); ...
这部分之所以会放在一起整理,是因为匿名函数和闭包的概念很容易混淆,经常会用错。闭包是JavaScript的一个难点,也是它的一个特色,很多高级应用都要通过闭包实现,正确的理解和使用闭包是很重要的。闭包...
看到这样一段js代码, 是不明白的, 于是上网找相关资料, 这是匿名函数的一种写法!function($){
... code ...
}(jquery)(function($){
var a = function(b){
var a = 5;
alert('init');
return function(c){
alert((++a)+c);
匿名函数的写法总结有三种:
//函数字面量:首先声明一个函数对象,然后执行它。
(function(){
//优先表达式:由于Javascript执行表达式是从...
前公司大神教我用JS闭包,一直只会用但没有理解里面的原理,今天一探究竟。首先先理解什么是匿名函数顾名思义,匿名函数就是没有实际名字的函数//经典代码
function aaa(){
【JS学习笔记】 匿名函数和闭包
今天看到js的闭包那一章,被例子搞的头大:首先是关于闭包中的自由变量:var result=[];
function foo(){
for (;i&3;i=i+1)...
下面,我们先初步了解一下和匿名函数相关的概念。
#############################################
#####################...
他的最新文章
讲师:何宇健
讲师:董岩
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)JavaScript给按钮绑定点击事件(onclick)的方法
作者:work24
字体:[ ] 类型:转载 时间:
这篇文章主要介绍了JavaScript给按钮绑定点击事件(onclick)的方法,涉及javascript绑定onclick的基本技巧,非常具有实用价值,需要的朋友可以参考下
本文实例讲述了JavaScript给按钮绑定点击事件(onclick)的方法。分享给大家供大家参考。具体分析如下:
我们可以通过设定按钮的onclick属性来给按钮绑定onclick事件
&!DOCTYPE html&
function displayDate()
document.getElementById("demo").innerHTML=Date();
&h1&My First JavaScript&/h1&
&p id="demo"&This is a paragraph.&/p&
&button type="button" onclick="displayDate()"&
Display Date&/button&
&PS:这里再为大家推荐一款关于JS事件的在线查询工具,归纳总结了JS常用的事件类型与函数功能:
javascript事件与功能说明大全:
希望本文所述对大家的javascript程序设计有所帮助
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具在 SegmentFault,解决技术问题
每个月,我们帮助 1000 万的开发者解决各种各样的技术问题。并助力他们在技术能力、职业生涯、影响力上获得提升。
一线的工程师、著名开源项目的作者们,都在这里:
获取验证码
已有账号?
问题对人有帮助,内容完整,我也想知道答案
问题没有实际价值,缺少关键内容,没有改进余地
今天在学习JS动画做一个简单的Demo时遇到一个问题&script type="text/javascript"&
window.onload = function(){
var aLi = document.getElementsByTagName("li");
for(var i =0;i&aLi.i++){
aLi[i].timer =
aLi[i].onmouseover = function(){//这里一定要使用匿名函数吗?
starMove(this,400);
aLi[i].onmouseout =function(){
starMove(this,200);
function starMove(obj,iTarget){
clearInterval(obj.timer);
obj.timer = setInterval(function(){
var speed = (iTarget-obj.offsetWidth)/8;
speed=speed&0?Math.ceil(speed):Math.floor(speed);
if(obj.offsetWidth==iTarget){
clearInterval(obj.timer);
obj.style.width=obj.offsetWidth+speed+'px';
如上段代码注释出,如果之间写成
aLi[i].onmouseover = starMove(this,400);
则没有反应出错。这里给事件的监听赋值一定要使用匿名函数的形式吗?不可以直接调用函数吗?我查了很多网上的示例,都是写在匿名函数中的
btn.onclick = function(){
alert(this.value);
btn.onclick = alert('123');
则会直接弹出一个提示框,这又是什么原因呢?
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
aLi[i].onmouseover = starMove(this,400);这是执行starMove函数,然后将函数的返回结果赋值给aLi[i].onmouseover
btn.onclick = alert('123');直接跳出一个提示框也是这个原因
绑定回调不一定要使用匿名函数,具名的也可以的绑定的时候把函数名赋值过去就好
aLi[i].onmouseover=starM
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
js初学者往往容易混淆函数申明(定义)和函数执行
创造一个函数
function foo(){}
var foo = function(){}
这是最基本的两种方法。
函数执行就是在这个函数后面加一个(),如果需要传参数,就是(a,b,c...)
现在,回到问题上。onmouseover如果是一个函数,那么在鼠标移上去的时候,会触发这个函数;否则,没有任何效果。aLi[i].onmouseover = starMove(this,400),这行代码,先执行starMove(this,400),然后将其返回值赋给aLi[i].onmouseover。因为starMove(this,400)返回值不是一个函数,所以没有任何效果。
至于函数是否需要名称,这个可有可无。但是,匿名函数没法重用。所以,如果不是一次性使用,我建议具名。代码稍作调整
// 这样做的好处是,可以把确定的参数提前传进去
aLi[i].onmouseover = starMove.bind(aLi[i],400)
function starMove(iTarget){
clearInterval(obj.timer);
obj.timer = setInterval(function(){
var speed = (iTarget-obj.offsetWidth)/8;
speed=speed&0?Math.ceil(speed):Math.floor(speed);
if(obj.offsetWidth==iTarget){
clearInterval(obj.timer);
obj.style.width=obj.offsetWidth+speed+'px';
分享到微博?
关闭理由:
删除理由:
忽略理由:
推广(招聘、广告、SEO 等)方面的内容
与已有问题重复(请编辑该提问指向已有相同问题)
答非所问,不符合答题要求
宜作评论而非答案
带有人身攻击、辱骂、仇恨等违反条款的内容
无法获得确切结果的问题
非开发直接相关的问题
非技术提问的讨论型问题
其他原因(请补充说明)
我要该,理由是:}

我要回帖

更多关于 js onclick 跳转 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信