2015第35周五JavaScript变量
java语言里有一句很经典的话:在java的世界里,一切皆是对象。
Javascript虽然跟java没有半点毛关系,但是很多会使用javascript的朋友同样认为:在javascript的世界里,一切也皆是对象。
其实javascript语言和java语言一样变量是分为两种类型:基本数据类型和引用类型。
基本类型是指:Undefined、Null、Boolean、Number和String;而引用类型是指多个指构成的对象,所以javascript的对象指的是引用类型。在java里能说一切是对象,是因为java语言里对所有基本类型都做了对象封装,而这点在javascript语言里也是一样的,所以提在javascript世界里一切皆为对象也不为过。
Javascript里的基本变量是存放在栈区的(栈区指内存里的栈内存),它的存储结构如下图所示:
javascript里引用变量的存储就比基本类型存储要复杂多,引用类型的存储需要内存的栈区和堆区(堆区是指内存里的堆内存)共同完成,如下图所示:
在javascript里变量的存储包含三个部分:
部分一:栈区的变量标示符;
部分二:栈区变量的值;
部分三:堆区存储的对象。
JS中变量赋值和函数传参都是传递栈区的值。JS中的变量未定义不能访问,但可以不用var定义而直接出现在赋值语句中,此时相当于在全局通过var定义该变量,实际上是window的一个属性。
其实javascript里的变量和其他语言有很大的不同,javascript的变量是一个松散的类型,松散类型变量的特点是变量定义时候不需要指定变量的类型,变量在运行时候可以随便改变数据的类型,但是这种特性并不代表javascript变量没有类型,当变量类型被确定后javascript的变量也是有类型的。但是在现实中,很多程序员把javascript松散类型理解为了javascript变量是可以随意定义即你可以不用var定义,也可以使用var定义,其实在javascript语言里变量定义没有使用var,变量必须有赋值操作,只有赋值操作的变量是赋予给window,这其实是javascript语言设计者提升javascript安全性的一个做法。
此外javascript语言的松散类型的特点以及运行时候随时更改变量类型的特点,很多程序员会认为javascript变量的定义是在运行期进行的,更有甚者有些人认为javascript代码只有运行期,其实这种理解是错误的,javascript代码在运行前还有一个过程就是:预加载,预加载的目的是要事先构造运行环境例如全局环境,函数运行环境,还要构造作用域链,而环境和作用域的构造的核心内容就是指定好变量属于哪个范畴,因此在javascript语言里变量的定义是在预加载完成而非在运行时期。
var ooo = null; console.log(ooo);// 运行结果:null console.log(ooo == undefined);// 运行结果:true console.log(ooo == null);// 运行结果:true console.log(ooo === undefined);// 运行结果:false console.log(ooo === null);// 运行结果:true

运行之,结果很震惊啊,null居然可以和undefined相等,但是使用更加精确的三等号“===”,发现二者还是有点不同,其实javascript里undefined类型源自于null即null是undefined的父类,本质上null和undefined除了名字这个马甲不同,其他都是一样的,不过要让一个变量是null时候必须使用等号“=”进行赋值了。
当变量为undefined和null时候我们如果滥用它javascript语言可能就会报错,后续代码会无法正常运行,所以javascript开发规范里要求变量定义时候最好马上赋值,赋值好处就是我们后面不管怎么使用该变量,程序都很难因为变量未定义而报错从而终止程序的运行,例如上文里就算变量是string基本类型,在变量定义属性程序还是不会报错,这是提升程序健壮性的一个重要手段,由引子的例子我们还知道,变量定义最好放在变量所述作用域的最前端,这么做也是保证代码健壮性的一个重要手段。
函数传递参数的本质就是外部的变量复制到函数参数的变量里,我们看看下面的代码:

function testFtn(sNm,pObj){ console.log(sNm);// 运行结果:new Name console.log(pObj.oName);// 运行结果:new obj sNm = "change name"; pObj.oName = "change obj"; } var sNm = "new Name"; var pObj = {oName:"new obj"}; testFtn(sNm,pObj); console.log(sNm);// 运行结果:new Name console.log(pObj.oName);// 运行结果:change obj
var ftn1 = function(){ console.log("test:ftn1"); }; var ftn2 = function(){ console.log("test:ftn2"); }; function ftn(f){ f(); f = ftn2; } ftn(ftn1);// 运行结果:test:ftn1 console.log("====================华丽的分割线======================"); ftn1();// 运行结果:test:ftn1

这个代码是很早之前有位朋友考我的,我当时答对了,但是我是蒙的,问我的朋友答错了,其实当时我们两个都没搞懂其中缘由,我朋友是这么分析的他认为f是函数的参数,属于函数的局部作用域,因此更改f的值,是没法改变ftn1的值,因为到了外部作用域f就失效了,但是这种解释很难说明我上文里给出的函数传参的实例,其实这个问题答案就是函数传参的原理,只不过这里加入了个混淆因素函数,在javascript函数也是对象,局部作用域里f = ftn2操作是将f在栈区的地址改为了ftn2的地址,对外部的ftn1和ftn2没有任何改变。
记住:javascript里变量复制和函数传参都是在传递栈区的值。
栈区的值除了变量复制起作用,它在if语句里也会起到作用,当栈区的值为undefined、null、“”(空字符串)、0、false时候,if的条件判断则是为false,我们可以通过!运算符计算,因此当我们的代码如下:

var obj = {}; if (!!obj){ console.log("true"); }else{ console.log("false"); }

结果则是true,因为var obj = {}相当于var obj = new Object(),虽然对象里没什么内容,但是在堆区里,对象的内存已经分配了,而变量栈区的值已经是内存地址了,所以if语句判断就是true了。
谈谈javascript语法里一些难点问题(一)
2015第35周五JavaScript变量的更多相关文章
- 2015第37周五javascript函数arguments对象巧用一
Javascript函数的一个巧妙利用:假定action中有一个JSONObject类型的对象data,其值有可能为空,则前台JSP页面的JS代码中想直接通过EL表达式,即${data}的形式访问对象 ...
- 【规范】javascript 变量命名规则
javascript 有三大经典的变量命名法:匈牙利命名法,驼峰式命名法和帕斯卡命名法.今天主要介绍下这三种命名方式. 匈牙利命名法 语法 变量名 = 类型 + 对象描述 类型指变量的类型 对象描述指 ...
- 【规范】javascript 变量命名规则(转)
匈牙利命名法 语法 变量名 = 类型 + 对象描述 类型指变量的类型 对象描述指对象名字全称或名字的一部分,要求有明确含义,命名要容易记忆容易理解. 通过在变量名前面添加相应小写字母的符号标示作为前缀 ...
- javascript变量的作用域
javascript变量的作用域 基本类型和引用类型 基本类型值指的是简单的数据段,而引用类型值指的是那个可能由多个值组成的对象 讲一个值赋值给变量时,javascript解析器首先要确定是基本类型 ...
- JavaScript 变量声明提前
<JavaScript权威指南>中指出:JavaScript变量在声明之前已经可用,JavaScript的这个特性被非正式的称为声明提前(hoisting),即JavaScript函数中声 ...
- JavaScript 变量
一,JavaScript 变量(存储信息的容器) 与代数一样,JavaScript 变量可用于存放值(比如 x=2)和表达式(比如 z=x+y). 变量可以使用短名称(比如 x 和 y),也可以使用描 ...
- javascript变量声明 及作用域
javascript变量声明提升(hoisting) http://openwares.net/js/javascript_declaration_hoisting.html 可能要FQ一下 java ...
- JavaScript 变量作用域
一. 变量声明 变量用var关键字来声明,如下所示: 变量在未声明的情况下被初始化,会被添加到全局环境. JavaScript执行代码时,会创建一个上下文执行环境,全局环境是最外围的环境.每个函数在被 ...
- 【转】javascript变量声明 及作用域
javascript变量声明提升(hoisting) javascript的变量声明具有hoisting机制,JavaScript引擎在执行的时候,会把所有变量的声明都提升到当前作用域的最前面. 先看 ...
随机推荐
- springMVC3学习(二)--ModelAndView对象
当控制器处理完请求时,一般会将包括视图名称或视图对象以及一些模型属性的ModelAndView对象返回到DispatcherServlet. 因此,常常须要在控制器中构造ModelAndView对象. ...
- Linux 开机自检的设置(tune2fs和fsck)
tune2fs和fsck的用法 tune2fs--调整ext2/ext3文件系统特性的工具. -l <device> 查看文件系统信息 -c <count> 设置强制自检的 ...
- 如何使用Valgrind memcheck工具进行C/C++的内存泄漏检测
系统编程中一个重要的方面就是有效地处理与内存相关的问题.你的工作越接近系统,你就需要面对越多的内存问题.有时这些问题非常琐碎,而更多时候它会演变成一个调试内存问题的恶梦.所以,在实践中会用到很多工 ...
- 模仿ios下的coverflow
Android高级图片滚动控件,编写3D版的图片轮播器 http://blog.csdn.net/guolin_blog/article/details/17482089 A cool Open So ...
- Android(java)学习笔记239:多媒体之撕衣服的案例
1.撕衣服的案例逻辑: 是两者图片重叠在一起,上面我们看到的是美女穿衣服的图片,下面重叠(看不到的)是美女没有穿衣服的图片.当我们用手滑动画面,上面美女穿衣服的图片就会变成透明,这样的话下 ...
- checkbox 全选/取消
<html><script language=javascript>function selectAll(){var a = document.getElementsByTag ...
- python 之路,Day27 - 主机管理+堡垒机系统开发
python 之路,Day27 - 主机管理+堡垒机系统开发 本节内容 需求讨论 构架设计 表结构设计 程序开发 1.需求讨论 实现对用户的权限管理,能访问哪些机器,在被访问的机器上有哪些权限 实 ...
- COGS 445. [HAOI2010]最长公共子序列
#include<iostream> #include<cstdio> #include<cstring> #define mod 100000000 #defin ...
- DataTable数据与Excel表格的相互转换
using Excel = Microsoft.Office.Interop.Excel; private static Excel.Application m_xlApp = null; /// & ...
- vertical-align各属性对比
测试用代码 <!DOCTYPE html> <html> <head> <style> #dd { //line-height: 300px; back ...