javascript 的一点疑问

fcxh
  • 434
var i = 0;
function fun() {
    alert(this.i);
    var a = 10;
}
fun(); // 0  --------------------------------1
alert(fun.a); // undefined ------------------2
  • 1处: 为0我的理解是在i绑定在window对象中,当执行fun()时,this.i 相当于 window.i, 换句话说,i 是作为window对象的一个属性

  • 2处: 那么,按照1处的理解,我觉得在在fun函数的内部,变量a也应该是作为函数这个对象的一个属性,因此,我试着alert(fun.a),结果却 undefined 为什么?,

-----------------------------问 题 更 新 ---------------------------
看了大家的回答,我是这样理解的:变量a仅仅是函数局部作用域的一个局部变量而已,并非它的属性。随着fun函数的执行而创建,随着fun函数执行完毕而销毁。

我理解了结果,同时疑问也并没有消失!
我的疑问是:

  • 变量i作为window对象的一个属性,那么a也应该是fun的一个属性。

或者

  • 变量i仅仅作为全局变量,而不是window对象的属性,这样a作为一个局部变量

可事实是:

  • 变量i是window的一个属性,a却仅仅是fun局部作用域中的一个局部变量

这就是我不理解的地方,难道是我过分追求这种“统一”的和谐思想吗?


回复
阅读 3.3k
10 个回答
✓ 已被采纳

第一点是对的。

第二点,你要分清局部变量和对象属性的区别。var a = 10;是局部变量,fun.a = 10fun作为对象的属性。两者没有半毛钱的关系。


函数其实也是对象的一个实例:

Function instanceof Object;//true

所以所有的函数,不管是通过Function构造还是自定义函数,也都是Object的实例。

var func = new Function();
func instanceof Function;//true
func instanceof Object;//ture

所以,函数是可以作为对象定义属性和方法的!

function fun() {
    var a = 10;
    fun.b = 11;
}
fun();
alert(fun.a); // undefined
alert(fun.b); // 11
console.log(fun.hasOwnProperty('b')); //true

可以看到,b确实是fun本身的属性。


----------------更新分割线----------------


@fcxh

作用域!

通过var这个关键字,将变量与它所储值的位置进行了绑定。

在全局作用域使用var初始化变量,这个变量就会储存在全局变量的内存中,在浏览器中只要不关闭网页,全局变量所在内存的变量都不会被销毁。

在函数内部使用var,变量会储存在‘临时’的内存中,当函数运行完毕后(不考虑闭包),这块内存中所有的变量都会被销毁。

全局变量,局部变量不是从属的关系,它们占有不同的内存空间。语言中各种各样的设计都有它足够充分的理由,不只是要‘统一和谐’这么简单。

var i = 0;
function fun() {
    console.log(this.i);//[1]
    var a = 10;//[2]
}
fun(); // 0  --------------------------------1
alert(fun.a); // undefined ------------------2

1.this的具体值以调用的不同方式,很导致不同的的结果,不一定就是全局对象

fun.call({i:'1234567890'});//输出为1234567890

2.函数也是对象,同样可以对其设置属性,其也有方法,例如call、apply方法
3.[2]处的代码只是在一个函数体的内容声明了一个局部变量,这个变量在fun函数执行完毕后就会被销毁掉,在func函数声明的时候变量a只是一个声明,不指向任何具体的值~~~这个变量不是fun函数对象的一个属性,只是其作用域链上的一个变量声明
4.fun函数对象上目前不存在属性a,所以fun.a的输出为undefined

因为你的fun是函数 不是对象

本以为你问了一个声明提前的问题
写完了发觉不对。。。貌似你还不知道ao/vo对象


fun是一个函数,你fun.a这样的写法是什么意思??函数肯定没有属性。。所以肯定是undefined

说下我的理解,请大牛斧正:
1处:this未指明绑定到哪个作用域,所以默认就是绑在window作用域上的,this.i就指向了window作用域下的i变量;
2处:虽然函数在js里是first class,但是a只是fun函数作用域下的一个局部变量而并不是成员,所以fun.a必然是undefined。


貌似题主陷入了死循环啊……
这么说吧,i是在window作用域下声明的(var声明函数作用域),放眼望去的代码都在window地盘下,所以谁想访问就能访问一下;但是你的a是在fun函数的作用域下声明的,你想访问?对不起请先入瓮(fun作用域)了再说~
一般的函数,如果是在函数内部声明的变量,都是private(私有)的,而你得用显式的用构造语法声明出来(比如fun.a = 10;)这种或者上闭包,才是 public(公有)的。

1.在浏览器环境中,window是你的全局对象,你定义的全局变量都会成为全局对象的一个属性,即:

var i = 0;
this.i = 0;
window.i = 0;

他们是等价的。
2.局部变量不会转换为任何对象的属性,但你可以为函数对象添加属性:

function fun() {}
fun.a = 10;

如果你没有明确定义这个属性,那么当然会得到undefined

全局运行上下文和局部运行上下文是不一样的,而且这个在网页上和在 Node 里的实现都不一样。
正是由于各种不确定因素,在 strict 模式下,像你这样在 function 中直接使用 this 是不允许的……

我刚刚的回答是错误的,更改一下。其实当你调用执行的时候 函数实际是添加了 a这个方法的是,但是因为调用执行完了之后就自动销毁了,所以等你在弹出的时候,实际上已经没有a这个属性了,所以undefined;对象跟函数还是相当有区别的 推进你看http://www.cnblogs.com/wangfupeng1988/p/...

看看函数的静态属性与方法

试着答一下。

var i = 0;

这句代码,你的理解“变量i仅仅作为全局变量,而不是window对象的属性”是正确的又是不完整的:

正确的是:i是全局上下文的变量;
不完整的是:i同时也是全局上下文中vo的属性,而vo===window(为什么,看下面的解释),所以i也是window的属性(即可以使用window.i);

解释:

ES的实现器(比如浏览器)在进入全局上下文之前,会创建一个全局对象global(并给它初始化了一些属性:比如MathStringDateparseInt等,以及一个指向全局对象自己的属性(在浏览器里是window)),并将global赋值给全局上下文的vo。也就是:

声明全局变量,即给vo添加属性,而vo===global===window,所以window也可以访问到该属性。

程序执行完var i = 0;之后,全局上下文如下:

//全局上下文
globalContext = {
    //vo===global
    vo: {
        Math: <...>,
        String: <...>,
        ...
        ...
        window: global,
        ...
        ...
        i: 0
    }
    ...
}

但是函数并没有这样的待遇,所以在函数内部声明的变量,只是存在于函数的作用域,并不能作为函数的属性访问。
(第一次答题,有错误的地方请一定指出,喷也可以,希望不要误导别人)

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
宣传栏