原文地址:http://dmitry.baranovskiy.com/post/91403200
看了文章中五个小例子,写了写自己的理解
#demo1
if (!("a" in window)) { var a = 1; } alert(a);
#demo1 主要用到javascript执行时候的预解析(变量声明提前),进入执行上下文的时候,解释器会把当前上下文中所有的函数声明、变量声明、函数形参提前,对象变量的状态大体如下:
var a; //等同于 var a = undefined; if (!("a" in window)) { //if不会成立 a = 1; } alert(a);//undefined
#demo2
var a = 1, b = function a(x) { x && a(--x); }; alert(a);//1
#demo2中,function a的定义采用函数表达式的方式,表达式的方式定义的function和声明式定义function最大的区别是函数表达式不会影响对象变量(VO),即不会对前面定义的变量a产生任何影响,a的调用会通过b这个引用来进行(a()可以在函数内部使用,递归或者内部执行)。比如引申一个demo:
function test(a, b) { var c = 10; function d() {} var e = function _e() {}; (function x() {}); } test(10); // call
test()执行的时候上下文对应的变量对象如下:
AO(test) = { a: 10, b: undefined, c: undefined, d: <reference to FunctionDeclaration "d"> e: undefined };
可以看到,AO里并不包含函数“x”。这是因为“x” 是一个函数表达式(FunctionExpression, 缩写为 FE) 而不是函数声明,函数表达式不会影响VO。 不管怎样,函数“_e” 同样也是函数表达式,但是就像我们下面将看到的那样,因为它分配给了变量 “e”,所以它可以通过名称“e”来访问
#demo3
function a(x) { return x * 2; } var a; alert(a);//function a{…}
#demo3还是有关变量对象的组成,当函数被调用,进入执行上下文期间,解释器对变量对象的操作如下:
>1. 函数形参作为VO的key,对应的value是实参,没有实参初始化为undefined
2>.函数声明(不包括函数表达式), function 名作为key,值为对函数的引用,如果已存在相同名称的变量,则完全覆盖
3>.变量声明,key为变量名,值初始化为undefined,如果已存在相同名称的函数声明或者形参,则不会干扰这些已存在的属性
所以var a 不会对function a()产生影响
#demo4
function b(x, y, a) { arguments[2] = 10; alert(a); } b(1, 2, 3);//10
#demo4 还是对变量对象的考察,AO通过arguments初始化,arguments是AO的属性,
AO = { arguments: <ArgO> };
它包括如下属性:
- callee — 指向当前函数的引用
- length — 真正传递的参数个数
- properties-indexes (字符串类型的整数) 属性的值就是函数的参数值(按参数列表从左到右排列)。 properties-indexes内部元素的个数等于arguments.length. properties-indexes 的值和实际传递进来的参数之间是共享的。
#demo5
function a() { alert(this); } a.call(null);//[object window]
不存在this的值为null的情况,因为当this的值为null的时候,其值会被隐式转换为全局对象