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. "/Date(1405056837780)/" 时间转换

    //往往json传过来的时间都是"/Date(1405056837780)/" //转换需要的方法 String.prototype.ToString = function (fo ...

  2. 配置pxe 自动化安装centos6.7

    dhcp服务器是pxe自动化安装的必要条件,因此先搞定dhcp服务器,yum -y install dhcp,  rpm -ql dhcp查看安装了哪些包,less /etc/dhcp/dhcpd.c ...

  3. PHP四大安全策略

    PHP中的文件系统安全.数据库安全.用户数据安全等安全相关的问题. 一.文件系统安全 php如果具有root权限,且在脚本中允许用户删除文件,那么用户提交数据,不进行过滤,就非常有可能删除系统文件 & ...

  4. 转:浅谈关于b、h标签的优化技巧

    <b>标签优化 <b>标签是一种加粗标记,作用就是加粗文章中的关键词,对于文章中重要的关键词加粗起到有利于用户阅读的作用.<b>标签的使用对于优化的作用是非常大的, ...

  5. wordpress学习-themes-001

    这一篇主要是来记录wordpress theme的内容.关于为什么要自己编写wordpress theme的理由,相信大家都有各自的体会.想让自己的博客变的更加突出?更加个性话?wordpress t ...

  6. 通过Eclipse创建SQLite数据库

    import android.content.Context;import android.database.sqlite.SQLiteDatabase;import android.database ...

  7. javascript jquery each 影响 函数返回值

    实例如下: $(function(){ if(chkInput()){ alert('OK!') } }); function chkInput(){ var data = jsonData(略); ...

  8. 正整数转换成N进制的数组

    给定一个正整数,按照N进制转换成数组元素存储 //给定一个整数,把它转换成按照N进制存储的数组 #include <stdio.h> #include <stdlib.h> # ...

  9. Linq操作

    Linq使用Group By 1 1.简单形式: var q = from p in db.Products group p by p.CategoryID into g select g; 语句描述 ...

  10. Red Gate Software 软件推荐

    这家公司的Wiki http://en.wikipedia.org/wiki/Redgate http://www.red-gate.com/products/ 好吧 就介绍点免费的 Find SQL ...