今天是学习面向对象的第五天,感觉今天听课比昨天还要混乱,可能是真的到了难的地方了,特别是闭包的知识点,尤其在闭包中实现AJAX获取json数据,代码量加大,一时接受不了呢,所以继续总结知识点。
概念:可以访问其他函数内部数据的函数。
注意:在js中,函数内部的数据在外部无法访问。为了访问函数内部的数据,提出闭包技术。
两种方式分别是:引用计数、标记清除。
引用计数:变量默认计数为0,如果有其他数据对其有使用,就引用计数加1,;如果对该变量使用的数据释放了,引用计数减1,在一定周期后,如果变量引用计数为0,就将回收掉。
标记清除:如果变量进入了一个执行环境,此时该变量被标记为不可回收;如果变量出了执行环境,此时该变量被标记为可回收。在一定周期后,如果变量被标记为可回收,就将其回收掉。
从文档的根节点尝试找一条路径可以到达变量。如果找到了,就将其变量标记为不可回收;否则标记为可回收。
// 1:
var a;
if("a" in window){
a = 10;
} else {
a = 20;
}
console.log(a); //10
var name = 1;
console.log(typeof window.name); //string
console.log(typeof name); //string
console.log(window.name === name); //true
// 2
function fn(a) {
console.log(a); //function a() { console.log(10);}
function a() {
console.log(10);
}
var a = 10;
console.log(a); //10
}
fn(100);
弱类型语言:大部分为静态作用域。
强类型语言:动态作用域。
原因:现代浏览器不会将函数声明提升,早起的浏览器会得到提升
面试题案例:
if(true){
function a() {
console.log(1);
}
} else {
function a() {
console.log(0);
}
}
a(); //1
新版本的浏览器会输出1,而IE6浏览器输出0(函数声明提升,同名函数后面的将前面的函数覆盖)。
当一个匿名函数 作为某个对象的属性值时, 在其内部 只有使用 arguments.callee 来获取 函数。
(1)实现计数的作用------计数器
function makeCounter() {
var count = 0;
return {
update: function() {
count++;
},
get: function() {
return count;
}
};
}
var personCounter = makeCounter();
function Person() {
personCounter.update();
}
new Person;
new Person;
new Person;
new Person;
new Person;
new Person;
new Person;
console.log(personCounter.get()); // 7
(2)实现沙箱模式---实质就是匿名自调用函数(很多的框架都使用了沙箱模式)
优点:与外界隔离,即可以分割作用域;内部代码自执行。
在实际开发中,可以考虑将全局对象当做实参传入沙箱内部的变量,以提高js性能。
用例:如果在开发中,遇到只需要执行一次的代码块。可以将其放到沙箱内部。
(3)实现缓存------优化fib递归调用性能
//获取fib函数的第n项值得闭包函数
var fib=function(){
var cache=[]; //缓存计算结果
return function(n){ //返回fib函数的闭包函数
var val=cache[n]; //从缓存从获取数据
if(val) return val; // 如果有值, 直接返回值
else{
if(n==1||n==2) val=1; // 如果n的值 为1 或者 2,值为 1
else if(n>2) val=arguments.callee(n-1)+arguments.callee(n-2); // 如果n的值 大于 2, 递归重新求值
return cache[n]=val; // 将重新计算的值,缓存起来并返回
}
}
}();
console.log(fib(1000));
(4)实现面向对象的封装
在Java 中,对象的属性可以 添加 访问修饰符,private, public,而在js并没这些关键字;通过Object.defineProperty(稍后解释)
(5)科里化:将一个拥有多个参数的函数 转化成 一个单一参数函数 的形式。(案例稍后补充)
当访问一个变量时, 首先在当前作用域上查找,如果找到就直接使用,并停止查找;
如果没有找到,就会向上一级作用域上查找,如果找到就直接使用,并停止查找;
如果还没有找到就继续向上一级作用域查找,直到全局作用域,如果找到就直接使用,并停止查找;
否则报错(xxx is not defined.)
function fun(n, o) {
console.log(o);
return {
fun: function(m) {
return fun(m, n);
}
};
}
var a = fun(0); // n = 0 undefined
a.fun(1); // n = 0 0
a.fun(2); // n = 0 0
a.fun(3); // 0
var b = fun(0).fun(1).fun(2).fun(3); // undefined, 0, 1, 2
var c = fun(0).fun(1); // undefined, 0
c.fun(2); //1
c.fun(3); //1
var d = b.fun(); //3
d.fun(); //undefined
原文:http://www.cnblogs.com/fatimah1214/p/6057688.html