之前学习js时,有个闭包的概念没弄懂。

之前学习js时,有个闭包的概念没弄懂。

绑定

编译原理中"绑定"的概念:一个对象(或事物)与其各种属性建立起某种联系的过程称为绑定(binding),这种联系的建立,实际上就是建立了某种约束。
一个程序往往要涉及若干实体,如变量、子程序和语句等。(子程序:比如C语言函数,动态链接库)
变量的属性有名字,类型和保留其值的存储区,还有个作用域等,子程序的属性有名字、某些类型的形参和某种参数传递方式的约定等;语句的属性是与之相关的一系列动作。
若一个绑定在运行之前(即编译时)完成,且在运行时不会改变,则称为静态绑定。若一个绑定在运行时完成(此后可能在运行过程中被改变),则称为动态绑定。

JS中闭包
var add = (function () { 
var counter = 0; 
return function () {
  return counter += 1;
 }
})(); 
add(); 
add(); 
add(); 
// 计数器为 3

很显然,可以看到 1.它返回的是一个函数 2.它返回的函数把其外层函数的局部变量暴露出去了(是不是像java函数返回局部变量的引用)
MDN解释 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Closures
一个函数和对其周围状态(lexical environment,词法环境)的引用捆绑在一起(或者说函数被引用包围),这样的组合就是闭包 (closure)。也就是说,闭包让你可以在一个内层函数中访问到其外层函数的作用域
闭包很有用,因为它允许将函数与其所操作的某些数据(环境)关联起来。(java的private函数)
因此,通常你使用只有一个方法的对象的地方,都可以使用闭包(you can use a closure anywhere that you might normally use an object with only a single method.)

闭包的陷阱就是在循环中创建闭包,最终只有最后一个生效,具体上述链接有说,我当初也是遇到这个问题;如果不想使用闭包来解决此问题可以用let定义那个局部变量或者foreache来解决

MDN解析 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Closures

原因是赋值给 onfocus 的是闭包。这些闭包是由他们的函数定义和在 setupHelp 作用域中捕获的环境所组成的。这三个闭包在循环中被创建,但他们共享了同一个词法作用域,在这个作用域中存在一个变量item。这是因为变量item使用var进行声明,由于变量提升,所以具有函数作用域。当onfocus的回调执行时,item.help的值被决定。由于循环在事件触发之前早已执行完毕,变量对象item(被三个闭包所共享)已经指向了helpText的最后一项。

function showHelp(help) {
  document.getElementById('help').innerHTML = help;
}

function setupHelp() {
  var helpText = [
      {'id': 'email', 'help': 'Your e-mail address'},
      {'id': 'name', 'help': 'Your full name'},
      {'id': 'age', 'help': 'Your age (you must be over 16)'}
    ];

  for (var i = 0; i < helpText.length; i++) {
    var item = helpText[i];
    document.getElementById(item.id).onfocus = function() {
      showHelp(item.help);
    }
  }
}

setupHelp();

js变量定义基本概念:

使用var声明的变量,其作用域为该语句所在的函数内,且存在变量提升现象
使用let声明的变量,其作用域为该语句所在的代码块内,不存在变量提升
使用const声明的是常量,在后面出现的代码中不能再修改该常量的值

拓展
Java

Java 逃逸 https://www.zhihu.com/question/361639494
Java编程思想中对闭包的描述:闭包是一个可调用的对象,它记录了一些信息,这些信息来自于创建它的作用域,可以看出内部类是面向对象的闭包,因为它不仅包含外围对象的(创建内部类的作用域)的信息,还自动拥有一个指向此外围类对象的引用,在此作用域内,内部类有权操作所有的成员,包括private成员。
可以看到,这种思想,是跨语言互通的.

题外话(翻笔记…):

编译的基本过程:
词法分析 语法分析(分析树)
语义分析(大多数编译器采用中间语言来描述源程序的语义,这种中间语言往往对应某种抽象机,其结构简单,语义明确,易于翻译成二进制代码,同时也便于优化和移植)
优化 目标代码生成 符号表管理 出错处理

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值