ホームページ  >  記事  >  ウェブフロントエンド  >  JavaScript関数の再帰、コールバック、クロージャ、スコープの使用例の詳細な説明

JavaScript関数の再帰、コールバック、クロージャ、スコープの使用例の詳細な説明

伊谢尔伦
伊谢尔伦オリジナル
2017-07-25 10:54:241683ブラウズ

再帰呼び出し(arguments.callee)
再帰呼び出しとは、自分自身を呼び出すことです。呼び出しは、直接呼び出しと間接呼び出しに分けられます。以下に、指定された値のフィボナッチ数列を計算するための再帰呼び出しの使用法を示します。

// 求i的阶乘
function factorial(i){
    if(i < 2){
        return 1;
    }
    return i*factorial(i-1); // 递归调用
}
alert(factorial(5)); // 求5的阶乘
// 以上方式存在一个问题?如下:
var factorial = function(i){
    if(i < 2){
        return 1;
    }
    return i*factorial(i-1); // factorial还能被调用吗?不能
}
var test = factorial; 
factorial = null;  
alert(test(2));
// 解决方案:
var factorial = function(i){
    if(i < 2){
        return 1;
    }
    return i*arguments.callee(i-1); // arguments.callee返回正被执行的 Function 对象,也就是所指定的 Function 对象的正文
}
var test = factorial;
factorial = null;
alert(test(5));

スコープ

// 在程序中,作用域控制着变量的可见性和生命周期。
var name = "default"; // 全局作用域
function getName(){
    var name = "getName"; // getName作用域下
    for(var i=0; i<2; i++){
        var inName = "inName";
    }
alert(i + "," + inName); // 2,inName 注意:在js中没有块级作用域,及if、for、while中声明的变量是放在块所在的作用域下
    return name;
}
alert(getName()); // getName 注意:js存在函数作用域,所以在函数内部定义的变量在外部是不可见的
alert(name); // default

注: 多くの現代言語では、変数をできるだけ遅く宣言することが推奨されています。例: java ただし、js ではブロックレベルのスコープがサポートされていないため、これはお勧めできません。使用するすべての変数を関数の先頭で宣言することをお勧めします。

クロージャー
作成時に環境のコンテキストにアクセスできる関数は、クロージャーと呼ばれます。スコープの利点は、内部関数が外部関数のすべての変数 (この関数と引数を除く) にアクセスできることです。

var myObject = {
    value   : 0,
    increment : function(inc){
        this.value = typeof inc === &#39;number&#39; ? inc : 1;
    },
    getValue  : function(){
        return this.value;
    }
};
myObject.increment(10);
alert(myObject.value);
alert(myObject.getValue());
// 上面使用字面常量方式定义了一个myObject对象。但是value变量可以被外部对象访问
var myObject = function(){
    var value = 0;
    return {
        increment: function(inc){
            value += typeof inc === &#39;number&#39; ? inc : 1;
        },
        getValue : function(){
            return value;
        }
    };
}();
myObject.increment(10);
alert(myObject.value); // 不能被外部对象访问
alert(myObject.getValue()); // 10
// 渐变body的背景色(黄色到白色)
var fade = function(node){
    var level = 1;
    var step = function(){
        var hex = level.toString(16);
        node.style.backgroundColor = &#39;#FFFF&#39; + hex + hex;
        if(level < 15){
            level += 1;
            setTimeout(step, 500); // 如果level小于15,则内部函数自我调用
        }
    };
    setTimeout(step, 1); // 调用内部函数
};
fade(document.body);
// 下面是一个很糟糕的例子
<a href="#" name="test">点击我...</a><br> // 点击时显示3
<a href="#" name="test">点击我...</a><br> // 点击时显示3
<a href="#" name="test">点击我...</a><br> // 点击时显示3
var add_the_handlers = function(nodes){
    var i;
    for(i = 0; i < nodes.length; i += 1) {
        nodes[i].onclick = function(e){ // 函数构造时的:i
            alert(i);
        };
    }
};
var objs = document.getElementsByName("test");
add_the_handlers(objs);
// 造成上面的原因是:a标签的事件函数绑定了变量i,则不是函数在构造时的i值。
// 解决方案如下:
var add_the_handlers = function(nodes){
    var i;
    for(i = 0; i < nodes.length; i += 1) {
        nodes[i].onclick = function(i){
            return function(e){
                alert(i); // 输出的i是构造函数传递进来的i,不是事件处理绑定的i。
            };
        }(i);
    }
};
var objs = document.getElementsByName("test");
add_the_handlers(objs);

コールバック

// data表示参数,而call_function则表示回调函数
function sendRequest(data, call_function){
    // setTimeout来模仿客户端请求服务端中传输数据的时间。
    // 当3秒钟后就调用回调函数(有客户端实现回调函数)
    setTimeout(function(){
        call_function(data); // 调用回调函数
    }, 3000);
}
// 测试sendRequest函数
sendRequest("参数", function(context){
    alert("context=" + context);
});

以上がJavaScript関数の再帰、コールバック、クロージャ、スコープの使用例の詳細な説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。