今天看到js的with语句部分,书中写到,with语句接收的对象会添加到作用域链的前端并在代码执行完之后移除。看到这里,我有两点疑问,添加到作用域链前端是不是指对象会被放置到作用域链的最底部,然后查找变量时最先查找这个对象(按照我的理解,js的作用域链查找变量的过程是一个冒泡的过程,底部开始往上走,找到了就停止冒泡),第二点就是,执行之后移除是不是指with语句之后就移除那个对象。于是写了一个简单的例子来验证一下。

var b = {a:2};

function sayA(){
var a = 1;
with(b){alert(a);}
alert(a);
} sayA();

代码运行结果是2和1。这证实了我之前的猜想,因为正常情况,位于作用域链底部的应该是函数的局部变量a,然而with语句中的a却是对象b的字段a,这证明对象b占据了作用域链中最底部的位置。而with语句之后的a的值又变成了1,说明对象b已从作用域链最底部移除。我自己认为在with语句中,这时的执行环境就是对象b,而不是函数,所以首先访问b中的a值。

我尝试在函数外直接访问a,结果当然是undefined,因为这时的执行环境应该是全局环境,而全局环境并没有这个a值,只有通过b.a才可以访问b中的a,所以可以这样说with语句其实还提供了简写访问对象字段的途径。假设b中有50个字段,你要全部访问,正常情况你要写50个b.xxx,而使用with语句只要直接写字段名就行了。

然而,我又有了一个疑问,我在with语句中创建一个变量,这个变量究竟属于谁。如果按照我的理解,这个变量应该属于对象b。

var b = {a:2};

function sayA(obj){
var a = 1;
with(b){a=5;c = 6;}
alert(c);
} sayA();
alert(b.c);
alert(b.a);

但是, 运行结果是6、undefined和5。这说明with语句中的对象并不是作为执行环境添加到作用域链中的,仅仅是作为一个变量添加到with语句所在的执行环境之中,with语句中的变量还是属于with语句所在的执行环境(这里是函数sayA),而对b的字段的改变也会真正影响到b。

总结

  • 在with语句块中,只是改变了对变量的遍历顺序,由原本的从执行环境开始变为从with语句的对象开始。当尝试在with语句块中修改变量时,会搜索with语句的对象是否有该变量,有就改变对象的值,没有就创建,但是创建的变量依然属于with语句块所在的执行环境,并不属于with对象。
  • 离开with语句块后,遍历顺序就会再次变成从执行环境开始。
  • 其实概括来说,和书本所总结的是一致的,with语句接收的对象会添加到作用域链的前端并在代码执行完之后移除。

本人见解,如有错误,欢迎指正。

关于js with语句的一些理解的更多相关文章

  1. 封装常用的js(Base.js)——【01】理解库,获取节点,连缀,

    封装常用的js(Base.js)——[01]理解库,获取节点,连缀,  youjobit07 2014-10-10 15:32:59 前言:       现如今有太多优秀的开源javascript库, ...

  2. 优化 JS 条件语句的 5 个技巧

    优化 JS 条件语句的 5 个技巧 原创: 前端大全 前端大全 昨天 (给前端大全加星标,提升前端技能) 编译:伯乐在线/Mr.Dcheng http://blog.jobbole.com/11467 ...

  3. JS高阶函数的理解(函数作为参数传递)

    JS高阶函数的理解 高阶函数是指至少满足下列条件之一的函数. · 函数可以作为参数被传递 · 函数可以作为返回值输出 一个例子,我们想在页面中创建100个div节点,这是一种写法.我们发现并不是所有用 ...

  4. Java中关于static语句块的理解

    Java中关于static语句块的理解 一.static块会在类被加载的时候执行且仅会被执行一次,一般用来初始化静态变量和调用静态方法. 实例一 public class A{ String name ...

  5. Js基本语句

    js基本语句整理导向图 ---欢迎收藏^ - ^

  6. vue.js循环语句

    vue.js循环语句 循环使用 v-for 指令. v-for 指令需要以 site in sites 形式的特殊语法, sites 是源数据数组, site 是数组元素迭代的别名. v-for 可以 ...

  7. JS循环语句的理解

    循环语句就是让程序重复性去做某些工作 最常见的就是for循环 那它的写法都有哪些呢? 1.必须要有初始值 2.要有条件判断 3.状态的改变 4.循环体 一定要控制循环多少次结束,否则就变成了死循环,消 ...

  8. 对JS事件机制的深入理解

    一.发生一个事件时,事件及事件处理程序会被放入浏览器的事件队列,事件可归为以下几类: 浏览器事件:window.load.document.DomContentLoaded等 网络请求事件:ajax. ...

  9. Js中函数式编程的理解

    函数式编程的理解 函数式编程是一种编程范式,可以理解为是利用函数把运算过程封装起来,通过组合各种函数来计算结果.函数式编程与命令式编程最大的不同其实在于,函数式编程关心数据的映射,命令式编程关心解决问 ...

随机推荐

  1. Android IOS WebRTC 音视频开发总结(四六)-- 从另一个角度看国内首届WebRTC大会

    文章主要从开发者角度谈国内首届WebRTC大会,支持原创,文章来自博客园RTC.Blacker,支持原创,转载必须说明出处,更多详见www.rtc.help. -------------------- ...

  2. Android IOS WebRTC 音视频开发总结(十三)-- ice原理

    以前在做一个视频监控项目的时候,刚开始客户没提到要支持P2P,因为服务端是我们自己写的,为了便于处理一些逻辑,全部采用转发的方式,后来客户要求支持P2P,没办法了,后来自己部署了一个STUN服务器(不 ...

  3. jQuery--each遍历使用方法

    定义和用法 each() 方法规定为每个匹配元素规定运行的函数. 提示:返回 false 可用于及早停止循环. 语法 $(selector).each(function(index,element)) ...

  4. C++ 必知必会:条款15 成员的指针并非指针

    指向类成员的类成员的指针说是“指针”,其实是不合适的,因为他既不包含地址,其行为也不像指针 常规的指正,包含地址,对其解应用可以得到该指针包含地址所指向的对象 1: int a = 12: 2: in ...

  5. Windows Phone 开发起步之旅之二 C#中的值类型和引用类型

    今天和大家分享下本人也说不清楚的一个C#基础知识,我说不清楚,所以我才想把它总结一下,以帮助我自己理解这个知识上的盲点,顺便也和同我一样不是很清楚的人一起学习下.  一说起来C#中的数据类型有哪些,大 ...

  6. CentOS学习笔记--时间

    时间 有装过Linux系统的人,可能都会有这样的经历,就是该机器安装windows系统时,时间正确,但是安装了linux系统后,尽管时区选择正确,也会发现系统时间不对.这是由于安装系统时采用了UTC, ...

  7. 类名 对象名 =new 类名();

    类名 对象名 =new 类名();该怎么理解 类名 对象名 =new 类名();=左边:创建一个类的对象=右边:调用这个类的构造函数初始化对象,类名()这个是构造函数,用来做初始化的.

  8. Varint编码

    LevelDB内部通过采用变长编码,对数据进行压缩来减少存储空间,采用CRC进行数据正确性校验.下面就对varint编码进行学习. 传统的integer是以32位来表示的,存储需要4个字节,当如果整数 ...

  9. 分享:php 上传图片的代码

    转自:http://www.jbxue.com/article/6379.html php 上传图片的代码,很简单,实现了基本的文件类型.文件大小的检测,并实现了基本的水印与缩略功能,比较适合初学的朋 ...

  10. OXPattern

    10000的随机数组由ox组成,查找数组中oox...x(任意x)oox....x(任意x)o的个数 enum { DATA_SIZE = , }; enum enum_status { STATUS ...