闭包应用场景以及作用
- 定义
有权访问另一个函数作用域中变量的函数。创建方式,就是在一个函数内部创建另一个函数,通过另一个函数访问这个函数的局部变量。
- 写第三方库(jquery lodash等)
- 立即执行函数(作用域包裹)
(function(){ })() - 作用
- 避免全局污染
所有库的逻辑,库所定义和使用的变量全部被封装到了该函数 的作用域中。
- 隐私保护
但凡在立即执行函数中声明的函数、变量等,除非是自己想暴露, 否则绝无可能在外部获得。
- so
所以,当我们撰写自己的库的时候,也可以考虑在最外层包裹上一个立即执行 函数。既不受外部影响,也不给外部舔麻烦。
- 缺点
注意:使用闭包会把局部变量驻留在内存中,避免了使用全局变量。由于闭包作用域返回的局部变量资源不会被立刻销毁回收,所以可能会占用更多的内存。
- 参考
线程解疑
作者:pansz 链接:www.zhihu.com/question/19… 1。单进程单线程:一个人在一个桌子上吃菜。2。单进程多线程:多个人在同一个桌子上一起吃菜。3。多进程单线程:多个人每个人在自己的桌子上吃菜。多线程的问题是多个人同时吃一道菜的时候容易发生争抢,例如两个人同时夹一个菜,一个人刚伸出筷子,结果伸到的时候已经被夹走菜了。。。此时就必须等一个人夹一口之后,在还给另外一个人夹菜,也就是说资源共享就会发生冲突争抢。1。对于 Windows 系统来说,【开桌子】的开销很大,因此 Windows 鼓励大家在一个桌子上吃菜。因此 Windows 多线程学习重点是要大量面对资源争抢与同步方面的问题。2。对于 Linux 系统来说,【开桌子】的开销很小,因此 Linux 鼓励大家尽量每个人都开自己的桌子吃菜。这带来新的问题是:坐在两张不同的桌子上,说话不方便。因此,Linux 下的学习重点大家要学习进程间通讯的方法。--补充:有人对这个开桌子的开销很有兴趣。我把这个问题推广说开一下。开桌子的意思是指创建进程。开销这里主要指的是时间开销。可以做个实验:创建一个进程,在进程中往内存写若干数据,然后读出该数据,然后退出。此过程重复 1000 次,相当于创建/销毁进程 1000 次。在我机器上的测试结果是: UbuntuLinux:耗时 0.8 秒 Windows7:耗时 79.8 秒 两者开销大约相差一百倍。这意味着,在 Windows 中,进程创建的开销不容忽视。换句话说就是,Windows 编程中不建议你创建进程,如果你的程序架构需要大量创建进程,那么最好是切换到 Linux 系统。大量创建进程的典型例子有两个,一个是 gnu autotools 工具链,用于编译很多开源代码的,他们在 Windows 下编译速度会很慢,因此软件开发人员最好是避免使用 Windows。另一个是服务器,某些服务器框架依靠大量创建进程来干活,甚至是对每个用户请求就创建一个进程,这些服务器在 Windows 下运行的效率就会很差。这"可能"也是放眼全世界范围,Linux 服务器远远多于 Windows 服务器的原因。--再次补充:如果你是写服务器端应用的,其实在现在的网络服务模型下,开桌子的开销是可以忽略不计的,因为现在一般流行的是按照 CPU 核心数量开进程或者线程,开完之后在数量上一直保持,进程与线程内部使用协程或者异步通信来处理多个并发连接,因而开进程与开线程的开销可以忽略了。另外一种新的开销被提上日程:核心切换开销。现代的体系,一般 CPU 会有多个核心,而多个核心可以同时运行多个不同的线程或者进程。当每个 CPU 核心运行一个进程的时候,由于每个进程的资源都独立,所以 CPU 核心之间切换的时候无需考虑上下文。当每个 CPU 核心运行一个线程的时候,由于每个线程需要共享资源,所以这些资源必须从 CPU 的一个核心被复制到另外一个核心,才能继续运算,这占用了额外的开销。换句话说,在 CPU 为多核的情况下,多线程在性能上不如多进程。因而,当前面向多核的服务器端编程中,需要习惯多进程而非多线程。
Web Workers 解疑
- 为什么JavaScript是单线程?
JavaScript语言的一大特点就是单线程,也就是说,同一个时间只能做一件事。那 么,为什么JavaScript不能有多个线程呢?这样能提高效率啊。 JavaScript的单线程,与它的用途有关。作为浏览器脚本语言,JavaScript的主要用途是与用户互动,以及操作DOM。这决定了它只能是单线程,否则会带来很复杂的同步问题。比如,假定JavaScript同时有两个线程,一个线程在某个DOM节点上添加内容,另一个线程删除了这个节点,这时浏览器应该以哪个线程为准? 所以,为了避免复杂性,从一诞生,JavaScript就是单线程,这已经成了这门语言的核心特征,将来也不会改变。 为了利用多核CPU的计算能力,HTML5提出Web Worker标准,允许JavaScript脚本创建多个线程,但是子线程完全受主线程控制,且不得操作DOM。所以,这个新标准并没有改变JavaScript单线程的本质。
- 新曙光:Web Worker
单线程始终是一个痛点,为了利用多核 CPU 的计算能力,HTML5 提出 Web Worker 标准,允许 JavaScript 脚本创建多个线程。但是子线程完全受主线程控制,且不得操作 DOM。所以,这个新标准并没有改变 JavaScript 单线程的本质。Web Workers 是现代浏览器提供的一个 JavaScript 多线程解决方案,我们可以找到很多使用场景:
- 应用场景
- 我们可以用 Web Worker 做一些大计算量的操作;
- 可以实现轮询,改变某些状态;
- 页头消息状态更新,比如页头的消息个数通知;
- 高频用户交互,拼写检查,譬如:根据用户的输入习惯、历史记录以及缓存等信息来协助用户完成输入的纠错、校正功能等
- 加密:加密有时候会非常地耗时,特别是如果当你需要经常加密很多数据的时候(比如,发往服务器前加密数据)。
- 预取数据:为了优化网站或者网络应用及提升数据加载时间,你可以使用 Workers 来提前加载部分数据以备不时之需。
加密是一个使用 Web Worker 的绝佳场景,因为它并不需要访问 DOM 或者利用其它魔法,它只是纯粹使用算法进行计算而已。随着大众对个人敏感数据的日益重视,信息安全和加密也成为重中之重。这可以从近期的 12306 用户数据泄露事件中体现出来。 一旦在 Worker 进行计算,它对于用户来说是无缝地且不会影响到用户体验。
- 局限性
在 worker 内,不能直接操作 DOM 节点,也不能使用 window 对象的默认方法和属性。然而我们可以使用大量window 对象之下的东西,包括 WebSockets,IndexedDB 以及 FireFox OS 专用的 Data Store API 等数据存储机制。 这是因为:worker.js 执行的上下文,与主页面 HTML 执行时的上下文并不相同,最顶层的对象并不是 Window,woker.js 执行的全局上下文,而是 WorkerGlobalScope,
workers 和主线程间的数据传递通过这样的消息机制进行:双方都使用 postMessage() 方法发送各自的消息,使用onmessage 事件处理函数来响应消息(消息被包含在 Message 事件的 data 属性中)。这个过程中数据并不是被共享而是被复制。
同源限制分配给 Worker 线程运行的脚本文件,必须与主线程的脚本文件同源。
文件限制Worker 线程无法读取本地文件,即不能打开本机的文件系统(file://),它所加载的脚本,必须来自服务器。
不允许本地文件
内容安全策略 有别于创建它的 document 对象,worker 有它自己的执行上下文。因此普遍来说,worker 并不受限于创建它的document(或者父级 worker )的内容安全策略。
Service Worker新晋宠儿
Service Worker是一个在浏览器后台运行,和当前页面没有关联的脚本,后台运行,用来实现一些不依赖页面或者用户交互的特性,比方说缓存啊,消息推送之类。
全局变量的缺点
首先,全局变量保存在静态存储区,程序开始运行时为其分配内存,程序结束时释放该内存。与局部变量的动态分配。动态释放相比,生存期比较长,因此过多的全局变量会占用较多的内存单元;
其次,全局变量破坏了函数的封装性能。函数象一个黑匣子,一般是通过函数参数和返回值进行输入输出,函数内部实现相对独立。但函数中如果使用了全局变量,那么函 数体内的语句就可以绕过函数参数和返回值进行存取,这种情况破坏了函数的独立性,使函数对全局变量产生依赖。同时,也降低了该函数的可移植性。
最后,全局变量使函数的代码可读性降低。由于多个函数都可能使用全局变量,函数执行时全局变量的值可能随时发生变化,对于程序的查错和调试都非常不利。