闭包
闭包的基本概念
闭包(closure)是JavaScript语言的一个难点,也是JavaScript的一个特色,很多高级的应用都要依靠闭包来实现。
闭包的概念
在计算机科学中,闭包(英语:Closure),又称词法闭包(Lexical Closure)或函数闭包(function closures),是引用了自由变量的函数
在JavaScript中,在函数中可以(嵌套)定义另一个函数时,如果内部的函数引用了外部的函数的变量,则产生闭包。
-
产生闭包的条件
当内部函数访问了外部函数的变量的时候,就会形成闭包。
闭包的作用
保护私有变量不被修改
计数器
需求:统计一个函数的调用次数
var count = 0;
function fn(){
count++;
console.log("我被调用了,调用次数是"+count);
}
fn();
fn();
fn();
缺点:count是全局变量,不安全。
使用闭包
function outer(){
var count = 0; // 私有变量, 将count保护起来了
function add(){
count++;
console.log("当前count"+count);
}
return add;
}
var result = outer();
result();
斐波那契数列优化
缓存(cache):数据的缓冲区,当要读取数据时,先从缓冲中获取数据,如果找到了,直接获取,如果找不到,重新去请求数据。
计算斐波那契数列,会有很大的性能问题,因为重复的计算了很多次,因此我们可以使用缓存来解决这个性能问题。
初级优化:
使用缓存的基本步骤:
如果要获取数据,先查询缓存,如果有就直接使用
如果没有,就进行计算,并且将计算后的结果放到缓存中,方便下次使用。
//缓存
var arr = [];
var fbi = function (n) {
count++;
if (n == 1 || n == 2) {
return 1;
}
if (arr[n]) {
return arr[n];
} else {
var temp = fbi(n - 1) + fbi(n - 2);
arr[n] = temp;//存入缓存
return temp;
}
}
缺点:既然使用缓存,就需要保证缓存的数据的安全,不能被别人修改,因此,需要使用闭包来实现缓存的私有化。
function outer() {
//缓存
var arr = [];
var fbi = function (n) {
if (n == 1 || n == 2) {
return 1;
}
if (arr[n]) {
return arr[n];
} else {
var temp = fbi(n - 1) + fbi(n - 2);
arr[n] = temp;//存入缓存
return temp;
}
}
return fbi;
}
var fbi = outer();
console.log(fbi(40));
继承
现实生活中的继承,子承父业, 如儿子继承了父辈的财产,公司等
程序中的继承,一个对象可以使用另一个对象中的方法或属性
继承的目的: 方便代码的复用
var lw = {
skill: "翻墙",
age: 28
}
function Person(){}
var xm = new Person();
// 如何实现让xm可以使用到lw对象上的skill属性???
xm.skill; // ==> 翻墙</pre>
JS常见的几种继承模式
原型链继承
一个对象可以访问构造函数的原型中的属性和方法,那么如果想要让一个对象增加某些属性和方法,只需要把这些属性和方法放到原型对象中即可。这样就实现了继承, 称之为原型链继承
直接给原型增加属性和方法
原型替换(注意:constructor)
借用构造函数继承
从构造函数中继承到构造函数中的成员
function Person(name, age, gender){
this.name = name;
this.age = age;
this.gender = gender;
}
function Chinese(name, age, gender, skin){
this.name = name;
this.age = age;
this.gender = gender;
// 以上代码重复,在构造函数Person中已经给this添加
this.skin = skin;
}
// 重写构造函数Chinese
function Chinese(name, age, gender, skin){
// 借用Person构造函数,继承到name、age、gender属性
Person.call(this, name, age, gender);
this.skin = skin;
}
组合继承
借用构造函数 + 原型链继承组合在一起使用
function Person(name, age, gender){
this.name = name;
this.age = age;
this.gender = gender;
}
// Person原型上的sayHi方法
Person.prototype.sayHi = function(){
console.log("hello, 我是" + this.name);
}
function Chinese(name, age, gender, skin){
// 借用Person构造函数,继承到name、age、gender属性
Person.call(this, name, age, gender);
this.skin = skin;
}
var xm = new Chinese("xm", 20, "male", "黄色");
// xm有name/age/gender属性从Person构造函数中继承到的
// 那么如何让Chinese的实例对象xm去继承到Person原型上的sayHi方法???
xm.sayHi();