向大师致敬!以前虽然看过,但是不求甚解,最近开始痛下苦功,有点收获。推荐李战的书 --悟透JavaScript
http://book.douban.com/subject/3271104/ 豆瓣上的介绍
在javascript里的全局环境就是一个对象,这个对象是javascript运行环境的根。对于浏览器中的javascript来说,这个根对象就是我们熟知的window对象。对于全局的javascript语句来说,window对象就相当于当前作用域。
当我们写下:
var myname="leadzen" ; //就是定义了window作用域的一个变量myname,而当我们写下:
myname="lead_zen"; //就是定义了window对象的一个属性myname
alert(window.myname1); //输出lead_zen
alert(window.myname); //输出leadzen
alert(myname); //输出leadzen
看另一个例子:
var yourname="真真";
myname="spring";
var interesting="laughing gor";
alert(myname + " like " + yourname); //输出spring like 真真
changenames(); //直接调用函数,即使函数定义在后面。 函数预编译
function changenames() {
alert('your old name is ' + yourname); //输出 your old name is undefined ,因为var yourname,这样yourname赋值undefine
alert('my old name is ' + myname); //输出my old name is spring 因为myname是window新添加的一个属性。原型链的问题
//虽然后面有句重设值的语句,但是,还没执行到,所以取全局的值
//这说明在函数体内也有预编译,对于var定义的变量,会先定义,即使先使用了该变量,也不会报错,只是该值是undefined而已
alert('interesting ' + interesting); //输出interesting laughing gor,这说明查找全局作用域(上层作用域)
//上面两个例子说明,全局变量,无论有无var定义,在函数内都能读取
alert('perporty of window name' + name ); //向上追溯的问题。最终找到window.name属性,这个为空。所以没有输出
var yourname = "海琴";
myname="小莫"; //全局变量,重设了该值
alert(myname + " do like " + yourname); //输出小莫 do like 海琴 ,这说明yourname被赋值了
}
alert(myname + " like " + yourname); //输出小莫 like 真真 海琴只是函数changenames的一个私有变量
alert(window.interesting); //输出laughing gor,说明全局变量定义是添加或修改了window属性
这里涉及到函数预编译
当代码运行进入一个函数时,javascript会创建一个新的作用域,来作为当前作用域的子作用域。然后,将当前全局作用域切换为这个新建的子作用域,开始执行函数逻辑。javascript执行引擎会把此函数内的逻辑代码,当一个代码段单元来分析和执行。 在第一步的预编译分析中,javascript执行引擎将所有定义式函数直接创建为作用域上的函数变量,并将其值初始化为定义的函数代码逻辑,也就是为其建立了可调用的函数变量。而对于所有"var"定义的变量,也会在第一步的预编译中创建起来,并将初始值设为undefined。
看一个特别的例子
function changenames() {
var yourname = "海琴";
myname="小莫";
}
alert(myname); //直接报错,为什么呢?因为预编译只是在该函数内有效
//alert(yourname); //报错,也是同样道理
function changenames() {
var yourname = "海琴";
myname="小莫";
}
changenames();
alert(myname); //输出小莫,因为函数已经执行了,myname是全局变量了,所以,能输出该变量的值
alert(yourname); //报错,因为yourname是函数体内的私有变量,所以,无法读取。
额外的思考
var aa = "dd";
//aa="dd";
function bb() {
alert(this.aa); //输出dd,而不是undefined
alert(aa);
var aa = "cc";
alert(aa);
}
bb(); //输出dd、undefined、cc,即使第一句没有var,aa="dd";调用该函数时,还是输出dd、undefined、cc
//这里强调的是this,this指谁呢?window对象 。
//alert(window.aa); //输出dd
网上的例子:
var x = 1, y = z = 0;
function add(n) {
n = n+1;
}
y = add(x);
function add(n) {
n = n + 3;
}
z = add(x);
还一个例子:
第一个