前言

这篇和大家说一下javascript中的变量和作用域,由于是将基础嘛,主要给大家捋一下知识,不想翻开书复习的道友可以看一下,打算刚开始学习javascript的同学可以扫一眼。

PS:jQuery源码交流群( 239147101)等你来,群里高手云集,让我受益匪浅,尽量少灌水。

变量

javascript中有两种变量,分别是基本类型和引用类型,基本类型是Null,Undefined,String,Boolean,Number这五种,前面简单的介绍了。引用类型是指Object,Array,Date,RegExp,Function这些。创建这两种变量是类似的,都是创建一个变量然后给它赋值。不同的原因主要是在内存中位置和操作不同。

基本类型

基本类型比较简单,基本类型的值保存在栈中。看例子

var v = 1;

基本类型变量在内存中的表示,没有涉及堆

看看复制变量之后在内存中的表示,执行的代码如下

var v = 1;
var n = v;

解释一下,如果一个变量把基本类型的值复制给另一个变量时,会创建一个新的相同的值,把这个新的值赋值给新的变量,这样,内存中就有两个一样的值了,分别是新的变量和就的变量指向的值,虽然值是一样的。

引用类型

应用类型的变量创建和基本类型的创建是一样的,主要看在内存中的存储方式,代码

var obj = new Object();

可以看到,变量obj存储的是一个地址(个人的理解),其实obj的值是一个指针,指向了堆中的对象,可以找到堆中的new出来的对象。再看看复制一个变量时的情况

var obj = new Object();
var o = obj;

解释一下,这和基本类型的复制是不同的,我们可以看出,当一个变量向另一个变量复制引用类型的值时,也会将存储在变量对象中的值复制一个给新的变量。复制的这个值实际上就是一个指针,指向堆中的一个对象,由于指针是相同的,所以知指向的对象就是同一个对象,此时无论你该哪一个变量,都会影响另一个变量,因为指向的对象是用一个嘛,例如

var obj = new Object();
var o = obj;
o.name = "hainan";
console.log(obj.name);//"hainan"

而基本类型则不会,看例子

var v = 1;
var n = v;
v = 100;
console.log(n);//
console.log(v);//

这个比较简单,不懂的话看上面的那个内存的图就懂了。

区别

上面说了复制的那个区别,还有一个就是基本类型不能添加属性和方法,而引用类型则可以添加,看例子吧,很简单

//基本类型
var peo = "hainan";
peo .age = 25;
console.log(peo.age);//undefined,但是不报错
//引用类型
var people = new Object();
people.age = 25;
console.log(people.age);//

函数传参

javascript中函数参数都是按值传递的,也就是把函数外部的值复制给函数内部的参数,和复制变量一样,无论传递的是什么类型,都和复制变量一样。首先看一下传递基本类型的例子

function test(n){
return n = n+100;
}
var num = 10;
var result = test(num);
console.log(num);//10 没有发生变化
console.log(result);//

简单解释一下,调用函数时,传递一个基本类型的参数num给函数,此时,复制值给内部的参数n,这样num和n变量都有了相同的值,但是,这两个之间没有任何的关系,只是值相同而已,想想前面的图就清楚了,内部的变量也就是参数n改变了之后,num的值并没有发生改变。

接下来看看传递引用类型的例子

function test(obj){
obj.name = "hainan";
}
var people = new Object();
test(people);
console.log(people.name);//"hainan"

解释一下,其实这个也和复制引用类型变量是一样的,传递一个引用类型给函数参数时,把外部的值复制给内部的函数参数,由于是引用类型这个值是一个指针,所以外部的引用类型变量和内部的参数此时会指向同一个对象,回想上面复制的图,当内部的参数指向的对象改变时,外部的变量指向的对象一定会改变,是同一个对象嘛。

所以,现在你只需知道,传递参数和复制变量是同一回事,不会的时候回想内存中的存储方式就明白了,管它是按值还是按引用传递呢,只是一个说法罢了,呵呵,但是面试的时候可能会问,记住javascript是值传递就行了。

作用域

执行环境

每个函数都有自己的执行环境(execution context),执行环境定义了变量和函数有权访问的数据,太官方了,就是每一个函数都有自己可以访问的范围,在自己的范围内的数据才可以得到。每一个执行环境中都有一个变量对象,保存着该环境中定义的变量和函数。全局执行环境是最外面的一个执行环境,就是window对象,所有的全局变量和函数就是它的属性。每一个执行环境执行完之后,这个环境就会被销毁,里面的变量对象也就没有了,当然变量对象中的变量和函数也就销毁了。

作用域

javascript的作用域是指变量和函数可以访问的范围,分为局部作用域和全局作用域,这个和C语言是类似的,但是不同点是javascript的作用域没有块级作用域,不像C语言的{}可以表示一个块级的作用域,javascript只有函数作用域,在函数内部声明的变量只能在函数体和子函数可以访问,这个函数的外部不能访问。看例子

//没有块级作用域
if(true){
var n = 1;
}
console.log(n);// //注意
for(var i=0;i<10;++i){ }
console.log(i);//

上面的例子要是在C语言或者java中n和i会在{}语言执行完之后销毁,在javascript中可以看到,它们并没有销毁,说明并没有块级作用域。

function test(a,b){
var sum = a + b;
return sum;
}
test(1,2);//
console.log(sum);//sum is not defined

可以看出sum是在函数的外部访问不到的,因为sum函数是在函数的局部作用域中定义的,在函数执行结束时,内部的变量就会销毁,所以外部的作用域访问不到它,这就是函数的作用域。

作用域链

作用域链(scope chain)是保证在执行环境中有序的访问变量和函数,我们可以这样想,每个函数都有一个自己的执行环境,这个执行环境的嵌套就像套娃是一样的,大的套小的,内部的执行环境的变量有权访问外部的执行环境的数据,而外部的不可以反问内部的,所以当内外的执行环境中都有一个相同的变量或函数时,你是先访问哪一个呢?所以就有了作用域链这个概念。这个作用域链的每一个节点是一个变量对象,函数中有一个活动变量对象的概念,刚开始时只有函数的arguments对象,之后会把当前的变量对象中的变量和函数复制到活动对象中。作用域链的第一个变量对象是活动对象,之后就是下一个包含环境,之后是包含环境的包含环境......直到全局执行环境的变量对象。 看例子可能大家会明白

function test(a,b){
var sum = a + b;
return sum;
}
var s = test(1,2);

分析上面的这段代码,在未调用test()函数之前,看看作用域链情况

在未执行函数的时候,可以看到函数的作用域链只用一个全局的变量对象,里面有window和test函数等,在执行var s = test(1,2);语句的时候,作用域链会发生变化,会增加一个函数的活动对象到作用域链的前面,这个活动对象的初始值只有函数的arguments对象,之后会把函数的内部变量等复制到这个活动对象中,请看下面的图

这就是函数的作用域链,以后要访问某个变量的时候,会沿着这个作用域链进行查找,即沿着活动对象->外部函数的活动对象->外部函数的外部函数的活动对象->......->终点的全局执行环境,在这期间在某个活动对象中内部有这个值就会返回这个值,这个过程就会停止,不在进入另一个执行环境中,看个例子

//全局变量
var color = "red";
function getColor(){
//内部变量
var color = "blue";
return color;
}
console.log(getColor());//blue

看到这里大家会明白了。

PS:其实javascript的闭包和作用域链有很大的联系,这里咱不讨论,闭包会单独讨论。

小结

这就是javascript的作用域了,主要大家还是好好看看变量内存那块,分析几个就会了。注意一下javascript没有块级作用域这一说法,这点大家要小心了。最近几天天天在群里看大家的聊天记录,论文也不想写了,哎,坐等回家吃猪肉了,希望老师别鄙视我。

【javascript基础】3、变量和作用域的更多相关文章

  1. Javascript基础回顾 之(二) 作用域

    本来是要继续由浅入深表达式系列最后一篇的,但是最近团队突然就忙起来了,从来没有过的忙!不过喜欢表达式的朋友请放心,已经在写了:) 在工作当中发现大家对Javascript的一些基本原理普遍存在这里或者 ...

  2. JavaScript基础学习-函数及作用域

    函数和作用域是JavaScript的重要组成部分,我们在使用JavaScript编写程序的过程中经常要用到这两部分内容,作为初学者,我经常有困惑,借助写此博文来巩固下之前学习的内容. (一)JavaS ...

  3. JavaScript基础03——函数的作用域及变量提升

    1.作用域 作用域,变量在函数内部作用的范围/区域.有函数的地方就有作用域.   2.局部作用域和全局作用域 function fn(){ var a = 1; } console.log(a); / ...

  4. javascript基础语法——变量和标识符

    × 目录 [1]定义 [2]命名规则 [3]声明[4]特性[5]作用域[6]声明提升[7]属性变量 前面的话 关于javascript,第一个比较重要的概念是变量,变量的工作机制是javascript ...

  5. 一篇文章带你了解JavaScript中的变量,作用域和内存问题

    1 在JavaScript中的变量分别区分为两种: 一种为基本类型值,一种为应用类型值. 基本类型值指的是简单的数据段 引用类型值为可能由多个值组成的对象 引用类型的值是保存在内存中的对象,JavaS ...

  6. JavaScript基础——定义变量

    在JavaScript中使用变量来临时存储和访问来自JavaScript文件的数据.变量既可以指向简单的数据类型,如数字或者字符串:也可以指向更复杂的数据类型,比如对象. 在JavaScript中定义 ...

  7. JAVA_SE基础——10.变量的作用域

    <pre name="code" class="java"> 上个月实在太忙了,从现在开始又可以静下心来写blog了. 变量的作用域指 可以使用此变 ...

  8. C语言基础之变量、作用域

    1.变量的定义 变量类型 变量名; int score; 2.变量的赋值 score = 100; score = a; score = b = 100; 3.变量的输出 int a = 200; p ...

  9. JavaScript基础——理解变量作用域

    一旦你开始在JavaScript应用程序中添加条件.函数和循环,就需要理解变量作用域.变量作用域规定了如何确定正在执行的代码行上的一个特定变量名的值. JavaScript允许你既定义全局版本又定义局 ...

  10. javascript中的变量、作用域和内存问题

    1.变量 变量的值的类型:基本类型值和引用类型值两种. 基本类型:Undefined.Null.Boolean.String.Number,这五类基本数据类型的值在内存中占有固定大小的空间,因此保存在 ...

随机推荐

  1. .htaccess根据IP地址限制访问

    屏蔽IP地址 屏蔽IP地址有时是非常必要的,比如对于一个外贸公司网站,来自国内的访问是不会带来任何经济效益的,而且还占用服务器资源,造成访问延迟等问题. 如果要屏蔽某一特定IP可以使用: order ...

  2. hdu 1041 (OO approach, private constructor to prevent instantiation, sprintf) 分类: hdoj 2015-06-17 15:57 25人阅读 评论(0) 收藏

    a problem where OO seems more natural to me, implementing a utility class not instantiable. how to p ...

  3. IOS时间传递机制简记

    事件传递顺序:自定义View -- > UIview --> RootViewController --> UIWindow -->UIApplication -->Ap ...

  4. Python开发入门与实战4-模板页面

    4.Django基于模板页面 在前一章中,HTML是直接被硬编码在 Python views.py代码中,如下: from django.http import HttpResponse import ...

  5. 学习笔记之 prim算法和kruskal算法

    ~. 最近数据结构课讲到了prim算法,然而一直使用kruskal算法的我还不知prim的思想,实在是寝食难安,于此灯火通明之时写此随笔,以祭奠我睡过去的数 据结构课. 一,最小生成树之prim pr ...

  6. Android中Service的使用

    我个人的理解是:我们平时使用的android系统的app的后台应用,就是这个原理 可以利用Service实现程序在后台运行,依照这个原理,可以通过Service来实现关键代码的运行与实现. <一 ...

  7. Divisors

    计算小于n的数中,约数个数最多的数,若有多个最输出最小的一个数. http://hihocoder.com/problemset/problem/1187 对于100有 60 = 2 * 2 * 3 ...

  8. UVA 10173 (几何凸包)

    判断矩形能包围点集的最小面积:凸包 #include <iostream> #include <cmath> #include <cstdio> #include ...

  9. 大数据批量插入数据库使用(SqlBulkCopy )效率更高

    SqlBulkCopy类是System.Data.SqlClient下的类,我们开发中不常用,甚至不知道有这么一个类的存在,但确实比sql插入,事务批量插入,sql批量拼接插入快很多,比调用存储过程插 ...

  10. GT 940M 到底怎么样! 768的可以 1080的不要用了

    而对于目前的市场来看,NVIDIA独显无疑是占据了产品端的绝对主力,9系列独显也已经全面上市,但除了大家熟悉的GTX级之外,入门级的更新也同样对入门级玩家有着至关重要的意义,其中最具代表性的莫过于今天 ...