码迷,mamicode.com
首页 > 编程语言 > 详细

Javascript语言精粹(二)

时间:2015-07-15 18:25:28      阅读:124      评论:0      收藏:0      [点我收藏+]

标签:

闭包

// 创建一个构造函数quo
// 它带有get_status方法和status私有属性
var quo = function(status){
    return {
        get_status: function(){
            return status;
        }
    };
};
var myQuo = quo(‘amazing‘);
alert(myQuo.get_status());

当我们调用quo时,它返回一个对象:

①该对象包含一个get_status方法,②该对象的一个引用保存在myQuo中。

即使quo已经返回了(return status;),但get_status方法仍然有访问status属性的特权。

get_status方法访问的并不是status参数的副本,而是status参数本身!

因为该函数可以访问它被创建时所处的上下文环境。也因此该函数被称为闭包。

 

再看一个更有用的栗子:

// 定义一个函数,它使一个DOM节点的背景色由黄变白
var fade = function(node){
    var level = 1;
    var step = function(){
        var hex = level.toString(16);
        node.style.backgroundColor = ‘#FFFF‘ + hex + hex;
        if(hex < 15){
            level += 1;
            setTimeout(step, 100);
        }
    };
    setTimeout(step, 100);
};

fade(document.body);

只要fade的内部函数step需要levellevel变量就会持续保留。

 

糟糕的栗子:

// 弹出节点的序号
var add_the_handlers = function(nodes){
    var i;
    for(i=0; i<nodes.length; i++){
        nodes[i].onclick = function(){
            alert(i);  //总是弹出节点的数目
        };
    }
};

未能达到目的的原因,是因为onclick时间处理器函数绑定了变量 i 本身,而不是函数在构造时的变量 i 的值

(个人理解:js解析的时候,把for循环解析了一遍, 运行的时候 i 已经等于节点数目了。绑定了 i 本身,故弹出的 i 等于节点数目。我们需要弹出的 i 是在它被构造时的值。)

 

解决糟糕的栗子:

var add_the_handlers = function(nodes){
    var helper = function(i){
        return function(){
            alert(i);
        };
    };

    var i;

    for(i=0; i<nodes.length; i++){
        nodes[i].onclick = helper(i);
    }
};

避免在循环中创建函数,这会带来无谓的计算,还会引起混淆。

可以在循环之外先创建一个辅助函数helper,让辅助函数返回一个绑定了当前 i 值的函数,这样就不会混淆了。

 

模块

我们可以使用函数和闭包来构建模块,这几乎可以完全摒弃全局变量的使用。

模块是一个提供接口却隐藏状态和实现的函数或对象。

模块模式也可以用来产生安全的对象。

我们来构造一个产生序列号的对象:

var serial_maker = function(){
// 该对象包含一个设置前缀的方法
// 该对象包含一个设置序列号的方法
// 和一个生成字符串的方法
    
    var prefix = ‘‘; //前缀
    var seq = 0; //序列号
    return {
        set_prefix: function(p){
            prefix = String(p);
        },
        set_seq: function(s){
            seq = s;
        },
        generate: function(){
            var result = prefix + seq;
            seq += 1;
            return result;
        }
    };
};

// 调用
var seqer = serial_maker();
seqer.set_prefix(‘Q‘);
seqer.set_seq(1000);
var unique = seqer.generate(); // "Q1000"

如果我们把seqer.generate作为一个值传递给第三方函数,这个函数能产生唯一的字符串,但却不能通过它来改变prefix和seq的值。

 

Javascript语言精粹(二)

标签:

原文地址:http://www.cnblogs.com/gallenhu/p/4648817.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!