闭包

深入浅出 JavaScript 变量、作用域和内存 v 0.5

时光怂恿深爱的人放手 提交于 2020-03-04 16:25:05
本文主要从原理入手分享变量和作用域的相关知识,最后结合本文所分享知识,再次深入了解下闭包的运行原理。 主要参考《JS高级程序设计》 《JS权威指南》 《高性能 JS》 三本书。 目录 1 变量 1.1 变量的声明 1.2 变量类型的特点 2 执行环境和作用域 3 再谈谈闭包 变量 对 JavaScript 稍微有点了解的同学都知道,JavaScript 中的 变量 与其他语言的变量有很大区别。 JS 的弱类型的特性决定了变量只是在特定时间( 生命周期 , 作用域 中)用于保存特定值的一个名字而已。 一个变量可以在生命周期内任意改变类型。(太灵活了以至于好复杂) JavaScript 变量可以用来保存两种类型的值: 基本类型值 和 引用类型值 。 变量的声明 在JavaScript 程序中,使用一个变量之前应该先声明它。变量使用 var 关键字声明的。 如果在声明的时候没有进行初始化,那么默认初始化为undefined。 重复声明和遗漏声明 使用 var 关键字重复声明变量时合法的而且无害的,如果重复声明带有初始化,那么该声明和一条普通的赋值语句没什么两样。 在非严格模式下,给未声明的变量赋值,JS 会在全局作用域中创建一个同名变量,并赋值。(这会造成很多bug,因此应该使用 var 来声明变量。) 保存引用类型值的变量我们可以为其添加、改变和删除其属性和方法 。 var

python:简单的装饰器 ^-^

隐身守侯 提交于 2020-03-03 02:48:15
今天我们讲一讲python中的装饰器。可能初次接触装饰器的同学会觉得它很难,其实也就那么一回事儿,今天就让我们会会它! 装饰器 首先它的 本质是函数 ,它的 功能是为其他函数添加附加功能 。 ps:它有两个原则: 1.不能修改被修饰的函数的代码。 2.不能更改被修饰函数的调用函数。 我所认为的装饰器其实就是: 装饰器 = 高阶函数+函数嵌套+闭包 我们先说什么是高阶函数? 当函数(符合其中任意一个): 函数接收的参数是一个函数名。 函数的返回值是一个函数名。 就是把高阶函数。 那么我们考虑当只有高阶函数时,我们能否写出一个装饰器? 现在我们只用高阶函数实现:运行foo函数时,添加功能:计算其运行时间并打印。试试看吧! # 装饰器 = 高阶函数 + 函数嵌套 + 闭包 # 先玩玩高阶函数 import time def foo ( ) : time . sleep ( 3 ) print ( '来自foo' ) def timer ( func ) : start_time = time . time ( ) func ( ) stop_time = time . time ( ) print ( '函数的运行时间是%s' % ( stop_time - start_time ) ) timer ( foo ) # 改变了函数的调用方式 import time def foo ( )

谈一谈对JavaScript闭包的理解

℡╲_俬逩灬. 提交于 2020-03-02 19:00:26
一,闭包的定义 **通俗点来说闭包就是能够读取其他函数内部变量的函数。**或者说闭包是指有权访问另一个函数作用域中的变量的这么一个函数。 由于在Javascript语言中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成定义在一个函数内部的函数”。 所以,在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。 需要理解的是,闭包存在于嵌套的内部函数中。 二,闭包产生的条件 函数嵌套----内部函数引用了外部函数的数据(变量/函数) 三,闭包的使用 下面先简单列举两个关于JavaScript中全局变量和局部变量的小Demo: 1,var count = 0; function add() { return count++; } console.log(add()); // 0 console.log(add()); // 1 console.log(add()); // 2 以上代码执行结果说明:全局变量会降低函数的独立性,每一次调用add()函数都会将全局变量count做一个修改,得到一个新的数据。 2,function add(){ var count = 0; return count++; } console.log(add()); // 0 console.log(add()); // 0 console.log(add()); // 0

JavaScript难点(1)

自闭症网瘾萝莉.ら 提交于 2020-03-02 14:55:53
1. 立即执行函数 立即执行函数,即Immediately Invoked Function Expression (IIFE),正如它的名字,就是创建函数的同时立即执行。它没有绑定任何事件,也无需等待任何异步操作: (function() { // 代码 // ... })(); function( ){…}是一个匿名函数,包围它的一对括号将其转换为一个表达式,紧跟其后的一对括号调用了这个函数。立即执行函数也可以理解为立即调用一个匿名函数。立即执行函数最常见的应用场景就是:将var变量的作用域限制于你们函数内,这样可以避免命名冲突。 2. 闭包 对于闭包(closure),当外部函数返回之后,内部函数依然可以访问外部函数的变量。 function f1() { var N = 0; // N是f1函数的局部变量 function f2() // f2是f1函数的内部函数,是闭包 { N += 1; // 内部函数f2中使用了外部函数f1中的变量N console.log(N); } return f2; } var result = f1(); result(); // 输出1 result(); // 输出2 result(); // 输出3 代码中,外部函数f1只执行了一次,变量N设为0,并将内部函数f2赋值给了变量result。由于外部函数f1已经执行完毕

一入前端深似海,从此红尘是路人系列第三弹之浅析JavaScript闭包

廉价感情. 提交于 2020-03-02 08:43:05
前言:最近由于公司项目太忙,很久没有更新博客了,加上之前就一直说要发表一篇有关闭包的博客帮助小伙伴们好好的理解一些JavaScript中的难点。所以,今天趁着国庆假期前赶紧写了去,写完国庆好好出去浪个够。 首先,必须要提的就是闭包它绝对算的上是JavaScript中的一大难点,当然也是一大重点。N多高级程序都需要或者必须用到闭包才能得以实现。参考了N篇很牛叉的对于闭包理解的文章,接下来我将陈述一下鄙人自己对于闭包的理解,希望可以帮助小伙伴们通俗切入闭包这个点。 1、变量作用域 理解闭包很重要的一点就是需要先理解JavaScript特殊的变量作用域。 而变量作用域无非两种形式,全局变量和局部变量。而在JavaScript中,所有的函数它都可以在其内部访问到全局变量。 var n = 123; function test1(){ alert(n); } test1(); //123 而在函数外部也无法读取函数内的局部变量。 function test1(){   var n=123; } test1(); alert(n); // Uncaught ReferenceError: n is not defined 当然在定义变量的时候,一定要记住加上var关键字,不然,JavaScript会默认你定义了一个全局变量。 function test1(){   n=123; } test1

Swift构造函数

谁说胖子不能爱 提交于 2020-03-02 05:30:33
1. 构造函数: 给属性开辟内存空间 给属性设置初始值 最终目标创建一个对象 用 init 构造函数 参数有可能不同 ( 1 ) // 定义属性使用 var 是我们开发需要的 var name : String // 可选属性 - 默认等于 nil 可以不需要在构造函数里进行初始化 title 属性没有分配内存空间 在其他地方设置值的时候才需要分配内存空间 var title : String ? //‘override’ 重写关键字 子类继承父类 需要对父类里面的方法进行扩展 就叫重写 // 调用 super init ()之前 保证子类初始化完成 // 在 swift 中 在当前工程 类都是全局共享的 不用导头文件 ( 2 )重载构造函数 函数名相同 参数名或者参数个数不同 就是重载 不仅限于构造函数 包括其他函数 // 属性名字和传入的参数一样 需要使用 self 区分 ( 3 )重写 // 如果当前类中提供了构造函数 则默认的构造函数没有了 因为默认的构造函数 init 无法给子类的属性进行初始化 2.KVC 本质: 在运行时动态向对象发送 setValue : forKey : ( 1 )可选类型的属性可以不在构造函数中初始化 ( 2 ) KVC 是 OC 特有的 age 在 swift 不兼容 基本数据类型不能使用可选类型 要进行初始化 ( 3

C#和Java的闭包-Jon谈《The Beauty of Closures》(转)

我的梦境 提交于 2020-03-02 02:48:38
原文: http://csharpindepth.com/Articles/Chapter5/Closures.aspx 第一段略。。。 大多数讲闭包的文章都是说函数式语言,因为它们往往对闭包的支持最完善。当你在使用函数式语言时,很可能已经清楚了解了什么是闭包,所以我想写一篇在经典OO语言出现的闭包有什么用处应该也是很合适的事情。这篇文章我准备讲一下C#(1、2、3)和JAVA(7以前版本)的闭包。 什么是闭包? 简单来讲,闭包允许你将一些行为封装,将它像一个对象一样传来递去,而且它依然能够访问到原来第一次声明时的上下文。这样可以使控制结构、逻辑操作等从调用细节中分离出来。访问原来上下文的能力是闭包区别一般对象的重要特征,尽管在实现上只是多了一些编译器技巧。 利用例子来观察闭包的好处(和实现)会比较容易, 下面大部份内容我会使用一个单一的例子来进行讲解。例子会有JAVA和C#(不同版本)来说明不同的实现。所有的代码可以 点这里下载 。 需求场景:过滤列表 按一定条件过滤某个列表是很常见的需求。虽然写几行代码遍历一下列表,把满足条件的元素挑出来放到新列表的“内联”方式很容易满足需求,但把判断逻辑提取出来还是比较优雅的做法。唯一的难点就是如何封装“判定一个元素是否符合条件”逻辑,闭包正好可以解决这个问题。 虽然我上面说了“过滤”这个词,但它可能会有两个截然不同的意思

理解 ARC 下的循环引用

梦想的初衷 提交于 2020-03-02 02:12:22
ARC 下的循环引用类似于日本的 B 级恐怖片。当你刚成为苹果开发者,你或许不会关心他们的存在。直到某天你的一个 app 因内存泄露而闪退,你才突然意识到他们的存在,并且发现循环引用像幽灵一样存在于代码的各个角落。年复一年,你开始学会如何处理循环引用,检测和避免它们,但是这部片子的恐怖结局还是在那里,随时可能出现。 ARC 令许多开发者(包括我)感到失望的地方之一是苹果保留了用 ARC 来进行内存管理。ARC 很不幸地没有包括一个循环引用检测器,所以很容易就会产生循环引用,因此迫使开发者在写代码的时候采取一些特别的防范措施。 循环引用一直是一些 iOS 开发者感到费解的一个问题。 网上有许多误导信息 [1] [2] ,这些文章给了错误的建议和修复方法,其方法甚至可能引发问题和导致 app 闪退。在这片文章,我想要针对这些问题解释清楚。 理论简介 内存管理可以追溯到手动内存管理(Manual Retain Release,简称 MRR)。在 MRR,开发者创建的每一个对象,需要声明其拥有权,从而保持对象存在于内存中,当对象不再需要的时候撤销拥有权释放它。MRR 通过引用计数系统实现这套拥有权体系,也就是说每个对象有个计数器,通过计数加1表明被一个对象拥有,减1表明不再持有。当计数为零,对象将被释放。由于手动管理内存实在太烦人,因此苹果推出了自动引用计数(ARC)来解放开发者

JavaScript 中的闭包

偶尔善良 提交于 2020-03-01 21:55:51
闭包 1. 闭包的概念: 闭包是一个函数的高级应用 通过建立一个不被销毁的存储空间,来在函数的外部调用和使用函数内部的数据 2. 闭包的条件: 当出现了一个不销毁的函数执行空间 在 A 函数内部,直接或间接的返回一个函数 B 被返回的函数 B 使用着 A 函数内部的数据 我们管 B 函数叫做 A 函数的闭包函数。 function funA ( ) { let a = 100 ; let b = 200 ; let c = 300 ; return function funB ( ) { // 在函数b中,引用了函数a中,定义的局部作用域变量 let abc = { str1 : a , str2 : b , str3 : c } ; // 返回值是 abc 也就是,函数a中的局部作用域变量 return abc ; } } // 在函数a外部,调用引用函数a,此时变量a1 中, 存储的是 函数b 的 内存地址 let a1 = funA ( ) ; // 调用a1,实际就是通过a1中存储的函数b的内存地址,来调用函数b // 此时a2存储的应该是函数b的返回值 abc 也就是 函数a中的局部作用域变量 let a2 = a1 ( ) ; console . log ( a2 ) ; // 最终的目的就是通过函数b的返回值,来在函数a的外部,来调用使用函数a的局部作用域变量 3.

JavaScript中的闭包问题

时光毁灭记忆、已成空白 提交于 2020-03-01 20:52:36
闭包(在函数嵌套函数时,被嵌套的函数就是一个闭包) 意义:为了在主函数体外使用主函数(内部的)局部变量 作用: 1、可以读取函数内部的变量 2、让这些变量的值始终保持在内存中。 3、增加块级作用域 一、变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域。 变量的作用域无非就是两种:全局变量和局部变量。 Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量。 例如: var n=999;   function f1(){     alert(n);   }   f1(); // 999 另一方面,在函数外部自然无法读取函数内的局部变量。 例如:   function f1(){     var n=999;   }   alert(n); // error 这里有一个地方需要注意,函数内部声明变量的时候,一定要使用var命令。如果不用的话,你实际上声明了一个全局变量! 例如:   function f1(){     n=999;   }   f1();   alert(n); // 999 二、如何从外部读取局部变量? 出于种种原因,我们有时候需要得到函数内的局部变量。但是,前面已经说过了,正常情况下,这是办不到的,只有通过变通方法才能实现。 那就是在函数的内部,再定义一个函数。 例如:   function f1(){     n=999