<html>
<head>
<title>变量作用域</title>
<script type="text/javascript">
/*
变量的作用域分为普通变量和引用变量
对于普通变量,变量里只是保持着某个具体
的值,对于引用变量,引用里只是保存对某
一个变量的引用,或者只是保存内存中某个
区间的地址,对于普通变量,当我们对其值进行
复制的时候,两个变量完全是独立的,各自操作
互不影响,但是,对于引用变量,进行复制后,两个
变量都是引用的同一个对象,因此在操作的时候,会
对另外的复制引用的变量的值产生影响,如下:
*/
//对于普通的变量
function print(str){
document.write(str+"<hr>");
}
var var_1 = 'felayman';
var var_2 = var_1;
print('var_1 = '+var_1+',var_2 = '+var_2);//var_1 = felayman,var_2 = felayman
//当我们对其中一个进行修改,另一变量值是不会受到影响的
var_2 = 'felayman1';
print('var_1 = '+var_1+',var_2 = '+var_2);//var_1 = felayman,var_2 = felayman1
//但是对于引用变量,则在复制后会产生影响
var obj1 = new Object();
obj1.name = 'felayman';
print('obj1.name = '+obj1.name);//obj1.name = felayman
var obj2 = obj1;
obj2.name = 'felay';
print('obj1.name = '+obj1.name+'obj2.name = '+obj2.name);//obj1.name = felayobj2.name = felay
/*
对于参数的传递
只有一个规则,就是按照值传递,与变量的访问不同,ecmascript不存在象其他语言一样的参数可以引用
*/
var name = 'felayman';
print(name);//全局变量 打印为felayman
function transport(name){
name = '小熊猫';//虽然改变了参数的内容,但是name的定义初始化值并没有发生改变依然是felayman
print('参数:'+name);
}
transport(name);//小熊猫
print(name);//felayman,说明,在函数内部是无法修改引用变量所指向的变量的,但是可以通过返回值的方式,获取到我们象修改的值
function return_var(name){
name = '小熊猫';
return name;//虽然没有修改name所指向的值,但是,获取到我们想要的name修改后的值
}
name = return_var(name);
print(name);//小熊猫
//下面对对象进行测试
function setName(person){
print(typeof person);//其实这里,我也比较困惑,为什么js引擎为什么会在这里判断出,person的类型是object
person.name = 'felayman';
person = new Object();
person.name = 'felaytest';
print(person === person);
}
var person = new Object();
setName(person);
print(person.name);//这里依然是felayman
print(person instanceof Object);
/*
很多人比较困惑,不是在setName函数中将传入的参数的name值变为felaytest么,为什么还会输出felayman呢?
不过也说明一个问题,那就是ecmascript的参数不存在引用传递,因为引用变量person指向的内容并没有发生变化
或者这么说,当参数按照值来传递的话,即在person被初始化的时候,它指向的是是在全局变量中定义的对象,而且
这个person一旦指向该对象,指向就步不会上变化,及时在函数中,函数的参数被实例化,但是person指向是不变的
因此,它的属性也不会发生变化.如果你曾经编写过OOP语言,则不要纠结于为什么会这样,这只是ecmascript的创造
者为了突出与其他语言的区别吧
*/
/*
ecmascript的执行环境和作用域
有时候去细心研究ecmascript的执行环境和作用域是一件特别振奋和受挫的一件事,我们经常会在它的作用域的特殊性中
找不到出口,有时候当你发现一些玄机的时候,又会觉得这么语言相比于其他的语言,的确尤其出色的地方,ecmascript的作
域与其他语言有很大的不同,其他语言的作用域都是以块为单位的,但是ecmascript的作用域却是一个链,每个链都会有一个
对象,而这个对象就保存着它对应链的所有定义的变量和函数。,虽然我们无法访问这个对象,但是js解析器会在后台去访问这些
对象来获取每个变量所属的作用域。例如下面的例子
*/
color = 'blue';//属于全部变量
var color = 'red';//属于全部变量
var size = 100;
print(color);//red
function getColor(){
var color = 'yellow';//属于局部变量
print(size);//undefined
var size = 1000;
print(color);
}
getColor();
/*
上面的函数中的size为什么会出现undefined呢?因为,js引擎在查找一个变量的时候,首先回去查找定义的地方,如果找到,则将变量的作用域
锁定在该链中,因此,size的作用域就在函数内部,但是执行到print(size);的时候,size还没有初始化,因此会出现未定义,因此也可以看出
js代码的查找优先原则,即ecmascript在引入一个函数的时候首先要做的是将函数内的所有变量的作用域确定下来,而非执行的时候才去确定
变量的作用域,当前这也用于所有的变量和函数。不过还有一点非常重要,就是ec,ascript中没有块级作用域,如下:
*/
var bool = true;
if(true){
if(true){
var name = 'felaman';
}
}
print(name);//felayman
print(window.name);//felayman
/*
上述代码依然能打印出name的值,尽管我使用了两个{}但是都没有锁住name的范围,name依然属于window作用域的变量,如果这个不明显的话
那么下面这个例子,则会更好的说明这个例子
*/
for(var i=0;i<10;i++){
name = 'test';
document.write(i+"\t");
}
print(i);
print(window.i);
/*
这里会得到什么呢?如果是其他语言的话,会报错的,但是在js中,这个i是全局变量,真的很意外,因此很多熟悉js的人,在定义循环
的时候,往往会吧循环定义在函数内部,用闭包的形式来避免循环变量的冲突,如下
*/
function for_statement(size){
for(var j=0;j<size;j++){
name = 'test';
document.write(j+"\t");
}
document.write('<br/>');
}
for_statement(10);
//print(100);
print(j);
print(j+'?');
/*
也许上述会有人认为会打印出undefined,其实我也是这么想的,不过很遗憾,什么都不会出现,为什么呢?这由于是我的错误,因为我在
定义print()函数的时候,接受了一个参数,可惜,这里我传入的参数j,定义的函数无法获取到j的值和类型,因此,当浏览器解析到该语句
document.write()的时候,就会出现错误,但是浏览器为了不影响用户体验,往往会隐蔽这种错误,只有我们开发人员进行调试的时候才会
去发现错误地方。谷歌浏览器会出现这样的错误:Uncaught ReferenceError: j is not defined,如果是IE的话,会出现这样的错误:
SCRIPT5009: “j”未定义,而firefox呢?ReferenceError: j is not defined。可看出主流浏览器对该类型的错误提示差不多。
IE9一下的浏览器会直接在页面上显示出现脚本错误的。
*/
</script>
</head>
</html>
分享到:
相关推荐
ECMAScript Fifth Edition Implemention in Object Pascal
ECMA-262 规范 第五版 英文版
ECMAScript Language Specification
Learn all the new ES6 features and be among the most prominent JavaScript developers who can write effcient JS programs as per the latest standards!
Javascript standard
learning_ecmascript_6 Curso y Conceptos de Javascript-Ecmascript(ES6) Uso de nodeJS,NPM,Babel TEMAS ¿声明变量吗? 在变量中使用的变量。 JavaScript声明变量的声明:var,let,const。 埃瓦卢阿瓦...
es6简介,针对es6的简单介绍。
主要介绍了ECMAscript 变量作用域,通过使用var操作符声明和未使用var操作符声明两种情景做出了解释,具体操作步骤大家可查看下文的详细讲解,感兴趣的小伙伴们可以参考一下。
作用域分配与变量访问规则 在 ECMAScript 中,函数也是对象。函数对象在变量实例化过程中会根据函数声明来创建,或者是在计算函数表达式或调用 Function 构造函数时创建。(关于’函数对象’请见《理解Javascript_08_...
ECMAScript Cookbook_Code 源码 本资源转载自网络,如有侵权,请联系上传者或csdn删除 查看此书详细信息请在美国亚马逊官网搜索此书
主要介绍了ECMAScript6块级作用域及新变量声明(let) 的相关资料,需要的朋友可以参考下
[React_JS][ES6][前端教學]_ES6#01._EcmaScript_2015_ES6與之後的版本相容性介紹,為什麼
ECMA-262简述 ECMAScript语言概述 ECMAScript对象概述...ECMAScript执行环境(作用域链Scope Chain,闭包机制) ECMAScript函数(new原理) ECMAScript内部属性(参考) ECMAScript执行环境作用域链图示 ECMA-262参考资料
es6标准入门pdf,es6学习必备,下载的txt文件有链接,可自行下载。注意:1.本PDF仅限用于个人获取知识。2.如觉得书籍内容很赞,请购买正版实体书,支持作者。
公用、受保护和私有作用域 在传统的面向对象程序设计中,主要关注于公用和私有作用域。公用作用域中的对象属性可以从对象外部...对ECMAScript讨论这些作用域几乎毫无意义,因为ECMAScript中只存在一种作用域——公用作
ECMAScript2021中文最新,ECMAScript2021中文文档,第1-6章,持续更新,喜欢请star。git地址https://github.com/fangniyima/ECMAScript-notes
JavaScript是一种最初由Netscape的LiveScript发展而来的面向对象的Web脚本语言,被ECMA国际定义为国际化标准——ECMAScript。JavaScript具有使用局限性。在Web方面,其必须与各种DOM技术结合才能发挥作用。因此,...
ECMAScript 6 入门 高清扫描