Maison > Questions et réponses > le corps du texte
<script>
var a=1;//全局环境下,用var声明一个全局变量
var b=function(){a=3}();//函数内的a没有用var声明
alert(a);//a的值为3
alert(delete a)//false
</script>
“如果你没有使用严格模式并给一个未声明的变量赋值的话,JS会自动创建一个全局变量。以这种方式创建的变量,是全局对象的正常可配置属性,并可以删除它们。”--------犀牛书6版,58页。
var b=function(){a=3}() 内的a没有用var声明,那么应该创建一个可配置的全局变量。但是全局环境有一个变量a,并且是用var声明过的。
按照我这个初学者的认识:
var b=function(){a=3}() 内的a应该覆盖掉全局环境下a的值,并且a应该是可用delete删除的。情况a的值确实变为3了,但delete a却不可以,请问这是为什么?谢谢。
高洛峰2017-04-10 15:23:24
首先,上个例子:
a = 1 // 1
this.a // 1
window.a // 1
delete a // true
var b = 2// 2
this.b // 2
window.b // 2
delete b // false
好,从例子看以看出,未通过var声明的变量a和通过var声明的变量b,都可以通过this和window访问到,区别是一个可以被delete,一个不可以,下面分析下:
为什么delete的结果不同?
因为(在全局下)通过var 声明的变量是全局变量,而未通过var声明的变量是附在this,也就是window上的属性,而属性是可以被删除的。
为什么他们都可以被this和window访问到?
在浏览器中,所以的变量都是存在于window下的,所以可以被window访问到;
而this是指向window的一个引用,未通过var声明的变量通过附在this上,达到可以全局访问的效果。
下面说说你的例子
var a = 1 // 全局都可以 window、this
a = 3 // 全局都可以 window、this 覆盖上一个a的值 现在a是3
delete a // 虽然值被覆盖了,但是a毕竟是通过var声明的,所以无法删除,所以是false
阿神2017-04-10 15:23:24
“如果你没有使用严格模式并给一个未声明的变量
赋值的话,JS会自动创建一个全局变量。以这种方式创建的变量,是全局对象的正常可配置属性,并可以删除它们。”--------犀牛书6版,58页。
<script>
var a=1;//全局环境下,用var声明一个全局变量
var b=function(){a=3}();//函数内的a没有用var声明
alert(a);//a的值为3
alert(delete a)//false</script>
var a = 1
已经在全局执行上下文中声明了变量 a
,并且赋值为 1
. 所以不符合书中描述的条件!
var a;
这条语句一执行,window
的属性a
对应的属性描述符对象(property descriptor)就确定了:
// in brower console
var a;
Object.getOwnPropertyDescriptor(window, 'a'); // {value: undefined, writable: true, enumerable: true, configurable: false}
configurable: false
就意味着 不能删除!
伊谢尔伦2017-04-10 15:23:24
js变量的作用域需要涉及到作用域链,如:http://www.cnblogs.com/lhb25/archive/2011/09/06/javascript-scope-chain...
1、函数运行时会有一个执行上下文,函数里用到的变量先去一个叫做活动对象的作用域查找该变量是否在这个类似“堆栈”的作用域链;
2、如果没有,则再去一个叫做全局对象的作用域链查找该变量;
3、每次使用变量都会重复去查找一次这个作用域链,所以为了在循环中提高代码效率,尽量将全局变量赋值给一个局部变量,解决全局变量在反复查找过程中带来的效率(全局作用域链在局部作用域链下面)
黄舟2017-04-10 15:23:24
function里面的a = 3并没有像你说的那样重新创建一个变量a并且覆盖掉以前的var a;在function里面出现对a的引用,会在函数作用域里面寻找a的定义,没有找到则在函数的作用域链的下一层即global里面寻找。找到a之后对a重新赋值为3。delete的语境等价于var a = 3;delete a;当然是false。如果你把function里面的a换成是c或者其它未定义的变量再delete c,就是true.关于作用域,执行环境的相关部分我建议阅读《Javascript 高级程序设计》的第四章。
阿神2017-04-10 15:23:24
因为a
不是一个隐式声明的变量!
// 隐式声明变量
a = 1;
delete a; // true
// 显示声明变量
var a = 1;
delete a; // false
返回值:在严格模式中,如果属性是一个不可配置(non-configurable)属性,删除时会抛出异常,非严格模式下返回 false。其他情况都返回 true。
MDN delete
所以说a=3
只是把全局变量的a
给覆盖了!
高洛峰2017-04-10 15:23:24
a已经被var声明了,所以是不能够被删除的,但是 var b=function(){a=3}();后面加了一个小括号是怎么回事?匿名函数?
天蓬老师2017-04-10 15:23:24
@qianjiahao 已经说的很好了
使用var 是声明变量,声明变量自带不可删除属性,而非var 产生的变量为window的属性,所以可以删除