下班回来刷了下javaeye,看见这篇博文
http://my249645546.iteye.com/blog/1716629
觉得写得很好,不由得想起很多自己零零碎碎了解的一些js知识,突然也想记录下来,一方面是回忆一遍加深印象,另一方面以后忘记了可以拿出来翻阅。
1、js的诡异的编译
// 解析器会先解析function xx()这种定义型的函数语句
// 对于所有的var a=xx,浏览器会预编译,声明所有var变量(初始为undefined)
/***** 情况1 :
alert(a);
var a = "window变量: a";
结果:undefined
*/
/***** 情况2 :
alert(a);
var a = "window变量: a";
function a() {}
结果:function a() {}
*/
/***** 情况3 :
alert(a);
//var a = "window变量: a";
//function a() {}
结果:报错
*/
/***** 情况4 :
alert(a);
var a = "window变量: a";
var a = function(){
alert("var型的函数定义,解析类似于var变量定义");
}
结果:undefined
*/
// 还有一种特殊情况
//alert(a); // 报错
//alert(window['a']); // 在window作用域下找不到a,返回undefined
a = "虽然a=''也是window作用域,但是和var a=''有区别。解析器不会预编译一个var a=undefined";
alert(window['a']); //这里可以正常输出
// js 对于函数局部变量的两种情况
function f1() {
var a='函数局部变量,无法访问';
}
f1();
alert(window.a);
function f2() {
b='window变量,可以访问';
}
f2();
alert(b);
2、js模拟一个类
/* 定义一个类,拥有私有属性,get set方法
var Student = function(){
var name;
var getName = function(){
return this.name;
}
var setName = function(name){
this.name = name;
}
var obj = {
name: name,
getName: getName,
setName: setName
}
return obj;
}
var s = Student();
alert(s.getName()); // 结果 undefined
s.setName('new name');
alert(s.getName()); // 结果 new name
*/
/** 符合java习惯,function可看做是构造方法
var Teacher = function(name){
this.name = name;
this.getName = function(){
return this.name;
}
this.setName = function(_name){
this.name = _name;
}
}
var t = new Teacher();
//alert(t.name); // 结果 undefined
t.setName('set方法调用成功');
//alert(t.getName()); // 结果 set方法调用成功
*/
3、apply、call改变作用域
function test(name){
this.name = name || this.name;
alert(this.name);
}
var obj1 = {name: '111'};
var obj2 = {name: '222'};
var obj3 = {name: '333'};
test.call(obj1); // call方式 结果111
test.call(obj2, '222222'); // call方式 方法作用在obj2上 结果222222
test.apply(obj3, ['333333']); // apply方式 方法作用在obj3上 结果333333
自我理解这个有点像java的反射,对于test进行invoke调用,可传入目标对象和方法调用需要的参数。方法体中的this对象就代表目标对象
4、java闭包
// 闭包就是在函数内部定义一个函数,作为其返回值
// 建立起函数内部和外部的桥梁,比如下面的n值,调用两次c(),分别为0 1,
// 而并不是执行完一次以后变量的生命周期也结束了。
// 因为外部对内部函数inner有依赖,内部函数对外部函数里面的局部变量n也有依赖,
// 那么n就需要一直驻留在内存中
function Clazz(){
var n=0;
function inner(){
alert(n++);
}
return inner;
}
var c = Clazz();
c(); // 0
c(); // 1
个人理解:这里相当于闭包返回一个对象c,而n相当于该对象的私有属性,所以n就和c的生命周期一样了