JavaScript 变量、作用域、内存

简略草稿简记(重点简记)

基本类型和引用类型

    其实这部分我们就是在讨论Object类型(引用类型)和其他类型(Null、String、Number、Undefined、Boolean)的一些操作的区别。

    ECMAScript标准包含两种不同的数据类型:基本类型值引用类型值

    引用类型值 是保存在内存中的对象,JavaScript不允许直接访问内存中的位置,即不能直接操作对象中的内存空间。(像C语言那样直接通过访问内存来改变变量?)
    所以,对基本类型的操作,就是对保存在内存中的实际值的操作,但是对引用类型值的操作就是对对象引用的操作

var person = new Object();//引用类型
person.name = "Nicholas";
alert(person.name);

var name = "Nicholas";//基本类型
name.age = 27;
alert(person.name);

    我们来对比一下以上的代码段:
    第一个代码段首先定义了一个新的对象(或者说我们常说的C语言中的类),可以理解为这是一个空对象,我们并没有对其进行任何初始化。之后我们可以动态的向其中添加属性,比如以上的name属性,并且可以直接为其进行初始化。这种操作是有效的
    第二个代码段我们首先定义了一个变量(基本类型String),之后为其添加属性age,但这种操作是无效的

拷贝操作

    对于基本类型操作就是和C/C++相同,考赋值拷贝就是开辟一个新的内存空间,两个值分别是不同的对象,占用内存不同位置,对一个对象的改变不会影响另一个。
    但对于Object类型则不然,实际上是对引用的拷贝,入下,拷贝后,对一个对象的操作会影响另一个,因为实际上二者占用的是同一内存空间。实际上是对指针的副本拷贝。

var obj1 = new Object();
var obj2 = obj1;
obj1.name = 'ctr_temp';
alert(obj2.name);

实际上打印出的是'ctr_temp'
可见,对其中一个对象的改变影响了另外一个Object对象。

参数传递

    这部分是关于函数参数传递的讨论,其实发现很多部分还是要借鉴关于C/C++的前景知识,这部分理解起来很快。
    C++中介绍了关于传引用以及传值的两种传参区别,这里JavaScript只有一种方式进行参数传递:值传递
    对于基本类型,由于无法通过访问内存空间地址来访问变量,我们同样无法通过传指针(其实也是传值的一种)来间接的访问改变传入的实参。

function num_add(num)
{
	num+=10;
	return num;
}
var count = 100;
var count_add = num_add(count);
alert(count);//打印出来是100,原值没有改变
alert(count_add);//打印出来是110

    对于Object类型(引用类型),我们需要着重理解一下:对于引用类型我们其实也是传值。

function set_Name(obj){obj.name = 'ctr_temp';}
var person = new Object();
set_Name(person);
alert(person.name);//打印出来是ctr_temp,被改变了!!!

    以上看来,似乎对于引用类型的传参是传引用了!实则不然,我们来回忆一下传值传参的基础:实际上传值传参是先对实参进行一个拷贝,用拷贝后的临时值对形参进行初始化。
    再加上刚刚第一部分的知识:对于Object类型的拷贝实际上是对指针进行副本拷贝,拷贝和被拷贝赋值的对象指向的是同一个内存地址,那么即使是传值,我们也可以通过这种方式对传入的引用类型实参进行改变。方便立即不如看看以下的实例。

function set_name(obj)
{
	obj.name = "ctr_temp";
	obj = new Object();
	obj.name = "CTR_Temp";
}
var person = new Object();
set_name(person);
alert(person.name);
可想而知,如果按以上的方式进行传值操作,我们得到的应该是"ctr_temp"
因为之后创建的新对象(开辟新空间)其实是一个局部变量,函数结束后即销毁,
而我们想要访问打印的还是原始对象。
(当然,如果是传引用操作的得到的就应该是"CTR_Temp"了)

检测类型

    主要介绍instanceof操作符,用来返回变量类型是否是引用,如果是引用类型就返回true。

instanceof

执行环境以及作用域

    其实就是类似于C/C++关于局部变量以及全局变量的一个讨论!局部作用域以及全局作用域,屏蔽以及访问的优先级关系!

var color = 'yellow';
//这里,在最外层作用域,你可以访问color
function search_color ()
{
	var ano_color = 'orange';
	//在这里,相对内层一些的作用域,你可以访问 ano_color以及color
	function swap_color()
	{
		var color_temp = 'red';
		//在这里,所有外层内层定义的变量都是可以访问的
	}
	//可以访问 color,ano_color
	any_func();
}
//只可以访问color
search_color();

    在这里,内部属于子执行环境,其外部都是其父执行环境,子执行环境可以访问一切其上级的父执行环境中定义的变量,反之则不允许。

关于延长作用域链

    这里涉及with语句以及 try-catch语句,暂时不提

关于块级作用域

    之前关于JavaScript的blog中提到过,JavaScript中不涉及块级作用域这个概念,在语句块内部定义的语句在外部是可以访问到的(当然不是函数中定义的那种),如下for语句和if语句的示例:

以下的两个语句块,内部定义的变量在外部仍可以被访问到
if(true){var color = 'blue';}
alert(color);

for(var index = 0; index<100; ++index)
{/*...*/}
alert(index);
function add(num1, num2)
{
	var sum = 0;
	sum = num1+num2;
	return sum;
}//对于此函数,sum对于外部是不可以访问的
function add_ano(num1, num2)
{
	sum = num1+num2;
	return sum;
}//这种定义形式的sum(没有var关键字),外部可以访问sum
//sum被默认为是一个全局变量
注意:我们不建议以上的第二种写法!!!

查询标识符

    实际上是一种对变量的查找索引方式,如下例子可以很好的说明:

var color = 'blue';
function find_color(){return color};
alert(find_color());//返回blue

    程序执行时,首先从当前的作用域(子作用域,这里就是函数内层作用域)进行搜寻,无法找到color对象时开始向上层作用域进行搜寻(这里就是全局作用域),找到后返回‘blue’,搜索过程结束。
    即,搜寻过程逐级向上,内层能够搜索到就停止继续向上搜寻。这样来看,与C/C++相同,内部定义使用的变量对象,将会隐藏外部的同名定义!

内存管理——垃圾收集

    对于C/C++之类的语言来说,开发人员的一个基本任务就是手工跟踪内存的使用情况(造成一些问题的根源)。
    这部涉及内存管理的问题,当我学完C++相关部分后,再来对此部分进行补充(目前先进行浅显的简要理解)。

待解决问题

1、对于我想在函数内部(内层作用域)访问外部(外层作用域)的对象的情况,应该怎样做呢?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值