这几天,闲的没事看看JavaScript高级编程,感觉JavaScript真的很强大,尤其是采用面向对象的编程方式。

一.   基本类型和引用类型的值:

ECMAScript变量可能包含两种不同数据类型的值:基本类型值和引用类型值。

基本类型的值指的是简单的数据段,比如Undefined、Null、Boolean、Number、String,这5种基本类型是按值访问的;

引用类型的值指的是保存在内存中的对象,在操作对象时,实际上是在操作对象的引用而不是实际的对象。为此,引用类型的值是按引用访问的。

二.传递参数:

ECMAScript中所有函数的参数都是按值传递的,换句话说,把函数外部的值复制给函数内部的参数,就和把值从一个变量复制到另一个变量一样。

基本类型值的传递如同基本类型变量的复制一样;

引用类型值得传递如同引用类型变量的复制一样;

三.执行环境及作用域链:

  1. 执行环境

执行环境(execution context) 是JavaScript中最为重要的一个概念,执行环境定义了变

量或函数是否有权访问其他数据,决定了它们各自的行为。每个执行环境都有一个与之相关的“变量对象”,环境中定义的所有变量和函数都保存在这个对象中。虽然我们

编写的代码无法访问这个对象,但解析器在处理数据是会在后台使用它。

全局执行环境是最外围的一个执行环境。在Web游览器中,全局执行环境被认为是Window对象,因此所有变量和函数都是作为window对象的属性和方法创建的。某个执

行环境中的所有代码执行完毕后,该环境被销毁,保存在其中的所有变量和函数定义也随之销毁(全局执行环境直到应用程序退出——例如关闭网页或游览器时才会被销

毁)。

执行环境类型总共两种:

(1)     全局执行环境(window);

(2)     局部执行环境(函数function);

  1. 作用域链

当代码在一个环境中执行时,会创建变量对象的一个作用域链。作用域链的用途,是保证对执行环境有权访问的所有变量和函数的有序访问。作用域链的的前端,始终都

是当前执行的代码所在环境的变量对象。作用域链中的下一个变量对象来自包含(外部)环境,而在下一个变量对象则来自下一个包含对象。这样,一直延续到全局执行

环境,全局执行环境的变量对象始终都是作用域链中的最后一个对象。

例如:

  1. var color = "blue";
  2. function changeColor(){
  3. var anotherColor = "red";
  4. function swapColors(){
  5. var tempColor = anotherColor;
  6. anotherColor = color;
  7. color = tempColor;
  8. //这里可以访问color、anotherColor和tempColor
  9. }
  10. //这里可以访问color和anotherColor,但不能访问tempColor
  11. swapColors();
  12. }
  13. //这里只能访问color
  14. changeColor();

先画一个作用域链示例图:

上图中,矩形表示特定的执行环境。其中,内部环境可以通过作用域链访问所有的外部环境,但外部环境不能访问内部环境中的任何变量和函数。每个环境都可以向上搜索作用域链,以查询变量和函数名。任何环境都不能通过向下搜索作用域链而

进入另一个执行环境。

以上代码共涉及3个执行环境:全局环境、changeColor()的局部环境和swapColors()的局部环境。

全局执行环境中有一个变量color和一个函数changeColor();

changeColor()局部环境中有一个变量anotherColor和一个函数swapColors(),但它也可以访问全局环境中的变量color,

swapColors()局部环境中有一个变量tempColor,该变量只能在该环境中访问到,无论是全局环境还是changeColor()的局部环境都无权访问tempColor。然而,在swapColors()内部,则可以访问其他两个环境中的所有变量,因为那两个环境是它的

父执行环境。

四.延长作用域链

当执行流进入下列任何一个语句时,作用域链将得到延长:

1) try-catch语句的catch块

2) with语句

此两个语句会在作用域链的前端添加一个变量对象。对with来说,其变量对象中包含着指定对象的所有属性和方法所作的变量声明;对catch来说,其变量对象中包含的是被抛出的错误对象的声明。这些变量对象都是只读的,因此在with和catch语句

中声明的变量都会被添加到所在执行环境的变量对象中。

例如:

  1. (function(){
  2. with(location){
  3. var myhref = href; //在with语句中声明一个myhref变量
  4. }
  5. // 居然被添加到当前执行函数的执行环境中了,看来with语句中指定的对象时只读的
  6. console.log(myhref);
  7. })();

五.没有块级作用域

  1. 什么是块级作用域?

在C/C++/Java中,由花括号封闭的代码都有自己的作用域(如果使用ECMAScript的话来讲,就是它们自己的执行环境)。

例如:

  1. if(true){
  2. //块级作用域
  3. var color = “blue”;
  4. }
  5. alert(color);

对于有块级作用域的语言来说,if语句中所定义的变量,只会存在于if的环境之中,color变量会在if语句执行完毕后被销毁。但是,在JavaScript中,if语句中的变量声明会将变量添加到当前的执行环境中(这里是全局环境)。

  1. 声明变量

使用var声明的变量会自动被添加到最接近的环境中。如果没有使用var声明变量,该变量会自动被添加到全局环境中。

例如:

  1. function add(num1,num2){
  2. //没有使用var声明变量,自动被添加到最接近的环境中(全局执行环境)
  3. sum = num1 + num2;
  4. return sum;
  5. }
  6. var result = add(10,20);
  7. //这里访问sum成功,说明该变量在全局执行环境中
  8. console.log(sum);

不声明而直接初始化变量时一个常见的错误做法,这样可能会导致意外。

  1. 查询标识符
  1. var color = "blue";
  2. function changeColor(){
  3. function swapColors(){
  4. return color;
  5. }
  6. return  swapColors();
  7. }
  8. console.log(changeColor());

先画一个查询标识符示意图:

调用本例中的changeColor()时会引用变量color,为了确定变量color的值,将开始一个3步的

搜索过程,首先,搜索swapColors()的变量对象,查找是否包含一个名为color的标识符。在没有找到的情况下,继续搜索下一个变量对象(changeColor()的变量对象),如

果没有继续搜索下一个变量对象(也就是全局环境的变量对象),然后在这里找

到了名为color的标识符,搜索过程宣告结束。

六.管理内存

优化内存占用的最佳方式,就是为执行中的代码只保存必要的数据,一旦数据不再使用,最好通过将其设置为null来释放其引用——这个做法叫做“解除引用”

例如:

  1. function createPerson(name){
  2. var localPerson = new Object();
  3. localPerson.name = name;
  4. return localPerson;
  5. }
  6. var globalPerson = createPerson("Admin");
  7. //手工解除globalPerson的引用
  8. globalPerson = null;

以上代码中,由于变量localPerson 在createPerson()函数执行完毕后就离开了其执行环境,因此,无需我们显式地为它解除引用。但是对于全局变量globalPerson而言,则需要我们在不使用它的时候手工为它解除引用。

JavaScript中变量、作用域、内存问题的更多相关文章

  1. 浅谈javascript中变量作用域和内存(2)

    1.无块级作用域 javascript没有块级作用域,这会让其他程序员在理解js代码上很痛苦.在其他很多语言,比如C,大括号括起来的代码块都有自己的作用域 举个例子 if(true) { var na ...

  2. 浅谈javascript中变量作用域和内存(1)

    先理解两个概念:基本类型和引用类型的值 1.基本类型和引用类型的值 (1)定义: 基本类型:指简单的数据段,比如按值访问的js五种基本数据类型undefined.null.boolean.number ...

  3. Javascript中变量作用域(2)

    多层函数调用取变量时,无论在哪里调用,要到创建此函数的作用域中取值,如果找不到再往上一级,直到全局变量. 外面定义了很多的全局的变量,下面我们来一个个理一下. 定义三个变量a,b,c;将A1函数赋值给 ...

  4. Javascript中变量作用域

    <script type="text/javascript"> var a = 10; var Bar = (function () { console.log(a); ...

  5. JavaScript 中变量、作用域和内存问题的学习

    这是我学习JavaScript的第二篇文章,之前做过几年的Java开发,发现JavaScript虽然也是面向对象的语言但是确实有很多不同之处.就本篇博客,主要学习总结一下最近学习到的JavaScrip ...

  6. javascript的变量作用域--对比js、php和c的for循环

    为什么要写这篇文章呢?主要是给自己提个醒,js的水很深,需要小心点儿才能趟过去,更何况自己不是专业人士,那就得更加小心了. 看下面的js代码: <!DOCTYPE html> <ht ...

  7. [转]深入理解JavaScript的变量作用域

    1.JavaScript的作用域链 2.函数体内部,局部变量的优先级比同名的全局变量高. 3.JavaScript没有块级作用域. 4.函数中声明的变量在整个函数中都有定义. 5.未使用var关键字定 ...

  8. JavaScript中的作用域

    很多(JavaScript)开发者都在讨论"作用域",但它是什么?它们在JavaScript中的任何地方!我发现很多年轻的开发者不知道作用域是什么.他们中大多数人可以用jQuery ...

  9. 深入理解JavaScript的变量作用域(转载Rain Man之作)

    在学习JavaScript的变量作用域之前,我们应当明确几点: JavaScript的变量作用域是基于其特有的作用域链的. JavaScript没有块级作用域. 函数中声明的变量在整个函数中都有定义. ...

  10. 【翻译】JavaScript中的作用域和声明提前

    原文:http://www.adequatelygood.com/JavaScript-Scoping-and-Hoisting.html ===翻译开始=== 你知道下面的JavaScript脚本执 ...

随机推荐

  1. 11.UiAutomator 相关JAVA知识

    一.封装方法与模块化用例 1.方法: 在JAVA中,方法就好比日常生活中的一个动作,由动作组合成一系列完整的操作. 方法结构: 方法修饰符 方法返回值类型 方法名 { 方法体 } 比如: public ...

  2. 手动搭建高可用的kubernetes 集群

    之前按照和我一步步部署 kubernetes 集群的步骤一步一步的成功的使用二进制的方式安装了kubernetes集群,在该文档的基础上重新部署了最新的v1.8.2版本,实现了kube-apiserv ...

  3. linux 下 mysql 主从配置

    话不多说,直接干. 准备条件:安装两个mysql数据库,随便哪个作主库,另一个从库. 1.在主库创建 复制用的账号 grant replication slave ,replication clien ...

  4. TCP和UDP相关概念

    位于传输层的协议,都是基于IP协议的. TCP是面向连接的.可靠的传输,UDP是无连接的.不可靠的传输.要进行TCp传输时候,需要进行三次握手,建立连接,然后才能发送数据,而且在发送过程中,有数据的确 ...

  5. MongoDB - MongoDB CRUD Operations, Update Documents

    Update Methods MongoDB provides the following methods for updating documents in a collection: Method ...

  6. Oracle Number类型超长小数位为0问题

    碰到了一个非常奇怪的问题,从Excel拷贝出来的数据,位数很长,通过Pl Sql 导出到Oracle后为0了,而且设置查询条件为0时,无法查询出来,条件大于0居然能查询出来,通过to_number也是 ...

  7. NYOJ 328 完全覆盖 (找规律)

    题目链接 描述 有一天小董子在玩一种游戏----用21或12的骨牌把mn的棋盘完全覆盖.但他感觉游戏过于简单,于是就随机生成了两个方块的位置(可能相同),标记一下,标记后的方块不用覆盖.还要注意小董子 ...

  8. html5优分期大学生分期购物商城模板

    链接:http://pan.baidu.com/s/1dEUAzBz 密码:j150

  9. vscode中go插件配置

    # 转自:http://www.mamicode.com/info-detail-2436665.html # https://blog.csdn.net/bing2011/article/detai ...

  10. 在新版linux上编译老版本的kernel出现kernel/timeconst.h] Error 255

    在使用ubuntu16.4编译Linux-2.6.31内核时出现这样的错误 可以修改timeconst.pl的内容后正常编译. 以下是编译错误提示的内容: Can't use 'defined(@ar ...