`
ralphr
  • 浏览: 142976 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

js函数的几种写法 闭包概要

    博客分类:
  • web
阅读更多

最常见的:

Js代码

 

function foo() {
 alert('hi, js');
}
foo();

 

用匿名函数:

Js代码
var foo = function () {
 alert('hi, js');
}
foo();

 

改装一下,给调用的foo()加个括号:

Js代码

 

var foo = function () {
 alert('hi, js');
}
(foo)();

 

干脆,连foo的定义也省掉------把foo赋值语句的等号右边的东东、直接替换掉刚才括起来的foo:

Js代码
(function () {
 alert('hi, js');
})();

 

 

先看常用的函数:

 

function sayHello(name) {
  var text = 'Hello ' + name;
  var sayAlert = function() { alert(text); }
  sayAlert();
}
sayHello('Bob');

 

闭包的例子

 

一句话描述:

  • 闭包是函数的局部变量,在函数return之后,仍然有值, 或者
  • 闭包是stack-frame,在函数return的时候,它不会被释放。(就好像'stack-frame'是内存分配、而非处于堆栈!)

下面的代码返回一个function的引用:

 

 

function sayHello2(name) {
  var text = 'Hello ' + name; // local variable
  var sayAlert = function() { alert(text); }
  return sayAlert;
}
var say2 = sayHello2('Jane');
say2(); //hello Jane

 

 

多数JavaScript程序员能够理解上面代码的函数引用如何返回给变量。请在学习闭包之前理解它。C程序员把函数看做返回的一个函数指针,变量sayAlert和say2分别是函数指针。


C函数指针和JavaScript的函数引用有着本质的不同。在JavaScript,函数引用变量既是一个函数指针,又是一个隐藏的闭包指针。

 

上面代码拥有闭包,因为函数体内又声明了一个匿名函数 function() { alert(text); } ,参看例子中的sayHello2()。如果你在另一个函数内使用function关键字,闭包就产生了。

 

在C和其他多数语言,当函数return之后,stack-frame就被销毁了,所有的局部变量也就不能访问了。

 

在JavaScript中,如果你在函数里声明了函数,在你调用的函数renturn之后,局部变量仍然可以访问。请注意上面的例子,我们调用了变量text,它是函数sayHello2的局部变量。

 

Example 3

 

这个例子表明局部变量不是拷贝传递,而是引用传递。在外层函数退出时,它把stack-frame保存在内存。

 

 

function say667() {
  // Local variable that ends up within closure
  var num = 666;
  var sayAlert = function() { alert(num); }
  num++;
  return sayAlert;
}
var sayNumba = say667();
sayNumba(); //667,而不是666
alert(sayNumba.toString());

 

Example 4

三个函数对某个闭包使用同一个引用,因为它们均在setupSomeGlobals()里声明的。

 

var gAlertNumber = gIncreaseNumber = gSetNumber = null;
function setupSomeGlobals() {
  // Local variable that ends up within closure
  var num = 666;
  // Store some references to functions as global variables
  gAlertNumber = function() { alert(num); }
  gIncreaseNumber = function() { num++; }
  gSetNumber = function(x) { num = x; }
}
setupSomeGlobals();
//任意、多次 运行下面的函数
gAlertNumber();
gIncreaseNumber();
gSetNumber(5); //把num重新设为 5
gSetNumber(-8888); //把num重新设为 -8888

 

重新运行setupSomeGlobals(); 就会重新产生一个新的闭包。在JavaScript中,当你在函数里又声明一个函数,外部函数每调用一次,内部函数将再被重新产生一次。

 

Example 5

 

当心下面例子的循环:闭包中的局部变量可能和你最初想的不一样。

 

function buildList(list) {
  var result = [];
  for (var i = 0; i < list.length; i++) {
    var item = 'item' + list[i];
    result.push( function() {alert(item + ' ' + list[i])} );
  }
  return result;
}

function testList() {
  var fnlist = buildList([1,2,3]);
  // using j only to help prevent confusion - could use i
  for (var j = 0; j < fnlist.length; j++) {
    fnlist[j]();
  }
}

testList();  //输出3次:'item3 undefined'

 

Example 6

 

下面的例子表明,闭包包含了 在外部函数退出之前、定义的任何局部变量。注意,变量alice实际上在匿名函数之后声明的。匿名函数先被声明:当函数被调用时,它可以访问alice,因为alice在闭包里。

function sayAlice() {
  var sayAlert = function() { alert(alice); }
  // Local variable that ends up within closure
  var alice = 'Hello Alice';
  return sayAlert;
}
sayAlice()(); //Hello Alice
alert(alice); //错误:alice不是全局变量,它在函数体内var了

 

Example 7


下面的例子表明,每次调用会产生各自的闭包。

function newClosure(someNum, someRef) {
  // Local variables that end up within closure
  var num = someNum;
  var anArray = [1,2,3];
  var ref = someRef;
  return function(x) {
      num += x;
      anArray.push(num);
      alert('num: ' + num + 
          '\nanArray ' + anArray.toString() + 
          '\nref.someVar ' + ref.someVar);
    }
}
closure1 = newClosure(40, {someVar : 'closure 1'}); 
closure1(5);

closure2 = newClosure(1000, {someVar : 'closure 2'});
closure2(-10);

 

小结


读一些说明要比理解上面的例子难得多。我对于闭包的说明以及stack-frame等等在技术上可能不正确 --- 但是它们的确有助于理解

分享到:
评论

相关推荐

    JS匿名函数、闭包

    ### JS匿名函数、闭包详解 #### 一、匿名函数概览 **匿名函数**,又称**拉姆达函数**,是一种在JavaScript中常见的函数形式,这类函数没有名称,因此不能像命名函数那样通过名称来调用。匿名函数通常作为临时使用...

    求闭包 属性集闭包 函数依赖的闭包

    1. 由用户输入函数依赖,当用户输入End时,表示所有依赖都输入完毕。(即函数依赖是由用户自己定的,程序中不能假定某个具体的依赖)。 2. 函数依赖的形式是ABC, ABE这样的形式,为了简单起见,我们假定所有的属性...

    JavaScript闭包函数

    闭包是ECMAScript (JavaScript)最强大的特性之一,但用好闭包的前提是必须理解闭包。闭包的创建相对容易,人们甚至会在不经意间创建闭包,但这些无意创建的闭包却存在潜在的危害,尤其是在比较常见的浏览器环境下...

    JavaScript 匿名函数和闭包介绍

    在JavaScript中,匿名函数的声明通常采用以下几种形式: ```javascript // 匿名函数表达式赋值给变量 var box = function() { return 'Lee'; }; // 立即执行的函数表达式(IIFE) (function(name) { console.log...

    深度探讨javascript函数的原型链和闭包

    在JavaScript中,函数扮演着至关重要的角色,它们不仅仅是代码块,更是数据的一种形式。JavaScript的灵活性使得函数可以作为变量、对象的方法甚至构造函数使用。理解函数的原型链和闭包对于深入掌握JavaScript至关...

    js高级函数之闭包

    js高级中的函数之闭包函数全解与应用场景(循环闭包,定时器,面试题)

    JavaScript基础篇(6)之函数表达式闭包

    JavaScript中定义函数主要分为函数声明和函数表达式两种形式。函数声明一般会使用`function`关键字直接声明一个函数,如`function fn() {}`,而函数表达式则通常将函数作为赋值表达式的一部分,例如`var fn = ...

    js闭包写法学习demo

    JavaScript中的闭包是一种非常重要的概念,它在编程中起着至关重要的作用,特别是在函数式编程和模块化设计中。闭包本质上是函数能够记住并访问其词法作用域内变量的能力,即使该函数在其词法作用域外部被调用。在...

    (转载)JavaScript中匿名函数,函数直接量和闭包.docx

    在JavaScript中,匿名函数、函数直接量和闭包是三种非常重要的概念,它们在编程实践中有着广泛的应用。让我们逐一深入探讨这些概念。 1. **匿名函数**: 匿名函数是指没有名字的函数,通常作为表达式的一部分存在...

    JavaScript函数式编程.pdf

    JavaScript函数式编程的知识点非常丰富,涉及很多方面的内容,下面将详细介绍几个核心知识点。 1. 函数式编程基础 函数式编程(Functional Programming)是一种编程范式,它将计算视为数学函数的评估,并且避免...

    swift_函数和闭包

    在Swift中,函数和闭包是核心概念,它们允许程序员组织代码并重复使用逻辑。本篇文章将深入探讨Swift中的函数和闭包。 **函数** 函数是执行特定任务的一段可重用代码。在Swift中,你可以通过定义函数来创建自己的...

    数据库求属性集闭包&函数依赖闭包

    4) 计算函数依赖的闭包。此步骤不作要求,但要会方法。个人总结:将所有属性元素组成一个集合(域)记为R;求R的所有子集(要用到第二步中的全排列~~~),设其中一个为Ri;对每一个子集求其闭包,记为Ri+;然后求Ri...

    理解javascript函数式编程中的闭包(closure)_.docx

    闭包是一种特殊的函数,它能记住其定义时的作用域,即使在函数执行完毕后,仍然可以访问到该作用域内的变量。在JavaScript中,每个函数都具备创建闭包的能力,但通常在嵌套函数中闭包的概念更为突出。 闭包的特点...

    深入Javascript函数、递归与闭包(执行环境、变量对象与作用域链)使用详解

    本文将深入探讨JavaScript中的函数、递归和闭包,以及执行环境、变量对象与作用域链的概念。 首先,我们来看JavaScript中定义函数的两种方式:函数声明和函数表达式。函数声明是一种明确的、独立的代码结构,例如`...

    javascript笔记之匿名函数和闭包.docx

    在上述文档中,我们看到几种不同的匿名函数使用方式: 1. **匿名函数自执行**:`(function(){})()`,这种写法会立即执行该匿名函数。 2. **函数内的匿名函数**:`function() { return function(){}; }`,在这里,...

Global site tag (gtag.js) - Google Analytics