JavaScript语言精粹之函数篇(二)

来源:互联网 发布:天谕萌女萝莉数据 编辑:程序博客网 时间:2024/06/09 07:52

1.异常
异常时干扰程序的正常流程的非正常事故,当事故被查出时,会抛出一个异常

var addHasError = function (a, b) {    if (typeof a !== "number" || typeof b !== "number") {        throw {            name : "TypeError",            message : "add needs number"        }    }    return a + b;}var try_it = function () {    try {        addHasError("two", "one");    } catch(ex) {        TypeError : add needs number         document.writeln(ex.name + " : " + ex.message);    }}try_it();

2.给类型添加方法
JS允许给基本类型添加方法,这样所有的函数都可以调用

Function.prototype.method = function (name, fun) {    // 如果添加的方法不存在,才可以添加    if(!this.prototype[name]) {        this.prototype[name] = fun;        return this;    }}

添加一个取整的方法

Number.method("integer", function () {    alert(this);    // this代表调用给方法的数字,这里是- 10 / 3    return Math[this < 0 ? 'ceil' : 'floor'](this); });alert((- 10 / 3).integer());    // -3

添加一个去除字符串末端空白的方法

String.method("trim", function () {    return this.replace(/^\s+|\s+$/g, '');});alert("  zhang shan  ".trim());

3.递归
递归函数会直接或间接的调用自身的一种函数
一个递归函数调用自身去解决它的子问题
汉诺塔问题
HTML部分

<div>    <ul name="good">        <p></p>        <span name="good"></span>    </ul>    <ul>    </ul></div><h1>    <h3 name="good"></h3></h1>

JS部分

var hanoi = function (disc, src, aux, dst) {    if (disc > 0) {        arguments.callee(disc - 1, src, dst, aux);        document.writeln("Move disc " + disc + " form " + src + " to " + dst + "<br/>");        arguments.callee(disc - 1, aux, src, dst);    }}hanoi(3, "盘子A", "盘子B", "盘子C");

调用walk_the_DOM函数,它从给定的节点开始,依照html的顺序访问该树的每个节点
他会调用一个函数,并依次传入每个节点给他
当他调用自身时,那么就会出来它的子问题

var walk_the_DOM = function walk (node, func) {    func(node);    node = node.firstChild;    while(node) {        walk(node, func);        node = node.nextSibling;    }}

定义一个getElementByAttribute方法,根据属性查找元素

var getElementByAttribute = function (attr, value) {    var res = [];    walk_the_DOM(document.body, function (node) {        var ele = node.nodeType == 1 && node.getAttribute(attr);        alert(node.tagName);        if(typeof ele === "string" && (ele === value || typeof value !== "string")) {            res.push(node);        }    });    return res;}alert(getElementByAttribute("name", "good"));var factorial = function (i, a) {    a = a || 1;    if( i < 2) {        return a;    }    return arguments.callee(i - 1, a * i);}alert(factorial(5));        // 120

4.作用域
作用域控制着参数和变量的可见性和生命周期

var foo = function () {    var a = 3, b = 5;    var bar = function () {        var b = 7, c = 11;        a += b + c;        alert("a = " + a + " , b = " + b + ", c = " + c);   // a = 21 , b = 7, c = 11    }    alert("a = " + a + " , b = " + b);  // a = 3 , b = 5    bar();    alert("a = " + a + " , b = " + b);  // a = 21 , b = 5    alert("a = " + a + " , b = " + b + ", c = " + c);   // c不存在}();

JS不支持块级作用域,即if、for、while等花括号中的变量,可以在外部访问

for(var i = 0; i < 10; i++) {}alert(i);   // 10

5.闭包
闭包的好处在于内部函数可以访问定义它的外部函数的参数和变量
且闭包的生命周期比它的外部函数要长
我们是将调用函数的结果,即返回的对象赋值给myObject对象

var myObject = function () {    var value = 0;    return {        increment : function (inc) {            value = typeof inc === "number" ? inc : 1;        },        getValue : function () {            return value;        }    };}();myObject.increment(10);alert(myObject.getValue());     // 10// 返回的对象访问私有属性// 并不需要new实例化
var quo = function (status) {    return {        getStatus : function () {            return status;        }    }}// var q = quo("zhang");// alert(q.getStatus());        // zhang
var fade = function (node) {    var level = 1;    var step = function () {        var hex = level.toString(16);        node.style.background = "#FFFF" + hex + hex;        if (level < 16) {            level++;            setTimeout(step, 100);        }    }    setTimeout(step, 100);}fade(document.body);

内部函数能够访问外部函数的变量并非复制
糟糕的例子
HTML部分

<div>    <ul name="good">        <p>111</p>        <span name="good">222</span>    </ul>    <ul>    3333    </ul></div><h1>

JS部分

var ul = document.querySelectorAll("ul");var add = function (nodes) {    for(var i = 0; i < nodes.length; i++) {        nodes[i].onclick = function() {            alert(i);        }    }};add(ul);    // 你会发现,无论你点击哪一个ul都只会返回2// 原因是闭包访问外部的变量是真实的并非复制的// 像本例子中的i,它是不断发生变化的

因此我们可以修改一下

var addClosed = function (nodes) {    for(var i = 0; i < nodes.length; i++) {        nodes[i].onclick = function(pos) {            return function () {                alert(pos);            }        }(i);    }};// addClosed(ul);   // 这样就ok了
0 0
原创粉丝点击