变量及作用域

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

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

类型值指的是那些保存在栈内存中的简单数据段,即这种值完全保存在内存中的一个位置。

而引用类型值则是指那些保存在堆内存中的对象,意思是变量中保存的实际上只是一个指

针,这个指针指向内存中的另一个位置,该位置保存对象。

将一个值赋给变量时,解析器必须确定这个值是基本类型值,还是引用类型值。基本类

型值有以下几种:Undefined、Null、Boolean、Number 和String。这些类型在内存中分别占

有固定大小的空间,他们的值保存在栈空间,我们通过按值来访问的。

PS:在某些语言中,字符串以对象的形式来表示,因此被认为是引用类型。ECMAScript

放弃这一传统。

如果赋值的是引用类型的值,则必须在堆内存中为这个值分配空间。由于这种值的大小

不固定,因此不能把它们保存到栈内存中。但内存地址大小的固定的,因此可以将内存地址

保存在栈内存中。这样,当查询引用类型的变量时,先从栈中读取内存地址,然后再通过地

址找到堆中的值。对于这种,我们把它叫做按引用访问。

图片发自简书App

2.动态属性

定义基本类型值和引用类型值的方式是相似的:创建一个变量并为该变量赋值。但是,

当这个值保存到变量中以后,对不同类型值可以执行的操作则大相径庭。

var box = new Object(); //创建引用类型

box.name = 'Lee'; //新增一个属性

alert(box.name); //输出

如果是基本类型的值添加属性的话,就会出现问题了。

var box = 'Lee'; //创建一个基本类型

box.age = 27; //给基本类型添加属性

alert(box.age); //undefined

3.复制变量值

在变量复制方面,基本类型和引用类型也有所不同。基本类型复制的是值本身,而引用

类型复制的是地址。

var box = 'Lee'; //在栈内存生成一个box 'Lee'

var box2 = box; //在栈内存再生成一个box2 'Lee'

图片发自简书App

box2 是虽然是box1 的一个副本,但从图示可以看出,它是完全独立的。也就是说,两

个变量分别操作时互不影响。

var box = new Object(); //创建一个引用类型

box.name = 'Lee'; //新增一个属性

var box2 = box;

图片发自简书App

在引用类型中,box2 其实就是box,因为他们指向的是同一个对象。如果这个对象中的

name 属性被修改了,box2.name 和box.name 输出的值都会被相应修改掉了。

4.传递参数

ECMAScript 中所有函数的参数都是按值传递的,言下之意就是说,参数不会按引用传

递,虽然变量有基本类型和引用类型之分。

function box(num) { //按值传递,传递的参数是基本类型

num += 10; //这里的num 是局部变量,全局无效

return num;

}

var num = 50;

var result = box(num);

alert(result); //60

alert(num); //50

PS:以上的代码中,传递的参数是一个基本类型的值。而函数里的num 是一个局部变

量,和外面的num 没有任何联系。

下面给出一个参数作为引用类型的例子。

function box(obj) { //按值传递,传递的参数是引用类型

obj.name = 'Lee';

}

var p = new Object();

box(p);

alert(p.name);

PS:如果存在按引用传递的话,那么函数里的那个变量将会是全局变量,在外部也可

以访问。比如PHP 中,必须在参数前面加上&符号表示按引用传递。而ECMAScript 没有这

些,只能是局部变量。可以在PHP 中了解一下。

PS:所以按引用传递和传递引用类型是两个不同的概念。

function box(obj) {

obj.name = 'Lee';

var obj = new Object(); //函数内部又创建了一个对象

obj.name = 'Mr.'; //并没有替换掉原来的obj

}

最后得出结论,ECMAScript 函数的参数都将是局部变量,也就是说,没有按引用传递。

5.检测类型

要检测一个变量的类型,我们可以通过typeof 运算符来判别。诸如:

var box = 'Lee';

alert(typeof box); //string

虽然typeof 运算符在检查基本数据类型的时候非常好用,但检测引用类型的时候,它就

不是那么好用了。通常,我们并不想知道它是不是对象,而是想知道它到底是什么类型的对

象。因为数组也是object,null 也是Object 等等。

这时我们应该采用instanceof 运算符来查看。

var box = [1,2,3];

alert(box instanceof Array); //是否是数组

var box2 = {};

alert(box2 instanceof Object); //是否是对象

var box3 = /g/;

alert(box3 instanceof RegExp); //是否是正则表达式

var box4 = new String('Lee');

alert(box4 instanceof String); //是否是字符串对象

PS:当使用instanceof 检查基本类型的值时,它会返回false。

5.执行环境及作用域

执行环境是JavaScript 中最为重要的一个概念。执行环境定义了变量或函数有权访问的

其他数据,决定了它们各自的行为。

全局执行环境是最外围的执行环境。在Web 浏览器中,全局执行环境被认为是window

对象。因此所有的全局变量和函数都是作为window 对象的属性和方法创建的。

var box = 'blue'; //声明一个全局变量

function setBox() {

alert(box); //全局变量可以在函数里访问

}

setBox(); //执行函数

全局的变量和函数,都是window 对象的属性和方法。

var box = 'blue';

function setBox() {

alert(window.box); //全局变量即window 的属性

}

window.setBox(); //全局函数即window 的方法

PS:当执行环境中的所有代码执行完毕后,该环境被销毁,保存在其中的所有变量和

函数定义也随之销毁。如果是全局环境下,需要程序执行完毕,或者网页被关闭才会销毁。

PS:每个执行环境都有一个与之关联的变量对象,就好比全局的window 可以调用变量

和属性一样。局部的环境也有一个类似window 的变量对象,环境中定义的所有变量和函数

都保存在这个对象中。(我们无法访问这个变量对象,但解析器会处理数据时后台使用它)

函数里的局部作用域里的变量替换全局变量,但作用域仅限在函数体内这个局部环境。

var box = 'blue';

function setBox() {

var box = 'red'; //这里是局部变量,出来就不认识了

alert(box);

}

setBox();

alert(box);

通过传参,可以替换函数体内的局部变量,但作用域仅限在函数体内这个局部环境。

var box = 'blue';

function setBox(box) { //通过传参,替换了全局变量

alert(box);

}

setBox('red');

alert(box);

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

var box = 'blue';

function setBox() {

function setColor() {

var b = 'orange';

alert(box);

alert(b);

}

setColor(); //setColor()的执行环境在setBox()内

}

setBox();

PS:每个函数被调用时都会创建自己的执行环境。当执行到这个函数时,函数的环境

就会被推到环境栈中去执行,而执行后又在环境栈中弹出(退出),把控制权交给上一级的执

行环境。

PS:当代码在一个环境中执行时,就会形成一种叫做作用域链的东西。它的用途是保

证对执行环境中有访问权限的变量和函数进行有序访问。作用域链的前端,就是执行环境的

变量对象。

6.没有块级作用域

块级作用域表示诸如if 语句等有花括号封闭的代码块,所以,支持条件判断来定义变

量。

if (true) { //if 语句代码块没有局部作用域

var box = 'Lee';

}

alert(box);

for 循环语句也是如此

for (var i = 0; i < 10; i ++) { //没有局部作用域

var box = 'Lee';

}

alert(i);

alert(box);

var 关键字在函数里的区别

function box(num1, num2) {

var sum = num1 + num2; //如果去掉var 就是全局变量了

return sum;

}

alert(box(10,10));

alert(sum); //报错

PS:非常不建议不使用var 就初始化变量,因为这种方法会导致各种意外发生。所以初

始化变量的时候一定要加上var。

一般确定变量都是通过搜索来确定该标识符实际代表什么。

var box = 'blue';

function getBox() {

return box; //代表全局box

} //如果加上函数体内加上var box = 'red'

alert(getBox()); //那么最后返回值就是red

PS:变量查询中,访问局部变量要比全局变量更快,因为不需要向上搜索作用域链。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,837评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,551评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,417评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,448评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,524评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,554评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,569评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,316评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,766评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,077评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,240评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,912评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,560评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,176评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,425评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,114评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,114评论 2 352

推荐阅读更多精彩内容

  • 谨记 当你感觉累的时候,说明你还活着,当你突然感觉不到的累那一刻,也就意味着你已经被社会淘汰了,人活着就的受累,因...
    长风留言阅读 1,296评论 3 7
  • 《ijs》速成开发手册3.0 官方用户交流:iApp开发交流(1) 239547050iApp开发交流(2) 10...
    叶染柒丶阅读 5,114评论 0 7
  • 第5章 引用类型(返回首页) 本章内容 使用对象 创建并操作数组 理解基本的JavaScript类型 使用基本类型...
    大学一百阅读 3,231评论 0 4
  • 第一章: JS简介 从当初简单的语言,变成了现在能够处理复杂计算和交互,拥有闭包、匿名函数, 甚至元编程等...
    LaBaby_阅读 1,664评论 0 6
  • ECMAScript有两种开发模式:1.函数式(过程化),2.面向对象(OOP)。面向对象的语言有一个标志,那就是...
    lovelydong阅读 647评论 0 2