JavaScript 函数自覆盖模式

简介: 如果一个函数中有不少局部变量,而且并非 primitive type 的,意味着在执行该函数的时候占用较多的内存开销。这一过程是显然易见的,例如执行这个函数 1000 次,就要重复创建那些局部变量 1000 次——这真是一个多余的过程。

如果一个函数中有不少局部变量,而且并非 primitive type 的,意味着在执行该函数的时候占用较多的内存开销。这一过程是显然易见的,例如执行这个函数 1000 次,就要重复创建那些局部变量 1000 次——这真是一个多余的过程。再者,如果函数逻辑不会去修改局部变量的值,即属于 constant / final 修饰的值,那么显然,我们仅仅创建一次变量便足够了。好,既然如此,我们把这些可以优化的变量都放置函数体外面好了。虽然 js 没有 constant / final 的修饰符,不过即使如此,那只会仅仅影响到程序的可读性这点不好。为优化这点,我们只需把变量的声明写到函数体外,不要写在函数里面。

有两点应注意:

  1. 你可选择不用局部变量,而是可以将变量写成 public 属性的调用方式,作用无异。但本文考虑的是基于替代局部变量的私有方式;
  2. 当然,这种优化不必然强制的,如果遇到是的简单的字符串,int……,那么小 case 写在函数体内倒无妨,解释器处理很快,再优化可能要差别不大。总之得看情况,千万别养成强迫症哦。

于是,我们需要考虑把这些 constant 放在何处合理的地方。通常会想到是一个闭包:

;(function(){
	var regExp = /d/; // 提取变量声明语句
	window.isNumber = function(v){
	    // var regExp = /d/;
            return regExp.test(v);
	}
})();

以上是一个简单的例子,就目的来说已经可以达到前面所说之要求了。我们利用一个闭包去存储私有变量,这些私有变量是可以被返回的函数访问的,但在这段代码外面则访问不到了。但问题是,若我们不想用闭包呢?那是一个“匿名函数”(反对使用闭包,其实也说不上究竟有什么不好,反正觉得多了一层“怪怪”的——纯属个人感观而言)。

这里,我们可以大胆使用“覆盖函数”的方式——竟然“覆盖”?是的,别以为“覆盖了就没了”是一件很危险的事哦:P,请注意我们这里是"巧用"覆盖。

以下就是一个例子:

/**
 * 固定位置元素。el必须为绝对定位。
 * @param {HTMLElement} el
 * @param {Boolean}  isOnTop 是否在最上方的,false=最下方
 */
$$.dhtml.fixedLayer = function(el, isOnTop){
        var body  = window.document.body;
        var floor = window.Math.floor;
        
        $$.dhtml.fixedLayer = function (el, isOnTop){
                var lastScrollY = isOnTop ? -20 : -(window.innerHeight - el.clientHeight - 30); /* 调整 CSS Bottom 的值 */
                window.setInterval(function(){
                        var percent = body.scrollTop - lastScrollY; // 移动的步伐是多大?
                        percent = shiftMove(percent);

                        if (percent == 0){
                                return; // 0表示不滚动,位置不变,所以DOM不作变化
                        }else{
                                lastScrollY += percent; // 保存偏移的位置,可正可负
                                addTop(el, percent);
                        }
                }, 10);
        }
        
        /**
         * stype.top 带单位的,运算时不方便,写一个函数处理吧
         * @private
         * @param {HTMLElement} el
         * @param {Number} amount
         * @return {Number} 增加 amount 后此时元素的 top 值
         */
        function addTop(el, amount){
                var top = window.parseInt(el.style.top) || 0; // style.top 有时为空字符,那就是 = 0
                top += amount;  // 弱类型的表现,先是int类型的+=
                top += 'px';    // 然后这是 string 类型的!
                el.style.top = top;
                
                return top;
        }
        
        /**
         * 为更加平滑,缩小移动的步伐。
         * @private
         * @param {Number} percent
         * @return {Number}
         */
        function shiftMove(percent){
                percent = 0.2 * percent;
                percent = floor(percent); // 取整数
                
                return percent;
        }
        
        return $$.dhtml.fixedLayer(el, isOnTop);
}
这种的方式特点是创函数逻辑在函数内一层,第一次执行函数会覆盖原定义的函数(被覆盖的函数是外一层,完成了函数签名档作用)。函数自己覆盖掉自己,但函数名字依旧不变,所以这一切对外如何如何调用都是透明的。如果不调用方法,函数的逻辑并不执行,颇有点类 lazyExecute 意味。

对于 hash 对象的写法,也就是存在冒号 :  的写法,相应的处理如 lifesinger 所示:

    createElement: function(sHtml) {
        // ...
        var createElement = function(sHtml) {
            // ...
        };
        this.createElement = createElement;
        return createElement(sHtml);
    }

该模式的一个缺点是,如果要重命名函数名称,比不使用该模式多一次的操作。

实不相瞒,小弟当时也是受 lifesinger 在 zbm2001 博文之留言所启发而至的。源地址如下:

《自定义createElement——根据html字符串创建元素》http://zbm2001.iteye.com/blog/510627


目录
相关文章
|
3月前
|
机器学习/深度学习 JavaScript 前端开发
JS进阶教程:递归函数原理与篇例解析
通过对这些代码示例的学习,我们已经了解了递归的原理以及递归在JS中的应用方法。递归虽然有着理论升华,但弄清它的核心思想并不难。举个随手可见的例子,火影鸣人做的影分身,你看到的都是同一个鸣人,但他们的行为却能在全局产生影响,这不就是递归吗?雾里看花,透过其间你或许已经深入了递归的魅力之中。
142 19
|
5月前
|
JavaScript
JS实现多条件搜索函数
JS封装的多条件搜索
|
7月前
|
JavaScript 前端开发 Docker
如何通过pm2以cluster模式多进程部署next.js(包括docker下的部署)
通过这些步骤,可以确保您的Next.js应用在多核服务器上高效运行,并且在Docker环境中实现高效的容器化管理。
807 44
|
7月前
|
JavaScript 前端开发
JavaWeb JavaScript ③ JS的流程控制和函数
通过本文的详细介绍,您可以深入理解JavaScript的流程控制和函数的使用,进而编写出高效、可维护的代码。
160 32
|
6月前
|
JavaScript 前端开发 Java
详解js柯里化原理及用法,探究柯里化在Redux Selector 的场景模拟、构建复杂的数据流管道、优化深度嵌套函数中的精妙应用
柯里化是一种强大的函数式编程技术,它通过将函数分解为单参数形式,实现了灵活性与可复用性的统一。无论是参数复用、延迟执行,还是函数组合,柯里化都为现代编程提供了极大的便利。 从 Redux 的选择器优化到复杂的数据流处理,再到深度嵌套的函数优化,柯里化在实际开发中展现出了非凡的价值。如果你希望编写更简洁、更优雅的代码,柯里化无疑是一个值得深入学习和实践的工具。从简单的实现到复杂的应用,希望这篇博客能为你揭开柯里化的奥秘,助力你的开发之旅! 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一
Next.js 实战 (三):优雅的实现暗黑主题模式
这篇文章介绍了在Next.js中实现暗黑模式的具体步骤。首先,需要安装next-themes库。然后,在/components/ThemeProvider/index.tsx文件中新增ThemeProvider组件,并在/app/layout.tsx文件中注入该组件。如果想要加入过渡动画,可以修改代码实现主题切换时的动画效果。最后,需要在需要的位置引入ThemeModeButton组件,实现暗黑模式的切换。
307 0
Next.js 实战 (三):优雅的实现暗黑主题模式
|
10月前
|
前端开发 JavaScript UED
探索JavaScript的异步编程模式
【10月更文挑战第40天】在JavaScript的世界里,异步编程是一道不可或缺的风景线。它允许我们在等待慢速操作(如网络请求)完成时继续执行其他任务,极大地提高了程序的性能和用户体验。本文将深入浅出地探讨Promise、async/await等异步编程技术,通过生动的比喻和实际代码示例,带你领略JavaScript异步编程的魅力所在。
85 1
|
10月前
|
前端开发 JavaScript 开发者
除了 Generator 函数,还有哪些 JavaScript 异步编程解决方案?
【10月更文挑战第30天】开发者可以根据具体的项目情况选择合适的方式来处理异步操作,以实现高效、可读和易于维护的代码。
|
11月前
|
前端开发 JavaScript UED
探索JavaScript中的异步编程模式
【10月更文挑战第21天】在数字时代的浪潮中,JavaScript作为一门动态的、解释型的编程语言,以其卓越的灵活性和强大的功能在Web开发领域扮演着举足轻重的角色。本篇文章旨在深入探讨JavaScript中的异步编程模式,揭示其背后的原理和实践方法。通过分析回调函数、Promise对象以及async/await语法糖等关键技术点,我们将一同揭开JavaScript异步编程的神秘面纱,领略其带来的非阻塞I/O操作的魅力。让我们跟随代码的步伐,开启一场关于时间、性能与用户体验的奇妙之旅。
|
11月前
|
JavaScript 前端开发
JavaScript 函数语法
JavaScript 函数是使用 `function` 关键词定义的代码块,可在调用时执行特定任务。函数可以无参或带参,参数用于传递值并在函数内部使用。函数调用可在事件触发时进行,如用户点击按钮。JavaScript 对大小写敏感,函数名和关键词必须严格匹配。示例中展示了如何通过不同参数调用函数以生成不同的输出。