网站前端_JavaScript-基础入门.0016.JavaScript匿名闭包

匿名函数:

说明: 匿名函数就是没有名字的函数,闭包是可以访问一个函数作用域里变量的函数


// 普通函数
function userInfo(name){
    return name
}
alert(userInfo(‘李满满‘))
// 匿名函数
var userInfo = function(name){
    return name
}
alert(userInfo(‘李满满‘))
// 自我调用
(function(name){alert(name)})(‘李满满‘)
// 闭包函数
function userInfo(name){
    var userName = name
    return function(){
        alert(userName)
    }
}
userInfo(‘李满满‘)()


深入闭包:

说明: 闭包是指有权访问另一个函数作用域中的变量的函数,创建闭包的常见方式,就是在一个函数内部创建另一个函数,通过另一个函数访问这个函数的局部变量

特性: 闭包可以把局部变量驻留在内存中,可以避免使用全局变量(函数内部使用全局变量会导致全局变量污染),使用闭包可以实现类似全局变量的效果但局部变量函数又可以和外部环境保持隔离


// 累加效果 - 全局实现
var count = 1
function add(){
    this.count += 1
}
add()
alert(count)
// 累加效果 - 闭包实现
function add(){
    var count = 1
    return function(){
        count += 1
        return count
    }
}
res = add()
alert(res())
alert(res())


注意: 由于闭包里作用域返回的局部变量资源不会被立即销毁回收,所以可能会占用更多内存,过度的使用会导致性能下降,所以在非常有必要的时候才使用闭包或者在是使用完毕后设置为null标记回收

闭包THIS:

说明: 在没有绑定任何运行环境的情况下,闭包由于不属于任何对象的属性和方法,所以通常运行时指向window,当然我们也可以通过冒充对象,改变指向,或是bind来绑定运行环境


var userInfo = {
    sayEnv: function(){
        return function(){
            alert(this)
        }
    }
}
// 此时闭包中的this指向window
userInfo.sayEnv()()
// 冒充对象,让闭包this指向userInfo
userInfo.sayEnv().call(userInfo)
// 借用this,让闭包this指向userInfo
var userInfo = {
    sayEnv: function(){
        var _this = this
        return function(){
            alert(_this)
        }
    }
}
userInfo.sayEnv()()
// 使用bind,让闭包this指向userInfo
var userInfo = {
    sayEnv: function(){
        return function(){
            alert(this)
        }.bind(this)
    }
}
userInfo.sayEnv()()


内存泄漏:

说明: 虽然多个浏览器对于垃圾回收机制不同的处理,导致内存泄漏的问题,常常是由于闭包循环引用对象或变量,导致在内存中长期驻留,强烈推荐大家循环引用时赋值给变量然后在最后将循环引用的变量设置为null标记删除来避免内存泄漏的问题

块作用域:

说明: Js中没有块儿级作用域的特性,所以出了块儿范围的变量i还可以在块儿外部访问,此时可通过模仿块级作用域来避免这个问题


for(var i=1; i<=Math.floor(Math.random()*(10+1)); i++){}
// i出了块儿范围应该被销毁,但是却没有销毁,而且可以被访问
console.log(i)
/*
 * 模仿块儿级作用域(私有作用域),让变量出了作用范围就销毁
 */
(function(){
    for(var i=1; i<=Math.floor(Math.random()*(10+1)); i++){}
})()
console.log(i)


说明: 使用了块儿级作用域(私有作用域)后,匿名函数中定义的任何变量,都会在执行结束时销毁,因此使用此种方式可以减少闭包占用的内存问题,因为没有指向匿名函数的引用,只要函数执行完毕,就可以立即毁其作用域链了

私有变量:

说明: 任何函数中定义的变量,都可以认为是私有变量,因为不能在外部访问,因此可通过对构造函数定义对外公开访问这些私有属性的方法来实现私有变量的效果

function User(){
    // 构造函数中私有变量
    var name= ‘李满满‘
    // 私有变量对外访问接口
    this.getName = function(){
        return name
    }
    // 私有变量对外设置接口
    this.setName = function(value){
        name = value
    }
}
limanman = new User()
console.log(limanman.getName())
limanman.setName(‘刘珍珍‘)
console.log(limanman.getName())


问题: 如上使用构造函数内部声明私有变量外加实例对外访问设置接口来实现封装会导致所有的实例都会创建一遍接口对象而其实所有的实例的访问设置接口都一样的,此时我们可以通过原型对象实现自动继承优化


// 放在块儿级作用域
(function(){
    var name = ‘‘
    // 巧用全局构造函数
    User = function(value){
        name = value
    }
    // 设置原型对象的获取接口
    User.prototype.getName = function(){
        return name
    }
    // 设置原型对象的设置接口
    User.prototype.setName = function(value){
        name = value
    }
})()
// 实例化全局构造函数User
limanman = new User(‘李满满‘)
console.log(limanman.getName())
limanman.setName(‘刘珍珍‘)
console.log(limanman.getName())


说明: 使用了原型模式+块儿作用域方法实现了访问设置接口共享于多个实例之间,而不需要每次实例化都重新创建,而且块儿级作用域内的东西对外都是隔离的

模块模式:

说明: 上面采用的都是构造函数的方式创建私有变量和特权方法,而对象字面量的方式常采用模块模式来创建


function user(value){
    name = value
    return {
            getName: function(){
                return name
        },
            setName: function(value){
                name = value
        }
    }
}
limanman = user(‘李满满‘)
console.log(limanman.getName())
limanman.setName(‘刘珍珍‘)
console.log(limanman.getName())


本文出自 “ζ自动化运维开发之路ζ” 博客,请务必保留此出处http://xmdevops.blog.51cto.com/11144840/1853403

时间: 2024-11-08 18:54:44

网站前端_JavaScript-基础入门.0016.JavaScript匿名闭包的相关文章

网站前端_Bootstrap.基础入门.0002.排版/列表/表格/表单/按钮/图像?

通用技能: # 文档类型 <!DOCTYPE html> <html lang="zh-cn">     <!-- Html Code --> </html> 说明: 由于BootStrap基于HTML5,所以所有的HTML文件都需要在其顶部引用HTML5的DOCTYPE属性. # 移动先行 <meta name="viewport" content="width=device-width, initi

网站前端_EasyUI.基础入门.0009.使用EasyUI Layout组件的最佳姿势?

1. 基础布局 <div id="l" class="easyui-layout" data-options="width:500,height:250">     <div data-options="region:'north',title:'north',height:50"></div>     <div data-options="region:'west',tit

网站前端_EasyUI.基础入门.0007.使用EasyUI Tabs组件的最佳姿势?

1. 基础选项卡 <div id="t" class="easyui-tabs" data-options="width:500,height:300">     <div data-options="title:'About',closable:true,bodyCls:'tabbody'">         <p style="font-size:14px">jQue

网站前端_EasyUI.基础入门.0002.使用EasyUI Panel组件的最佳姿势?

1. 基础面板 <div id="p" class="easyui-panel" style="padding: 10px;" data-options="width:700,height:250,title:'基础面板'">     <p>jQuery EasyUI framework helps you build your web pages easily.</p>     <u

网站前端_EasyUI.基础入门.0002.带你玩转jQuery EasyUI Panel组件 ?

简单介绍: 说明: Panel面板常当作其它内容的容器,可用于创建包含Layout布局/Tabs选项卡/Accordion折叠面板等基础组件,还提供了内置的折叠/关闭/最大化/最小化的行为,你可以将它嵌入到网页的任何位置. 基础用法: <div id="p" class="easyui-panel" title="面板-标题" data-options="iconCls:'icon-save',closable:true,coll

网站前端_Bootstrap.基础入门.0001.BS的模版标准/样式标准/脚本标准?

简单介绍: 1. Bootstrap于2010年Twitter开源将常见的CSS布局小组件和JS插件进行了封装,大大规范且提高了代码质量及开发效率. 2. Bootstrap包含完整的基础CSS插件,丰富的预定义样式表,基于JQuery的JS插件集,非常灵活的响应式删栏系统,支持跨平台,且完全支持自定义. 注意: Bootstrap的所有JS插件都依赖jQuery库,所以要确保在使用这些功能的时候引用相应的jQuery文件 模版标准: <!DOCTYPE html> <html lang

网站前端_KindEditor.基础入门.0001.KindEditor_3.4.2配置参数?

初始方式: 说明: 在快速入门中使用KE.show({ .. .})来初始化了一个编辑器,具体进入js/kindeditor.js下可以看到KE对象下的show方法先调用了KE的init方法然后又调用了其event事件对象的ready方法,内部其实是调用的KE的create方法,传递的参数为args的id属性,所以可通过2种方式来初始化编辑器 # 方式一 : # 方式二 : 注意: 无论使用哪种方式初始化编辑器,都需要传递配置对象{ ... },配置对象中id属性是必须配置的,其它的属性默认采用

网站前端_JavaScript-基础入门.0009.JavaScript对象类型

对象简介: 说明: Object属于引用类型,引用类型是一种数据结构,用于将数据和功能组织在一起,如var newObj = new Object(),这行代码创建了Object引用类型的一个新实例,保存在newObject中,使用的构造函数是Object,它只为新对象定义了默认的属性和方法. 对象相关: 说明: Object实例虽然不具备多少功能但对于应用程序中的存储和传输数据而言,确实是非常理想的选择. /*  * 创建对象方式  */ // 支持构造参数 var newObj = new 

网站前端_JavaScript-基础入门.0015.JavaScript面向对象

简单介绍: 说明: Js中的对象似乎无序属性的集合,其属性可以包含基本值,对象,函数,严格的说也就是对象是一组没有特定顺序的键值对,每个对象都是基于一个引用类型创建 /*  * 创建对象,强烈推荐字面量式创建  */ var person = {     name: '李满满',     age: 25,     job: '运维开发工程师',     sayInfo: function(){         var info = '姓名 : '+this.name+'\n'+