这个问题很基础了,其实在JavaScript中变量和属性的含义跟其他命令式的语言(纯函数式语言没有变量)没有区别。
其实变量和属性的共同点很明显,就是都可以存储数据,并且可以通过一定的途径来访问,大部分的情况下,我们也都是这么使用它们的,但是随着对JavaScript学习的深入,问题就随之而来了,那么它们有什么区别呢?它们是一样的吗?
下面我们看看它们的主要区别:
为了方便描述,我们给变量取名叫variable, 给属性取名attr,并且指定一个前提:JavaScript只有函数是可以运行的,也就是说全局范围内写的JavaScript代码我们都假定它们写在一个浏览器提供的最外层的函数里面。
1. 定义方式
a.变量是在函数定义中通过var variable定义的
这里面需要注意两点,一个是变量只在函数定义中声明,当然这里我们用了前面假定的前提。二是只能通过var关键字来定义。
b.属性是通过this.attr或者objName.attr来定义的,或者attr定义的(.操作符可以换成[""])
2. 访问方式
2.1 可访问性
a.变量:闭包中包含此变量的函数可以对此变量进行访问(后续文章会对此作出更详细的解释)
b.属性:只要有对象的引用(包括this),就可以通过对象来访问属性
2.2 delete操作
a.变量不能被delete
b.属性可以delete
3. 归属
a. 变量:归属于执行上下文(Execution Context)的变量对象(Variable Object)
b.属性: 归属于所在对象
下面就归属问题详细聊一下。
总是感觉JavaScript研究深入的时候,有很多刚入门的时候看似很简单,很浅显的问题,追究起来,就变得不那么简单了。
属性其实比较简单,它就归属于它所在的对象,不管在什么场景,什么情况下,对象内部都可以通过this.attr来定义或访问变量,对象外部都可以通过对象的引用 objName.attr来定义或访问变量。
而变量就相对复杂一些,从外面看来 var attr就声明了一个变量,如果当前函数的作用域链中有attr,就可以访问。如果对Execution Context有了解的话就会知道,其实就会知道变量其实也是一个特殊的属性:变量对象(VO)的一个属性。
如果变量其实也是一个属性的话,那么它如何被访问就很明显了,谁能访问VO,谁就能访问到变量。 那么谁能访问VO?不考虑global的话,就是函数执行的时候,函数的作用域链上有属性所在的VO的话,那么函数就可以访问这个属性。
总结:
其实变量和属性本质上都是属性,只不过在JavaScript引擎上访问它们的方式不一样,可见对象的属性是JavaScript本身提供给开发者的一种访问方式,而变量其实是JavaScript引擎内部不可见对象的属性,所以只能通过JavaScript引擎提供的其他方式来访问,
也就是通过在执行函数时JavaScript引擎自动从函数所在闭包中查找变量的方式来访问。
两个潜规则 = 一个有趣的事情:
1.如果单独声明变量,那么默认会声明称全局对象global的属性。
2.全局对象global的VO是它自己。按照上面我们的结论,变量和属性一个是可见对象的属性,另一个是VO的属性,那么对于global来说,VO是它自己,也就是说它的VO是对外可见的。那么会发生什么事情?
一个有趣的事情:
//浏览器下global是window
var a = "a";
b = "b";
alert(window.a) ; //a
alert(window.b); //b
是不是每本JavaScript的书上都有这样的例子?都会告诉你这是JavaScript的一个规则?但是这是为什么?
现在知道为什么a和b都是window的属性了吧,a是因为它在预执行阶段被放到了VO的属性里面,而VO是global;b是因为它没有指定对象,所以默认声明到了global上。