ps:本文前面大部分是错的,后边大部分也是错的,搞混了不要怪我。。。。。。。。。。。。。。。。。。。

这篇文章讲述了一个悲伤的故事,从一个似似而非的概念一步一步到错误的理解,最后勉强正确的过程

其实我本不想说我对scope的理解,因为我没写过c++,没看过脚本引擎规范,没看过js脚本引擎实现,说的也都是乱七八糟看到的加我自己猜测的,首先看一块js代码,因为这真是一块代码

<script type="application/javascript">
var a='topscope';
function makescope()
{
console.log(a);
var a='some scope';
console.log(a);
}
makescope();
console.log(a);
</script>

在看看输出

undefined

some scope

topscope

这是怎么回事呢?为什么会是undefined

1:很久以前我发现这个怪物时候,我也不懂,但是我可以规避,那就是把var 放在第一行

2:后来我学习了python,接触了第一门动态脚本语言,知道了脚本语言基本分为解析和执行两个过程,对这个现象就进一步“异想天开”的解释了下,让自己更容易接受

在全局语法扫描阶段,全局a声明了,但是没有复制,函数makescope声明了,但是内部还未进行扫描

在全局执行阶段,先给 全局a进行赋值,在执行makescope 时,

先进行makescope语法扫描,扫描时候发现了var 声明的局部变量a,但没有进行赋值

makescope语法扫描 完成后一行一行的执行,发现a已经在函数作用域内进行了定义但是没有赋值,所以值为undefined

在执行makescope 后,离开了makescope的作用域输出a值,a是全局的所以为topscope

3:再后来,我知道了js执行时候是单线程的栈运行时,那这些scope就进一步有了想象空间了

什么是栈,我也不知道,每次用的时候谷歌下

http://zh.wikipedia.org/zh-cn/%E5%A0%86%E6%A0%88

打开太慢了 还是百度下

http://baike.baidu.com/link?url=B2MYX6pxno5uC9df1t3oK6sAQdOUrLHa8vbp51Q8CAkf_LkcQOhExMpytIhwvWAp

在计算机领域,堆栈是一个不容忽视的概念,堆栈是两种数据结构。堆栈都是一种数据项按序排列的数据结构,只能在一端(称为栈顶(top))对数据项进行插入和删除。要点:堆,顺序随意。栈,后进先出(Last-In/First-Out)

栈 有个特点 后进先出,so 我们再看看看刚才的一块js的作用域

首先在 全局扫描结束后创建 父作用域 P

假设作用域p是个js对象 例如 p={}

p里面应该存储什么呢?扫描倒啥就存储啥呗,应该是 p.a,p.makescope

当执行makescope 的时候,因为改函数有自己的作用域,所以得进入makescope的作用域,

那么 p应该进入jslstack了,jslstack.push(P) 操作,由于js是单线程的,不能两个作用域同时跑,so p一定要进入stack

执行makescope 创建的作用域 假设为 s, s={}

在扫描阶段创建了那些属于s的对象呢?   因为有个var 所以 s.a 被创建了,

在  执行  console.log(a); 的时候由于还没有被赋值,所以a为undefined ,

这里我把代码改一下,增加点小东西,让实验数据更有意思

<script type="application/javascript">
var a='topscope';
function makescope()
{
console.log(a);
var a='some scope';
console.log(a);
var b='b';
Grandson();

}

function Grandson(){ console.log("a:"+a); console.log("b:"+b); }

makescope();
console.log(a);
</script>

在看下输出数据

在刚才的代码里面增加了一个函数 Grandson() 并在makescope 函数内部进行调用 因为要进入Grandson所以makescope 的作用域要进行

这个时候开始执行Grandson, 输出结果里面 a的值为topscope,b is not defined

这是为啥呢?

为什么没有去makescope 去找呢?

其实我也不太了解,难道js的 栈结构是坑爹的?

没关系 代码再改一改还是 可以运行正确的

经过试验发现刚才想的是错的

<script type="application/javascript">
var a='topscope';
function makescope()
{
console.log(a);
var a='some scope';
console.log(a);
var b='b';
Grandson();

function Grandson(){ console.log("a in:"+a); console.log("b in:"+b); }

    }
function Grandson(){
console.log("a:"+a);
console.log("b:"+b);
}
makescope();
console.log(a);
Grandson();
</script>

再看看输出

这说明啥了呢?好像扯了半天和刚才说的js 栈结构没什么关系………….貌似的确是没 关系

不过还是说明了写问题

1 js 在语法扫面阶段会扫描全部 需要扫描的东西 一般都是var 和 function,从而形成一个语法树…………ps我是这么称呼的

2 js 的每一个作用域在编码阶段已经定义完毕,在扫描阶段称为语法树 上的一个节点,

[[scope]]是静态的, 在编码函数定义时就确定下来了,[[scope]] 节点组成 的[[scope]] 树 也是静态的

3 平时说的变量在当前作用域下没找到,就到父亲的作用域去找,这个作用域是在编码阶段就可以看到的

4 那这运行时作用域和js栈结构有关系吗?

这是这个例子的 各个作用域组成 树状结构  这个树结构,在扫描阶段生成,并且每个作用域内,查找本级作用域内的变量,

没有找到的时候,只能向上查找,而不能向下查找,

为啥只能向上不能向下呢? 我觉得这是 js 栈 结构运行时决定的

现在这个树是扫描时候生成的,运行时候是按照栈进行访问的(我猜测是按照 栈结构对作用域进行执行和访问的)

因为js 的 栈 运行时,以一个一个的作用域为单元,他在处理当前作用域节点的时候,如果改作用域内部的数据处理了一部分,还没有处理完如果这个时候进入新的函数作用域,那么就要吧当前则个作用域存储起来,进行压栈操作,这个作用域的数据也将得到保存,进而可以处理新进入的作用域例如这里的

Grandson (makescope 内部的 )如果Grandson 处理完了,那么就取出刚才存储的makescope作用域继续进行处理

so js 栈 的单个节点是 scope

==============================================================================================

说道这里忽然发现一次生成一个很大的作用域树还是很浪费资源的,所以,一般大家都用函数表达式创建函数,因为函数表达式是在执行时候才执行的,扫描阶段不执行,因此,加快了扫描阶段的速度

===================================================================================================

还有闭包是在扫描阶段就定义好的呢还是在执行阶段定义好了?闭包的作用域有没有在扫描后生成的树上

这个还需要实验数据看看

代码1

<script>
var topone='topone'
function makesacpe(){
var topone='sacpeone'
function smallsacpe(){
console.log(topone)
}
//return smallsacpe
return smallsacpe2
} function smallsacpe2(){
console.log(topone)
}
makesacpe()
console.log('==')
makesacpe()(); </script>

输出

代码2

<script>
var topone='topone'
function makesacpe(){
var topone='sacpeone'
function smallsacpe(){
console.log(topone)
}
return smallsacpe
//return smallsacpe2
} function smallsacpe2(){
console.log(topone)
}
makesacpe()
console.log('==')
makesacpe()(); </script>

输出

看看代码扫描阶段形成的作用域树

1:就会发现 闭包返回的作用域 在查找值的时候,是按照生成的作用域树向上查找的

2:闭包可以保存状态是因为闭包引用了其父作用域内的值,造成阻挡了垃圾回收策略,但是这个父亲是在写代码时候就确定了的

不想说作用域scope,因为是scopeTree,的更多相关文章

  1. 聊一下JS中的作用域scope和闭包closure

    聊一下JS中的作用域scope和闭包closure scope和closure是javascript中两个非常关键的概念,前者JS用多了还比较好理解,closure就不一样了.我就被这个概念困扰了很久 ...

  2. 理解AngularJS的作用域Scope

    AngularJS中,子作用域一般都会通过JavaScript原型继承机制继承其父作用域的属性和方法.但有一个例外:在directive中使用scope: { ... },这种方式创建的作用域是一个独 ...

  3. 理解angularJS中作用域$scope

    angularJS中作用域是什么 作用域(scope)是构成angularJS应用的核心基础,在整个框架中都被广泛使用,因此了解它如何工作是非常重要的 应用的作用域是和应用的数据模型相关联的,同时作用 ...

  4. angualar入门学习-- 作用域$scope

    作用域$scope: 是ng执行环境,视图与controller之间的胶水,双向绑定的基础 $scope提供里$watch方法,监听数据模型变化 $scope提供里$apply方法,将数据模型变化更新 ...

  5. Bean的作用域scope

    Bean的作用域scope 1.singleton 单例,指一个bean容器中只存在一份 2.prototype 每次请求(每次使用)创建新的实例,destroy方式不生效 3.request 每次h ...

  6. angularJS(二):作用域$scope、控制器、过滤器

    app.controller创建控制器 一.作用域 Scope(作用域) 是应用在 HTML (视图) 和 JavaScript (控制器)之间的纽带. Scope 是一个对象,有可用的方法和属性. ...

  7. angular 指令作用域 scope

    转载自:https://segmentfault.com/a/1190000002773689 下面我们就来详细分析一下指令的作用域. 在这之前希望你对AngularJS的Directive有一定的了 ...

  8. --@angularJS--独立作用域scope绑定策略之=符策略

    1.index.html: <!DOCTYPE HTML><html ng-app="app"><head>    <title>s ...

  9. Spring-bean作用域scope详解

    Spring Framework支持五种作用域(其中有三种只能用在基于web的Spring ApplicationContext). singleton 在每个Spring IoC容器中一个bean定 ...

随机推荐

  1. shell的一些应用场景

    列出每个IP的连接数 netstat -n | awk '/^tcp/{print $5}' | awk -F: '!/^::/{print $1}' | sort | uniq -c | sort ...

  2. 微信"流量红包"的玩法攻略 广东移动用户有福啦

    前面我们说了广东移动联合微信正式推出流量红包业务,移动终于hold不住了,想要借此挽回一些些损失.只可惜,现在只是广东小范围测试,其他地区的用户暂时还没有这等福利.那么微信"流量红包&quo ...

  3. Linux服务器,PHP的10大安全配置实践

    PHP被广泛用于各种Web开发.而当服务器端脚本配置错误时会出现各种问题.现今,大部分Web服务器是基于Linux环境下运行(比如:Ubuntu,Debian等).本文例举了十大PHP最佳安全实践方式 ...

  4. PHP如何判断一个gif图片是否为动画?

    首先想到的是用getimagesize()看看type,发现都是gif. 然后想gif动画是gif89格式的,发现文件开头是gif89,但是很多透明图片也是用的gif89格式. 看来必须分析文件的祯了 ...

  5. 【强烈推荐】利用NAT、Host-Only双虚拟网卡,实现Virtual Box中CentOS6.3联网

    问题背景: 先前都是在Virtual Box中以“网络共享”方式,让里面的Linux虚拟机Host-Only方式联网,参考如下: Virtual Box下配置Host-Only联网方式详解 但最近被公 ...

  6. vs2015安装体验

    后边出现这样的问题该怎么解决?

  7. curl发送get和post请求

    function getAction($url='') { // curl 请求一共分四步,初始化,设置属性,执行并获取结果,释放句柄 // 一.初始化 $curl = curl_init(); // ...

  8. 基于jquery fly插件实现加入购物车抛物线动画效果,jquery.fly.js

    在购物网站中,加入购物车的功能是必须的功能,有的网站在用户点击加入购物车按钮时,就会出现该商品从点击出以抛物线的动画相似加入购物车,这个功能看起来非常炫,对用户体验也有一定的提高.下面介绍基于jque ...

  9. Java四种线程池的使用

    Java通过Executors提供四种线程池,分别为:newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程.newFixe ...

  10. 【Python基础学习一】在OSX系统下搭建Python语言集成开发环境 附激活码

    Python是一门简单易学,功能强大的编程语言.它具有高效的高级数据结构和简单而有效的面向对象编程方法.Python优雅的语法和动态类型以及其解释性的性质,使它在许多领域和大多数平台成为编写脚本和快速 ...