JS 中变量和其它语言中变量最大的区别就是,JS 是松散型语言,决定了它只是在某一个特定时间保存某一特定的值的一个名字而已。由于在定义变量的时候不需要显示规定必须保存某种类型的值,故变量的值以及保存的数据类型可以在脚本页面的生命周期中随意的改变,其他语言则不可。

1、基本类型和引用类型的值    

  基本类型:指那些保存在栈内存中的简单数据,即这种值完全保存在内存中的一个位置。他们所占据的空间大小是固定的。类型有:Number, Null, Boolean, Undefined, String[其他语言中String类型被认为是引用类型的]。但是这些基本类型如果用new方式来声明变量的话,也是引用类型

  引用类型:指那些保存在堆内存中的对象,这些类型的真正数据是保存在堆内存中的,而同时在栈内存中保存的只是一个指针这个指针指向的是这个对象在堆内存中的一块地址。[Object类型]

  基本类型的复制:基本类型在内存中占有的空间大小是固定的,复制的时候会重新在栈内存中开辟一块空间,是按值来访问的。

  引用类型的复制:由于这种对象所占的大小是不固定的,是放在堆内存中的,但是内存的地址大小是固定的,故栈中存放的是对象在堆内存的地址。这样当查找引用的时候,是先从栈内存中取出地址,然后再到堆内存中找到对应的值,这就是引用访问。复制的时候是复制的栈内存的值,也就是拷贝的一个引用而已,两个变量指向的堆内存中对象还是同一个对象。

2、动态属性    

  引用类型变量可以直接添加属性,box.name='abc';

  值类型的变量(字面量形式声明)如果按照同样的方式添加属性,不会报错,但是按照同样的方式输出属性的时候就是undefined,但是如果通过new的方式来声明的话则效果和Object是一样的

3、复制变量的值

  基本类型:复制的是变量本身的值,复制后是在栈空间重新开辟一块空间,复制完成后两个变量是相互独立的,各不相干,故一个变量的值改变后不会影响另外一个变量的值。

  引用类型:复制的时候只是复制的栈空间的地址而堆内存中还是同一个对象,也就是复制的引用,结果是两个变量指向的是同一个内存块,所以,复制后两个变量中某一个改变了对象的值那么另外一个变量输出的结果也会改变,因为他们是指向的内存中同一个对象。

4、传递参数

  在JS中参数传递都是值传递,不存在引用传递,C语言中引用传递就是在变量前面添加一个&符号。

  值类型:传递的是变量本身的值,和复制是一样的,函数中改变了变量的值,不会影响源变量值

  引用类型:同样是值传递,传递的是变量再栈内存空间中的地址值,如果在函数中改变了对象某一个属性的值,源变量中的值也会改变,因为在堆内存中它们是指向的同一个对象

function func(num){
num.name=123;
} var box={};
box.name='abcd';
alert(box.name); //abcd
func(box);
alert(box.name); //123 值在函数func中被改变了

  ECMAScript 函数中的参数都是局部变量,没有按照引用传递的变量。只有传递引用类型的变量

5、检测类型    

  在 《JS 学习笔记--3---数据类型》中知道,检测变量的类型的时可以用 typeof 来实现,但是这个只是返回的几大基本的数据类型,在检测Object类型的时候则不是那么好用,因为Null,Object,Array,RegExp 等都会返回object,那样就不知道变量到底是什么类型。

  可以 instanceof 来确定变量是某种具体的引用类型。   alert(box instanceof Array);  alert(box instanceof Null);     alert(box instanceof RegExp);  alert(box instanceof String); 等   如果是这种类型就返回true,否则就返回false

  用 instanceof 来检测用字面量形式声明的基本类型的变量返回的是false,但是如果用 new 方法声明的变量则会返回为 true

6、执行环境以及作用域   

  执行环境也就是作用域在很多的编程语言中都是一个很重要的概念,规定了变量或者函数有权访问其他数据的权限,规定了各自的行为。JS 中执行环境和其他语言差不多。

  全局执行环境是最外围的执行环境在Web中,全局执行环境被认为是window对象,故所有的变量和函数都是以window对象的属性和方法创建的。

  当执行环境中代码执行完成后,就会销毁该执行环境,也会销毁里面的变量和函数等。全局执行环境是需要在网页关闭或者程序执行完毕后才会被销毁。

  函数体内还包含着函数,只有这个函数才可以访问内一层的函数。

  每当函数被调用的时候都会创建自己的环境对象,当执行这个函数时,函数的环境就会被推到环境栈上面去执行,而环境栈执行完成后,又回弹出栈,把控制权交给上一级的执行环境。

  当代码在一个环境中执行的时候,就会形成一个块级作用链域的东西,作用就是保证对执行环境中有访问权限的函数和对象进行有序访问,处于链域的最前端就是执行环境的变量对象

  一般来说对象只是能够访问它的本身的属性和方法,不能够隔代访问,window不能够访问方法func中定义的方法ziFunc,但是可以通过点访问形式访问对象box中定义的方法ziFunc,参考C#点访问法   

7、没有块级作用域  

  块级作用域表示诸如if等有花括号封闭的代码段块,所以支持条件判断来定义变量。 像 if,for 等代码块中定义的变量再花括号外面是可以访问的,这和其他语言中有很大的差别

8、var 关键字在函数中的区别  

  函数中声明变量的时候,如果不加上关键字 var 那变量会被认为是全局的,函数外面也可以访问它,当然在访问之前要先执行一次函数,加了则是局部的

  最好不要不用var关键字就初始化变量,因为这种情况下可能会导致各种错误,所有初始化变量的时候一定要加上关键字 var

  一般确定某一个变量的时候是通过搜索来确定的,现在本级作用域上找,如果没有,在向上级作用域找,依次类推,故访问局部变量要比访问全局变量的效率更高。因为不需要向上收索作用域链

9、内存相关  

  JS中也存在垃圾回收机制,和C#差不多,我们不需要担心内存的泄露问题,垃圾回收机制会自动的管理内存的分配和无用内存的回收。

  JS中最常用的垃圾回收的方式是标记清楚,就是在运行的时候会给内存中的变量加上一个标记,然后去掉环境中正在使用的变量的标记,而没有被去掉标记的变量将被视为准备删除的变量。最后垃圾清理器完成内存清理的工作,销毁那些带有标记的变量,并且回收他们所占用的内存空间

  垃圾收集器是周期性的运行,不是随时运行,这样可能会遇到一些性能问题,但是一般情况下不需要担心这个问题

  一般来说,确保页面占用的内存更少可以让页面获得更好的性能,最好的减少内存占用量的方式就是,一旦变量或者对象不再使用的时候,将其赋值为空,即:box=null; 来释放引用,这种方式叫做删除引用,这种方式使用大多数的全局变量和全局对象。

练习代码:

 /*
//字面量形式定义的基本类型数据是非引用类型的变量
var box='ABC';
box.name='abc';
alert(box.name); //undefined //通过new的方式声明的各种基本类型的变量就是引用类型的变量
var box=new String();
box.name='abc';
alert(box.name); //abc var box=new Boolean(123);
box.name='ca';
alert(box.name); //ca
alert(box); //true 因为在声明的时候赋了值,不为空故为true
var age=box;
alert(age.name); //ca */ /* 复制变量的值
//值类型的数据是拷贝的一个副本,是在栈内存空间开辟一块新的内存,
//复制完成后两个变量各不相干,改变一个变量的值不会改变另外一个变量的值
var box='abcd';
var age=box;
alert(box); //abcd
alert(age); //abcd
age=123;
alert(box); //abcd
alert(age); //123 //引用类型的变量复制时,也是复制的栈空间的值,也就是把变量的地址块的引用复制了一份
//但是两个变量还是指向的堆内存中同一块内存区域,故一个变量的值改变,另外一个变量值同样改变
var box2={};
box2.name='abcd';
var age2=box2;
alert(box2.name); //abcd
alert(age2.name); //abcd
age2.name=123;
alert(box2.name); //123
alert(age2.name); //123
*/ /* 参数传递 JS 中没有引用传递,只有值传递
//值类型变量,变量传入到函数后,无论函数如何改变值,在函数外面还是不变的,
//和拷贝差多不,同样是在栈内存中重新开辟一块区域
function func(box){
box=10;
} var box=20;
alert(box); //20
func(box);
alert(box); //20 //引用类型的变量 传递的同样是栈内存中的值,也就是对象的地址,这种变量传递过去后如果在
//函数中改了对象的某个属性的值,那么外面的源对象的值同样会改变,因为指向的是同一块堆内存空间
function func(num){
num.name=123;
} var box={};
box.name='abcd';
alert(box.name); //abcd
func(box);
alert(box.name); //123 值在函数func中被改变了 */ /* 类型检测 instanceof
//通过instanceof来确定变量是否是某一具体的类型,比如 Array RegExp 等类型
var box=[2,3,4,5];
alert(box instanceof Array); //true
alert(box instanceof Object); //true
alert(box instanceof RegExp); //false
var age=/123/;
alert(age instanceof RegExp); //true // 检测字面量形式申请的基本类型的时候返回的是false,但是采用new方式声明的变量返回的是true
var box='abcd';
alert(box instanceof String); //false
box=new String('abc');
alert(box instanceof String); //true var box=1234;
alert(box instanceof Number); //false
box=new Number(124);
alert(box instanceof Number); //true */ /* 块级作用域
function func(){ for(var i=0;i<10;i++){
var box=123;
}
//for循环中定义的变量可以再外面访问,也就所for中定义的变量再它所在的作用域中是全局的
alert(i); //10
alert(box); //123
} func(); */ /* 函数中的关键字var
function func(){
sum=100;
var age=100;
}
func();
alert(sum); //100 因为函数中声明变量的时候没有添加关键字,被认为是全局的,故可以访问
alert(age); //error
*/

JS 学习笔记--9---变量-作用域-内存相关的更多相关文章

  1. python3学习笔记12(变量作用域)

    变量作用域 参考http://www.runoob.com/python3/python3-function.html Python 中,程序的变量并不是在哪个位置都可以访问的,访问权限决定于这个变量 ...

  2. Python 3 学习笔记之——变量作用域、模块和包

    1. 变量作用域 Python 中,程序的变量并不是在哪个位置都可以访问的,访问权限决定于这个变量是在哪里赋值的.变量的作用域决定了在哪一部分程序可以访问哪个特定的变量名称.Python 的作用域一共 ...

  3. 《JavaScript 高级程序设计》读书笔记四 变量 作用域 内存

    一   变量(基本类型和引用类型) a.基本类型保存值,保存在栈内存,引用类型保存指针,保存在堆内存: b.所有函数的参数都是按值进行传递的,不管参数是何种类型: c.检测类型 typeof     ...

  4. vue.js 学习笔记3——TypeScript

    目录 vue.js 学习笔记3--TypeScript 工具 基础类型 数组 元组 枚举 字面量 接口 类类型 类类型要素 函数 函数参数 this对象和类型 重载 迭代器 Symbol.iterat ...

  5. Node.js学习笔记(2):基本模块

    Node.js学习笔记(2):基本模块 模块 引入模块 为了编写可维护的代码,我们把很多函数分组,分别放到不同的文件里,这样,每个文件包含的代码就相对较少,很多编程语言都采用这种组织代码的方式.在No ...

  6. JUC学习笔记——共享模型之内存

    JUC学习笔记--共享模型之内存 在本系列内容中我们会对JUC做一个系统的学习,本片将会介绍JUC的内存部分 我们会分为以下几部分进行介绍: Java内存模型 可见性 模式之两阶段终止 模式之Balk ...

  7. Redis学习笔记(二)-key相关命令【转载】

    转自 Redis学习笔记(二)-key相关命令 - 点解 - 博客园http://www.cnblogs.com/leny/p/5638764.html Redis支持的各种数据类型包括string, ...

  8. 2019-4-29 js学习笔记

    js学习笔记一:js数据类型   1:基本数据类型       number类型(整数,小数)      String类型          boolean类型        NaN类型其实是一个nu ...

  9. 一点感悟:《Node.js学习笔记》star数突破1000+

    写作背景 笔者前年开始撰写的<Node.js学习笔记> github star 数突破了1000,算是个里程碑吧. 从第一次提交(2016.11.03)到现在,1年半过去了.突然有些感慨, ...

随机推荐

  1. 状态可以通过动画切换的按钮--第三方开源--TickPlusDrawable

    Android tickplusdrawable(TickPlusDrawable)在github上的项目主页是:https://github.com/flavienlaurent/tickplusd ...

  2. c# equals和==的区别

    简言之: equals必须是类型和值都得相等 == 只要值相等 注意: void Main() { ; ; Console.WriteLine(a.Equals(b)); //True (short会 ...

  3. win7旗舰版在安装vs2010后向sql2008添加SQL_Server_Management详解

    原文地址:http://blog.csdn.net/bruce_zeng/article/details/8202746

  4. python ssh

    使用python包paramiko实现通过ssh的安全远程访问 使用pip下载安装paramiko,提示会缺一个crypto包,用pip将这个包也安好,python就可以正常引用paramiko了 一 ...

  5. xcode plugin

    http://alcatraz.io/ https://github.com/macoscope/CodePilot prepo  curl -fsSL https://raw.githubuserc ...

  6. [转]Oracle 10g及pro*c相关问题及解决方法(转)

    Oracle 10g及pro*c相关问题及解决方法 2008年08月21日 星期四 上午 11:21 最近一直在进行ORACLE 10g和PRO*C的学习. 其中遇到了不少的问题: 现列于此,已备他用 ...

  7. Word2013死机的问题

    Word2013用公式编辑器经常死机,网上介绍方法.试试看https://zhidao.baidu.com/question/937023473910649252.html1.启动word2013 2 ...

  8. eclipse创建android项目失败的问题 [ android support library ]

    有根筋搭错了,想起来android应用开发???? 放下两年的手机应用开发,昨天有更新了android SDK, 重新搭建开发环境. 这两年android 变化真TM的大............... ...

  9. Your First ASP.NET 5 Application on a Mac

    Your First ASP.NET 5 Application on a Mac By Daniel Roth, Steve Smith, Rick Anderson ASP.NET 5 is cr ...

  10. 对 Linux 新手非常有用的20个命令

    你打算从Windows换到Linux上来,还是你刚好换到Linux上来?哎哟!!!我说什么呢,是什么原因你就出现我的世界里了.从我以往的经验来说,当我刚使用Linux,命令,终端啊什么的,吓了我一跳. ...