JavaScript忍者秘籍笔记02之闭包

来源:互联网 发布:产品排名优化流程 编辑:程序博客网 时间:2024/06/06 03:27

若网络条件允许,可以直接看我的个人博客,可能阅读体验更好
点击查看

闭包的作用域

var later;function outerFunction() {    var innerValue = true;    function innerFunction(paramValue) {        console.log(innerValue); // true        console.log(paramValue); // true        console.log(tooLate); // true    }    later = innerFunction;}outerFunction();var tooLate = true; // 这个声明必须在later调用前,否则later函数中的tooLate为undefinedlater(true);

绑定函数上下文

var button = {    clicked: false,    click: function() {        this.clicked = true;        console.log(this);        console.log(button.clicked);    }};var elem = document.getElementById('test');elem.addEventListener('click', button.click, false);

在本例中,浏览器的事件处理系统认为函数调用的上下文(this)是事件的目标元素,所以才导致其上下文是<button>元素,而不是button对象

// 解决方法1,使用匿名函数elem.addEventListener('click', function() {    button.click();}, false);// 解决方法2,使用bind方法elem.addEventListener('click',button.click.bind(button),false);

setTimeout和setInterval也是同样的解决方法,区别是这两个绑定的上下文(this)是window对象

更多请参考:Function.prototype.bind() - JavaScript | MDN

偏应用函数

函数科里化

Function.prototype.curry = function() {    var fn = this,        args = Array.prototype.slice.call(arguments); // 将类数组对象arguments转换为数组    return function() {        var allArgs = Array.prototype.slice.call(arguments).concat(args);        return fn.apply(this, allArgs);    }}function add(n1, n2) {    return n1 + n2;}console.log(add.curry(1)(4)); // 5

“分部”函数

Function.prototype.partial = function() {    var fn = this,        args = Array.prototype.slice.call(arguments);    return function() {        var j = 0;        for (var i = 0; i < args.length && j < arguments.length; i++) {            if (args[i] === undefined) {                args[i] = arguments[j++];            }        }        return fn.apply(this, args);    };};var delay = setTimeout.partial(undefined, 1000);delay(function() {    console.log('delay 1 s'); // 1秒后输出});

使用闭包实现缓存记忆功能

Function.prototype.memoized = function(key) {    this._values = this._values || {};    console.log(this);    return this._values[key] ? this._values[key] : this._values[key] = this.apply(this, arguments);}Function.prototype.memoize = function() {    var fn = this;    return function() {        return fn.memoized.apply(fn, arguments);    }}function isPrime(num) {    var prime = num != 1;    for (var i = 2; i < num; i++) {        if (num % i == 0) {            prime = false;            break;        }    }    return prime;}var isPrimeMemo = isPrime.memoize();console.log(isPrimeMemo(4)); // falseconsole.log(isPrimeMemo(7)); // trueconsole.log(isPrime._values); // { '4': false, '7': true }

即时函数

(…)()中,第一组圆括号仅仅是用于划定表达式的范围,而第二个圆括号则是一个操作符。eg,将函数引用通过圆括号括起来是合法的:

var someFunction = function() {... };result = (someFunction)();

通过参数限制作用域内的名称

    <img src="../images/ninja-with-pole.png">    <script type="text/javascript">    $ = function() {alert('not jQuery!');}; // 定义一个$表示其他内容,而不是jQuery    (function($) {        $('img').on('click', function(event) {            $(event.target).addClass('clickedOn');        });    })(jQuery); // 在调用即时函数时,将jQuery作为参数传递进去,就会将jQuery绑定到$参数上了    </script>
原创粉丝点击