- 浏览: 104040 次
- 性别:
- 来自: 杭州
文章分类
最新评论
-
kuchaguangjie:
great, thanks!!!
python学习笔记之module && package -
newlifewant:
nice article! thanks for sha ...
python学习笔记之module && package -
arganzheng:
备战备荒 写道貌似第二种的单例是县城不安全的吧。使用Synch ...
单例的两种线程安全实现 -
arganzheng:
@备战备荒: 如果还不相信,这里有一篇step-by-step ...
单例的两种线程安全实现 -
arganzheng:
备战备荒 写道貌似第二种的单例是县城不安全的吧。这里有个ste ...
单例的两种线程安全实现
eval
function also gets a distinct execution context but as eval
is never normally used by javascript programmers it will not be discussed here. The specified details of execution contexts are to be found in section 10.2 of ECMA 262 (3rd edition). When an execution context is created a number of things happen in a defined order. First, in the execution context of a function, an "Activation" object is created. The activation object is another specification mechanism. It can be considered as an object because it ends up having accessible named properties, but it is not a normal object as it has no prototype (at least not a defined prototype) and it cannot be directly referenced by javascript code.
The next step in the creation of the execution context for a function call is the creation of an arguments
object, which is an array-like object with integer indexed members corresponding with the arguments passed to the function call, in order. It also has length
and callee
properties (which are not relevant to this discussion, see the spec for details). A property of the Activation object is created with the name "arguments" and a reference to the arguments
object is assigned to that property.
Next the execution context is assigned a scope. A scope consists of a list (or chain) of objects. Each function object has an internal [[scope]]
property (which we will go into more detail about shortly) that also consists of a list (or chain) of objects. The scope that is assigned to the execution context of a function call consists of the list referred to by the [[scope]]
property of the corresponding function object with the Activation object added at the front of the chain (or the top of the list).
Then the process of "variable instantiation" takes place using an object that ECMA 262 refers to as the "Variable" object. However, the Activation object is used as the Variable object (note this, it is important: they are the same object). Named properties of the Variable object are created for each of the function's formal parameters, and if arguments to the function call correspond with those parameters the values of those arguments are assigned to the properties (otherwise the assigned value is undefined
). Inner function definitions are used to create function objects which are assigned to properties of the Variable object with names that correspond to the function name used in the function declaration. The last stage of variable instantiation is to create named properties of the Variable object that correspond with all the local variables declared within the function.
The properties created on the Variable object that correspond with declared local variables are initially assigned undefined
values during variable instantiation, the actual initialisation of local variables does not happen until the evaluation of the corresponding assignment expressions during the execution of the function body code.
It is the fact that the Activation object, with its arguments
property, and the Variable object, with named properties corresponding with function local variables, are the same object, that allows the identifier arguments
to be treated as if it was a function local variable.
Finally a value is assigned for use with the this
keyword. If the value assigned refers to an object then property accessors prefixed with the this
keyword reference properties of that object. If the value assigned (internally) is null then the this
keyword will refer to the global object.
The global execution context gets some slightly different handling as it does not have arguments so it does not need a defined Activation object to refer to them. The global execution context does need a scope and its scope chain consists of exactly one object, the global object. The global execution context does go through variable instantiation, its inner functions are the normal top level function declarations that make up the bulk of javascript code. The global object is used as the Variable object, which is why globally declared functions become properties of the global object. As do globally declared variables.
The global execution context also uses a reference to the global object for the this
object.
[[scope]]
property. Function objects created with the Function
constructor always have a [[scope]]
property referring to a scope chain that only contains the global object.
Function objects created with function declarations or function expressions have the scope chain of the execution context in which they are created assigned to their internal [[scope]]
property.
Closure semantics
Closures appear to be a convenient mechanism for defining something like an inner classs, but the semantics are in fact more powerful and subtle than what an inner class offers. In particular, the properties of closures can be summarized in this manner:
- They have one implicit method (which is never specified in a closure definition) called doCall()
- A closure may be invoked via the call() method, or with a special syntax of an unnamed () invocation. Either invocation will be translated by Groovy into a call to the Closure's doCall() method.
- Closures may have 1...N arguments, which may be statically typed or untyped. The first parameter is available via an implicit untyped argument named it if no explicit arguments are named. If the caller does not specify any arguments, the first parameter (and, by extension, it) will be null.
- The developer does not have to use it for the first parameter. If they wish to use a different name, they may specify it in the parameter list.
- Closures always return a value. This may occur via either an explicit return statement, or as the value of the last statement in the closure body (e.g. an explicit return statement is optional).
- A closure may reference any variables defined within its enclosing lexical scope. Any such variable is said to be bound to the closure
- Any variables bound to a closure are available to the closure even when the closure is returned outside of the enclosing scope.
- Closures are first class objects in Groovy, and are always derived from the class Closure. Code which uses closures may reference them via untyped variables or variables typed as Closure.
- The body of a closure is not executed until it is explicitly invoked e.g. a closure is not invoked at its definition time
- A closure may be curried so that one a copy the closure is made with one or more of its parameters fixed to a constant value
this, owner, and delegate
this : as in Java, this refers to the instance of the enclosing class where a Closure is defined
owner : the enclosing object (this or a surrounding Closure)
delegate : by default the same as owner, but changeable for example in a builder or ExpandoMetaClass
Example:
class Class1 {
def closure = {
println this.class.name
println delegate.class.name
def nestedClos = {
println owner.class.name
}
nestedClos()
}
}
def clos = new Class1().closure
clos.delegate = this
clos()
/* prints:
Class1
Script1
Class1$_closure1 */
因为闭包实际上就是一个对象,所以它是可以,并且经常作为参数传递。这点有点类似于C++中的函数对象。
def list = ['a','b','c','d']
def newList = []
list.collect( newList ) {
it.toUpperCase()
}
println newList // ["A", "B", "C", "D"]
In the above example, the collect method accepts a List and a Closure argument. The same could be accomplished like so (although it is more verbose):
def list = ['a','b','c','d']
def newList = []
def clos = { it.toUpperCase() }
list.collect( newList, clos )
assert newList == ["A", "B", "C", "D"]
groovy方法调用中Closure可以并且经常作为参数传递,而为了方便编写代码,一般也是将Closure写在方法调用的最后,这个特性是Groovy的Builder构建DSL的核心(当然最核心的是方法调用invokeMethod方法)。关于Groovy的Builder构建DSL,我们将在另外一篇文章中介绍。
相关推荐
本文实例讲述了JS页面获取 session 值,作用域和闭包。分享给大家供大家参考,具体如下: Javascript获取session的值: var name= "${sessioScope.变量名}"; 注意这里面需要使用 “” 把 El 表达式给括起来,否则...
根据提供的文件内容,以下是对Go语言学习笔记的详细知识点阐述。 Go语言是Google开发的一种静态类型、编译型、并发型,并具有垃圾回收功能的编程语言。它由Robert Griesemer、Rob Pike和Ken Thompson于2007年9月...
Go语言学习笔记.pdf 共174页 Go语言学习笔记.pdf 共174页是一本关于Go语言的详细学习笔记,涵盖了Go语言的基础知识、函数、数组、Maps、Structs、接口、并发、程序结构、标准库等方面的内容。本笔记共分为三大部分...
学习笔记通常包括了基础概念、关键特性、实用技巧以及常见问题的解决方法。 【标签】"h5"、"前端"、"学习笔记"进一步明确了内容的重点。"h5"即HTML5,是前端开发的核心;"前端"意味着这些笔记涉及的是用户可见和...
7. Rust闭包:Rust学习笔记Day 23-24讲述了Rust的闭包,包括闭包的定义、闭包的使用场景、闭包的实现等。 8. Rust库和生态系统:Rust学习笔记Day 25讲述了Rust的库和生态系统,包括Rust的标准库、 THIRD-PARTY库和...
"Go语言学习笔记" Go语言学习笔记是关于Go语言基础入门篇的笔记,主要介绍Go语言基础语法、数据类型、逻辑语句等相关知识点。 语言概述 Go语言是一种开源的编程语言,能让构造简单、可靠且高效的软件变得容易。Go...
这份“Python语言学习笔记”是一份开源文档,最初发布在GitHub上,作者希望借助开放的精神将其分享出来。文档主要包含两大部分,第一部分是Python语言的基础知识,第二部分则是关于Python标准库的介绍。文档适合已经...
《王纯业的Python学习笔记》是一份专为Python初学者和进阶者设计的学习资料,旨在帮助读者全面掌握这门强大的编程语言。Python作为一门高级编程语言,因其简洁、易读的语法特性,被广泛应用于数据分析、机器学习、...
本学习笔记将深入探讨JavaScript的核心概念,包括变量、数据类型、操作符、控制流程、函数、对象、数组、原型链、闭包等,并结合实际示例,如my.js、order.js、login.js等文件,来讲解其在实际项目中的应用。...
闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现
"Python学习笔记+源码练习"是一个适合初学者的资源包,旨在帮助你从零基础开始掌握Python编程。这份资料包含了理论知识讲解和实际代码实践,使学习过程更为直观和实用。 在学习Python时,笔记是关键,它们可以帮助...
在《Groovy学习笔记》这本书中,你可能会学到如何快速入门Groovy,理解其基本语法,包括变量、控制流、类和对象的创建,以及如何利用Groovy的特性来提高开发效率。此外,书中可能还会涵盖Groovy在实际项目中的应用,...
本文档是一份详尽的Python基础学习笔记,适用于初学者,涵盖了Python编程语言的方方面面。笔记内容从基础的环境配置到面向对象的高级特性,详尽阐述了Python的核心概念和技术要点。 在Linux基础部分,笔记从终端...
本文档集合了关于Go语言的学习笔记,旨在帮助读者全面理解并掌握Go语言的核心概念、语法特性以及实际应用。 一、基础语法 Go语言的语法简洁明了,易于上手。它采用了C风格的语法,但增加了诸如类型推断(Type ...
本文实例讲述了JS学习笔记之闭包小案例。分享给大家供大家参考,具体如下: 直接上代码 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <title>Document</...
Go+学习笔记所包含的知识点涵盖了Go语言的基础知识、编程范式、数据结构、并发处理、标准库使用以及进阶话题等多个方面,详细介绍了Go语言的学习路径和应用实践。 首先,Go语言的基础部分包括变量声明、基本类型、...
以下是对"javascript入门学习笔记"的详细解读: 一、JavaScript基础 1. 变量与数据类型:JavaScript支持六种基本数据类型(字符串、数字、布尔值、null、undefined和symbol)以及一种复杂数据类型(对象)。变量...