• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
繁星
不要浪费时间
博客园    首页    新随笔    联系   管理    订阅  订阅

[翻译]javascript学习笔记 (五) -继承和Closures

javascript中的继承和Closures
实现继承的两种方法
使用"call"函数,call允许我们在一个上下文环境中调用另外一个函数。我们在cat和dog类中调用animal类。
function Animal(name){
    
this.name = name;

    
this.species = 'Animal';
    
this.sleep   = function(){ alert(this.name+' falls asleep: Zzzzz'); }
}
function Cat(name){
    Animal.call(
this, name);

    
this.talk = function(){ alert('Meow!'); }
}
function Dog(name){
    Animal.call(
this, name);

    
this.talk = function(){ alert('Woof!'); }
}

var sam = new Cat('Sam');
var joe = new Dog('Joe');
sam.sleep(); 
// Sam falls asleep: Zzzzz
joe.sleep(); // Joe falls asleep: Zzzzz

sam.talk();  
// Meow!
joe.talk();  // Woof!

缺点是prototyping不能在这种方法中使用,animal prototype中的方法不能带到cat或dog中。于是每个cat或dog实例中都有species和sleep的副本,因此效率是不高的。
另外一种替代的方法是使用prototype
function Animal(name){
    
this.name = name;
}
Animal.prototype 
= {
    species: 'Animal',
    sleep  : 
function(){ alert(this.name+' falls asleep: Zzzzz'); }
}

function Cat(name){
    Animal.apply(
this, arguments);
}
Cat.prototype         
= new Animal;
Cat.prototype.species 
= 'Cat';
Cat.prototype.talk    
= function(){ alert('Meow!'); }

function Dog(name){
    Animal.apply(
this, arguments);
}
Dog.prototype         
= new Animal;
Dog.prototype.talk    
= function(){ alert('Woof!'); }

var sam = new Cat('Sam');
var joe = new Dog('Joe');
sam.sleep(); 
// Sam falls asleep: Zzzzz
joe.sleep(); // Joe falls asleep: Zzzzz

alert(sam.species); 
// Cat
alert(joe.species); // Animal -- no species is defined for Dog

Closures
看如下代码
function beginAdding(a){
    a 
*= 5;
    
return function finishAdding(b){ alert(a+b); }
}

var add = beginAdding(10);

add(
20); // 70

add变量的内容是函数function finishAdding(b){ alert(a+b); } 且有a变量的副本

下面来讨论下内存泄露
IE中有两个GC ,分别用来回收javascript和Dom对象。当退出页面时,他们将删除所有的javascript和dom对象。如果你循环引用DOM->JS->DOM或JS->Dom->Js时会放生泄露。IE将不知道删除那个对象。
例如:

var someInput    = document.getElementById('inputbox');
var someFunction = function(){
    alert(someInput.value);
}

someInput.onclick 
= someFunction;

当页面不停的刷新时,占用的内存为越来越多。

你也许会在不知情的情况下创建closure 
function Animal(name){
    
this.sleep = function(){ alert(name+' falls asleep: Zzzzz'); }
}

sleep函数中name变量来自父函数,这样就产生了一个closure
下面代码也产生了closure 在n函数中有x变量的引用
var x = 5;
var n = function(){
    y
=10;
    
return y;
}
每个函数都有自己的作用域,你代码的所有域都在一个内部内存栈中。当你创建一个closure,closure访问其中的一个域。当在通过域中创建多个closure时,每个closure会指向相同的域变量。

var x       = 5;
var alertX1 = function(){ alert(x); }

x           
= 10;
var alertX2 = function(){ alert(x); }

alertX1();
alertX2();

两个的运行结果都是alert 10,因为他们指向相同x的副本


如果我们改变x,两个alert都会跟着改变。解决方法是修改closure的域。

function makeClosure(x){
    
return function(){ alert(x); }
}

var x       = 5;
var alertX1 = makeClosure(x);

x           
= 10;
var alertX2 = makeClosure(x);

alertX1(); 
// 5
alertX2(); // 10



注意到x变量被拷贝到每个域中。因为x是一个字符串或一个数字。javascript总是将他们以值传递,在新的域中创建x变量的副本。如果是对象就不同了,他会传递引用。这样x变量就会指向相同的对象。

function makeClosure(x){
    
return function(){ alert(x.val); }
}

var x       = {val:5};
var alertX1 = makeClosure(x);

x.val       
= 10;
var alertX2 = makeClosure(x);

alertX1(); 
// 10
alertX2(); // 10
Created by jecray
posted @ 2009-03-01 12:57  ※繁星※  阅读(149)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3