koa中生成器函数generator执行顺序详解
ES6的generator http://book.apebook.org/minghe/koa-action/co/start.html
function* gen() {
var a = yield 'start';
console.log(a);
var b = yield 'end';
console.log(b);
return 'over';
}
var it = gen();
console.log(it.next()); // {value: 'start', done: false}
console.log(it.next(22)); // 22 {value: 'end', done: false}
console.log(it.next(333)); // 333 {value: 'over', done: true}
带有 *
的函数声明表示是一个 generator 函数,当执行 gen()
时,函数体内的代码并没有执行,而是返回了一个 generator 对象。
generator 函数通常和 yield 结合使用,函数执行到每个 yield 时都会暂停并返回 yield 的右值。下次调用 next 时,函数会从 yield 的下一个语句继续执行。等到整个函数执行完,next 方法返回的 done 字段会变成 true,并且将函数返回值作为 value 字段。
By admin
read more给一个正在运行的Docker容器动态添加Volume(转)
之前有人问我Docker容器启动之后还能否再挂载卷,考虑mnt命名空间的工作原理,我一开始认为这很难实现。不过现在我认为是它实现的。
简单来说,要想将磁盘卷挂载到正在运行的容器上,我们需要:
- 使用nsenter将包含这个磁盘卷的整个文件系统mount到临时挂载点上;
- 从我们想当作磁盘卷使用的特定文件夹中创建绑定挂载(bind mount)到这个磁盘卷的位置;
- umount第一步创建的临时挂载点。
注意事项
在下面的示例中,我故意包含了$符号来表示这是Shell命令行提示符,以帮助大家区分哪些是你需要输入的,哪些是机器回复的。有一些多行命令,我也继续用>。我知道这样使得例子里的命令无法轻易得被拷贝粘贴。如果你想要拷贝粘贴代码,请查看文章最后的示例脚本。
详细步骤
下面示例的前提是你已经使用如下命令启动了一个简单的名为charlie的容器:
$ docker run --name charlie -ti ubuntu bash
我们需要做的是将宿主文件夹 /home/jpetazzo/Work/DOCKER/docker
挂载到容器里的 /src
目录。好了,让我们开始吧。
nsenter
首先,我们需要nsenter以及docker-enter帮助脚本。为什么?因为我们要从容器中mount文件系统。由于安全性的考虑,容器不允许我们这么做。使用nsenter,我们可以突破上述安全限制,在容器的上下文(严格地说,是命名空间)中运行任意命令。当然,这必须要求拥有Docker宿主机的root权限。
nsenter最简单的安装方式是和 docker-enter
脚本关联执行:
$ docker run --rm -v /usr/local/bin:/target jpetazzo/nsenter
更多细节,请查看nsenter项目主页。
找到文件系统
我们想要在容器里挂载包含宿主文件夹( /home/jpetazzo/Work/DOCKER/docker
)的文件系统。那我们就需要找出哪个文件系统包含这个目录。
首先,我们需要canonicalize(或者解除引用)文件,以防这是一个符号链接,或者它的路径包含符号链接:
$ readlink --canonicalize /home/jpetazzo/Work/DOCKER/docker
/home/jpetazzo/go/src/github.com/docker/docker
哈,这的确是一个符号链接!让我们将其放入一个环境变量中:
$ HOSTPATH=/home/jpetazzo/Work/DOCKER/docker
$ REALPATH=$(readlink --canonicalize $HOSTPATH)
接下来,我们需要找出哪个文件系统包含这个路径。我们使用一个有点让人意想不到的工具来做,它就是 df
:
$ df $REALPATH
Filesystem 1K-blocks Used Available Use% Mounted on
/sda2 245115308 156692700 86157700 65% /home/jpetazzo
使用-P参数(强制使用POSIX格式,以防是exotic df,或者是其他人在Solaris或者BSD系统上装Docker时运行的df),将结果也放到一个变量里:
$ FILESYS=$(df -P $REALPATH | tail -n 1 | awk '{print $6}')
找到文件系统的设备(和sub-root)
By admin
read morenode出现“dyld: bad external relocation length”的解决办法
mac下有时候在执行 npm的过程中,我们强制中止了操作或者一些命令出现问题会提示“dyld: bad external relocation length”这个错误,这个时候只要将未下载完的文件删除即可,我这里使用 n 4.4.3下载的时候,网络出现异常,提示这个错误,只要删除 /usr/local/n/versions/node/4.4.3 这个目录即可。
如果还是不行的话,可以试着执行一下
brew doctor
命令,根据提示操作就可以了。
我遇到的情况是使用node版本控制n安装新版本号的时候,好像安装包下载的不完整,但提示安装成功了,在最后提示这个错误。试了好多方法卸载重装也不行,最后根据 brew doctor 的提示,执行了
brew link --overwrite node
彻底解决了。
By admin
read morenodejs中package.json文件说明
推荐: http://jingpin.jikexueyuan.com/article/34254.html
package.json 中包含各种所需模块以及项目的配置信息(名称、版本、许可证等)meta 信息。
package.json文件可以通过npm init 来创建
包含可配置项
- name 名称
- 应用描述 description
- 版本号 version
- 应用的配置项 config
- 作者 author
- 资源仓库地址 respository
- 授权方式 licenses
- 目录 directories
- 应用入口文件 main
- 命令行文件 bin
- 项目应用运行依赖模块 dependencies
- 项目应用开发环境依赖 devDependencies
- 运行引擎 engines
- 脚本 script
简单模式
==========================
{
name: "myApp",
version :"0.0.1"
}
完整模式
===========================
{
"name": "myApp",
"version": "0.0.0",
"author" : "simple",
"description" : "Nodejs Package json介绍",
"keywords" : "javascript, nodejs",
"respository" : {
"type" :"git",
"url" :"http://path/to/url"
},
"bugs" : {
"url" : "http://path/to/bug",
"email" : "[email protected]"
},
"contributors" : [
{"name" : "zhangsan", "email" : "[email protected]"
]
"license" : "MIT",
"engines" : { "node" : "0.10.x"},
"script" : {
"start" : "node index.js"
},
"private": true,
"scripts": {
"start": "node ./bin/www"
},
"dependencies": {
"express": "~4.9.0",
"body-parser": "~1.8.1",
"cookie-parser": "~1.3.3",
"morgan": "~1.3.0",
"serve-favicon": "~2.1.3",
"debug": "~2.0.0",
"jade": "~1.6.0"
},
"devDependencies": {
"bower" : "~1.2.8",
"grunt" : "~0.4.1",
"grunt-contrib-concat" : "~0.3.0",
"grunt-contrib-jshint" : "~0.7.2",
"grunt-contrib-uglify" : "~0.2.7",
"grunt-contrib-clean" : "~0.5.0",
"browserify" : "2.36.1",
"grunt-browserify" : "~1.3.0"
}
}
1.scripts
运行指定脚本命令。
By admin
read morewindows平台下的PHP的线程安全版本与非线程安全版本的区别
Windows版的PHP从版本5.2.1开始有Thread Safe(线程安全)和None Thread Safe(NTS,非线程安全)之分(Linux/Unit平台没有这个概念的东西的),这两者不同在于何处?到底应该用哪种?这里做一个简单的介绍。
PHP有2中运行方式:ISAPI和FastCGI。
ISAPI执行方式是以DLL动态库的形式使用,可以在被用户请求后执行,在处理完一个用户请求后不会马上消失,所以需要进行线程安全检查,这样来提高程序的执行效率,所以如果是以ISAPI来执行PHP,建议选择Thread Safe版本;
而FastCGI执行方式是以单一线程来执行操作,所以不需要进行线程的安全检查,除去线程安全检查的防护反而可以提高执行效率,所以,如果是以FastCGI来执行PHP,建议选择Non Thread Safe版本。
对于apache服务器来说一般选择isapi方式,而对于nginx服务器则选择FastCGI方式。
1.Non Thread Safe版本php适用在使用CGI以及fastCGI的web服务器上,如nginx,lighttpd以及IIS的CGI模式下
2.Thread Safe版本php适用在使用ISAPI或者module的web服务器上,如IIS的ISAPI模式或者apache module模式
这只是一般的适用区别,并不绝对,也就是说两种版本在web服务器上都能使用,并不一定会出什么问题
By admin
read morePHP底层工作原理
从图上可以看出,php从下到上是一个4层体系
①Zend引擎
Zend整体用纯c实现,是php的内核部分,它将php代码翻译(词法、语法解析等一系列编译过程)为可执行opcode的处理并实现相应的处理方法、 实现了基本的数据结构(如hashtable、oo)、内存分配及管理、提供了相应的api方法供外部调用,是一切的核心,所有的外围功能均围绕zend 实现。
②Extensions
围绕着zend引擎,extensions通过组件式的方式提供各种基础服务,我们常见的各种内置函数(如array系列)、标准库等都是通过 extension来实现,用户也可以根据需要实现自己的extension以达到功能扩展、性能优化等目的(如贴吧正在使用的php中间层、富文本解析 就是extension的典型应用)。
③Sapi
Sapi全称是Server Application Programming Interface,也就是服务端应用编程接口,sapi通过一系列钩子函数,使得php可以和外围交互数据,这是php非常优雅和成功的一个设计,通过 sapi成功的将php本身和上层应用解耦隔离,php可以不再考虑如何针对不同应用进行兼容,而应用本身也可以针对自己的特点实现不同的处理方式。后面 将在sapi章节中介绍
④上层应用
这就是我们平时编写的php程序,通过不同的sapi方式得到各种各样的应用模式,如通过webserver实现web应用、在命令行下以脚本方式运行等等。
构架思想:
引擎(Zend)+组件(ext)的模式降低内部耦合
中间层(sapi)隔绝web server和php
******************************
如果php是一辆车,那么
车的框架就是php本身
Zend是车的引擎(发动机)
Ext下面的各种组件就是车的轮子
Sapi可以看做是公路,车可以跑在不同类型的公路上
而一次php程序的执行就是汽车跑在公路上。
因此,我们需要:性能优异的引擎+合适的车轮+正确的跑道
Apache和php的关系
Apache对于php的解析,就是通过众多Module中的php Module来完成的。
把php最终集成到Apache系统中,还需要对Apache进行一些必要的设置。这里,我们就以php的mod_php5 SAPI运行模式为例进行讲解,至于SAPI这个概念后面我们还会详细讲解。
假定我们安装的版本是Apache2 和 Php5,那么需要编辑Apache的主配置文件http.conf,在其中加入下面的几行内容:
Unix/Linux环境下:
LoadModule php5_module modules/mod_php5.so
AddType application/x-httpd-php .php
注:其中modules/mod_php5.so 是X系统环境下mod_php5.so文件的安装位置。
Windows环境下:
LoadModule php5_module d:/php/php5apache2.dll
AddType application/x-httpd-php .php
注:其中d:/php/php5apache2.dll 是在Windows环境下php5apache2.dll文件的安装位置。
这两项配置就是告诉Apache Server,以后收到的Url用户请求,凡是以php作为后缀,就需要调用php5_module模块(mod_php5.so/ php5apache2.dll)进行处理。
Apache的生命周期
Apach的请求处理流程
Apache请求处理循环详解
Apache请求处理循环的11个阶段都做了哪些事情呢?
1、Post-Read-Request阶段
在正常请求处理流程中,这是模块可以插入钩子的第一个阶段。对于那些想很早进入处理请求的模块来说,这个阶段可以被利用。
2、URI Translation阶段 Apache在本阶段的主要工作:将请求的URL映射到本地文件系统。模块可以在这阶段插入钩子,执行自己的映射逻辑。mod_alias就是利用这个阶段工作的。
By admin
read moreNPM 命令介绍(转)
NPM是随同NodeJS一起安装的包管理工具,能解决NodeJS代码部署上的很多问题,常见的使用场景有以下几种:
- 允许用户从NPM服务器下载别人编写的第三方包到本地使用。
- 允许用户从NPM服务器下载并安装别人编写的命令行程序到本地使用。
- 允许用户将自己编写的包或命令行程序上传到NPM服务器供别人使用。
由于新版的nodejs已经集成了npm,所以之前npm也一并安装好了。同样可以通过输入 **“npm -v” **来测试是否成功安装。命令如下,出现版本提示表示安装成功:
$ npm -v
2.3.
如果你安装的是旧版本的 npm,可以很容易得通过 npm 命令来升级,命令如下:
$ sudo npm install npm -g
/usr/local/bin/npm -> /usr/local/lib/node_modules/npm/bin/npm-cli.js
[email protected] /usr/local/lib/node_modules/npm
如果是 Window 系统使用以下命令即可:
npm install npm -g
使用 npm 命令安装模块
npm 安装 Node.js 模块语法格式如下:
$ npm install <Module Name>
以下实例,我们使用 npm 命令安装常用的 Node.js web框架模块 express:
$ npm install express
安装好之后,express 包就放在了工程目录下的 node_modules 目录中,因此在代码中只需要通过 require(‘express’) 的方式就好,无需指定第三方包路径。
var express = require('express');
全局安装与本地安装
npm 的包安装分为本地安装(local)、全局安装(global)两种,从敲的命令行来看,差别只是有没有-g而已,比如
npm install express # 本地安装
npm install express -g # 全局安装
如果出现以下错误:
By admin
read morenodejs学习资料
修改npm包管理器的registry( registry.npmjs.org)为淘宝镜像( npm.taobao.org),参考nam config -h 相关命令
npm config set registry “https://registry.npm.taobao.org“
七天学会NodeJS http://nqdeng.github.io/7-days-nodejs/
Node.js Style Guide https://github.com/dead-horse/node-style-guide
深入Node.js的模块机制 http://www.infoq.com/cn/articles/nodejs-module-mechanism/
学习ES6生成器(Generator) http://www.toobug.net/article/learning_es6_generator.html
require() 源码解读 http://www.ruanyifeng.com/blog/2015/05/require.html
npm 模块安装机制简介 http://www.ruanyifeng.com/blog/2016/01/npm-install.html
NodeJs 测试框mocha https://cnodejs.org/topic/516526766d38277306c7d277
exports 和 module.exports 的区别
http://cnodejs.org/topic/5231a630101e574521e45ef8 http://cnodejs.org/topic/52308842101e574521c16e06
NodeJS 开发者的 10 个常见错误 http://web.jobbole.com/82504/
koa资料
《koa实战》 http://book.apebook.org/minghe/koa-action/index.html
yield 和 yield* http://taobaofed.org/blog/2015/11/19/yield-and-delegating-yield/
【koa经典入门教程】 https://github.com/koajs/kick-off-koa https://github.com/koajs/koa/wiki
koa源码分析系列 http://purplebamboo.github.io/2014/05/24/koa-source-analytics-1/ http://cnodejs.org/topic/56936889c2289f51658f0926 如何优雅的在 koa 中处理错误 http://taobaofed.org/blog/2016/03/18/error-handling-in-koa/
项目结构图 https://github.com/focusaurus/express_code_structure http://blog.csdn.net/tinico/article/details/18033433 https://cnodejs.org/topic/538edddda087f456207d1a81
10个最好的 Node.js MVC 框架
http://www.cnblogs.com/lhb25/p/10-best-node-js-mvc-frameworks.html
By admin
read morenodejs中exports与module.exports的区别
对于两者的理解只要记住一句话:“exports就是module.exports****的引用”即可。
推荐易理解的文档: http://cnodejs.org/topic/5231a630101e574521e45ef8
原文:
你肯定非常熟悉nodejs模块中的exports对象,你可以用它创建你的模块。例如:(假设这是rocker.js文件)
exports.name = function() {
console.log('My name is Lemmy Kilmister');
};
在另一个文件中你这样引用
var rocker = require('./rocker.js');
rocker.name(); // 'My name is Lemmy Kilmister'
那到底Module.exports是什么呢?它是否合法呢?
其实,Module.exports
才是真正的接口,exports只不过是它的一个辅助工具。 最终返回给调用的是Module.exports
而不是exports。
所有的exports收集到的属性和方法,都赋值给了**Module.exports
。当然,这有个前提,就是Module.exports
本身不具备任何属性和方法``。如果,
Module.exports
**`已经具备一些属性和方法,那么exports收集来的信息将被忽略。```
修改rocker.js如下:
module.exports = 'ROCK IT!';
exports.name = function() {
console.log('My name is Lemmy Kilmister');
};
再次引用执行rocker.js
var rocker = require('./rocker.js');
rocker.name(); // TypeError: Object ROCK IT! has no method 'name'
发现报错:对象“ROCK IT!”没有name方法(因为第二行的exports是对第一行的module.exports的引用,第二句exports.name则表示 module.exports.name,它想给声明一个name方法,但是第一行module.exports = ‘ROCK IT!’已经进行了赋值操作,值为一个字符串常量,所以最后提示错误 “对象ROCK IT! 没有name方法”)。
rocker模块忽略了exports收集的name方法,返回了一个字符串“ROCK IT!”。由此可知,你的模块并不一定非得返回“实例化对象”。你的模块可以是任何合法的javascript对象–boolean, number, date, JSON, string, function, array等等。
By admin
read morejQuery.extend和jQuery.fn.extend的区别-转
jQuery.extend和jQuery.fn.extend的区别,其实从这两个办法本身也就可以看出来。很多地方说的也不详细。这里详细说说之间的区别.
- 我们先把jQuery看成了一个类,这样好理解一些。
jQuery.extend(),是扩展的jQuery这个类。
假设我们把jQuery这个类看成是人类,能吃饭能喝水能跑能跳,现在我们用jQuery.extend这个方法给这个类拓展一个能唱歌的技能。这样的话,不论是男人,女人,xx人…..等能继承这个技能(方法)了。
可以如下图这样写着:
- 然后:$.liu();这样就能打印出来”liu“这个字符串
代码在下面:
3. 这说明啥啊,这说明.liu()变成了jQuery这个类本身的方法(object)嘛。他现在能”唱歌“了。但是吧,这个能力啊,只有代表全人类的 jQuery 这个类本身,才能用啊。你个人想用,你张三李四王五麻六,你个小草民能代表全人类嘛?
所以啊,这个扩展也就是所谓的静态方法。只跟这个 类 本身有关。跟你具体的实例化对象是没关系滴。
我们再看看jQuery.fn.extend()这个方法。
从字面理解嘛,这个拓展的是jQuery.fn的方法。
jQuery.fn是啥玩意呢?
源码如下
4. 哦,原来jQuery.fn=jQuery.prototype,就是原型啊。
那就一目了然了,jQuery.fn.extend拓展的是jQuery对象(原型的)的方法啊!
对象是啥?就是类的实例化嘛,例如
$(“#abc”)
这个玩意就是一个实例化的jQuery对象嘛。
那就是说,jQuery.fn.extend拓展的方法,你得用在jQuery对象上面才行啊!他得是张三李四王五痳六这些实例化的对象才能用啊。
说白了就是得这么用(假设xyz()是拓展的方法):
$(‘selector’).xyz();
你要是这么用$.xyz();是会出错误滴。
代码看下面图片:
转: http://jingyan.baidu.com/article/fec4bce259ef67f2608d8b10.html
By admin
read moreGit-svn命令对比表,svn用户必看
提供给从svn转git的开发人员参考
Git与Subversion的命令对比表
操作 | GIT | SUBVERSION |
---|---|---|
复制数据仓库 | git clone | svn checkout |
提交 | git commit | svn commit |
查看提交的详细记录 | git show | svn cat |
确认状态 | git status | svn status |
确认差异 | git diff | svn diff |
确认记录 | git log | svn log |
添加 | git add | svn add |
移动 | git mv | svn mv |
删除 | git rm | svn rm |
取消修改 | git checkout / git reset | svn revert (※1) |
创建分支 | git branch | svn copy (※2) |
切换分支 | git checkout | svn switch |
合并 | git merge | svn merge |
创建标签 | git tag | svn copy (※2) |
从服务端更新本地 | git pull / git fetch | svn update |
推送到远端 | git push | svn commit (※3) |
忽略档案目录 | .gitignore | .svnignore |
※1. SVN的revert是用来取消修改,但Git的revert是用来消除提交。所以即使是同样的命令,在SVN和Git里的含义是不同的。
By admin
read more深入解析php中的foreach问题
篇文章是对php中的foreach问题进行了详细的分析介绍,需要的朋友参考下
前言: php4中引入了foreach结构,这是一种遍历数组的简单方式。相比传统的for循环,foreach能够更加便捷的获取键值对。在php5之前,foreach仅能用于数组;php5之后,利用foreach还能遍历对象(详见:遍历对象)。本文中仅讨论遍历数组的情况。foreach虽然简单,不过它可能会出现一些意外的行为,特别是代码涉及引用的情况下。
下面列举了几种case,有助于我们进一步认清foreach的本质。
问题1:
$arr = array(1,2,3);
foreach($arr as $k => &$v) {
$v = $v * 2;
}
// now $arr is array(2, 4, 6)
foreach($arr as $k => $v) {
echo "$k", " => ", "$v";
}
先从简单的开始,如果我们尝试运行上述代码,就会发现最后输出为0=>2 1=>4 2=>4 。
为何不是0=>2 1=>4 2=>6 ?
其实,我们可以认为 foreach($arr as $k => $v) 结构隐含了如下操作,分别将数组当前的’键’和当前的’值’赋给变量$k和$v。具体展开形如:
foreach($arr as $k => $v){
//在用户代码执行之前隐含了2个赋值操作
$v = currentVal();
$k = currentKey();
//继续运行用户代码
……
}
根据上述理论,现在我们重新来分析下第一个foreach:
第1遍循环,由于$v是一个引用,因此$v = &$arr[0],$v=$v*2相当于$arr[0]*2,因此$arr变成2,2,3
By admin
read moreJavaScript垃圾回收机制
一、垃圾回收的必要性
下面这段话引自《JavaScript权威指南(第四版)》
_ 由于字符串、对象和数组没有固定大小,所有当他们的大小已知时,才能对他们进行动态的存储分配。JavaScript程序每次创建字符串、数组或对象时,解释器都必须分配内存来存储那个实体。只要像这样动态地分配了内存,最终都要释放这些内存以便他们能够被再用,否则,JavaScript的解释器将会消耗完系统中所有可用的内存,造成系统崩溃。_
这段话解释了为什么需要系统需要垃圾回收,JS不像C/C++,他有自己的一套垃圾回收机制(Garbage Collection)。JavaScript的解释器可以检测到何时程序不再使用一个对象了,当他确定了一个对象是无用的时候,他就知道不再需要这个对象,可以把它所占用的内存释放掉了。例如:
var a = "before";
var b = "override a";
var a = b; //重写a
这段代码运行之后,“before”这个字符串失去了引用(之前是被a引用),系统检测到这个事实之后,就会释放该字符串的存储空间以便这些空间可以被再利用。
二、垃圾回收原理浅析
现在各大浏览器通常用采用的垃圾回收有两种方法:标记清除、引用计数。
1、标记清除
这是javascript中最常用的垃圾回收方式。当变量进入执行环境是,就标记这个变量为“进入环境”。从逻辑上讲,永远不能释放进入环境的变量所占用的内存,因为只要执行流进入相应的环境,就可能会用到他们。当变量离开环境时,则将其标记为“离开环境”。 垃圾收集器在运行的时候会给存储在内存中的所有变量都加上标记。然后,它会去掉环境中的变量以及被环境中的变量引用的标记。而在此之后再被加上标记的变量将被视为准备删除的变量,原因是环境中的变量已经无法访问到这些变量了。最后。垃圾收集器完成内存清除工作,销毁那些带标记的值,并回收他们所占用的内存空间。
关于这一块,建议读读 Tom大叔的几篇文章,关于作用域链的一些知识详解,读完差不多就知道了,哪些变量会被做标记。
2、引用计数
另一种不太常见的垃圾回收策略是引用计数。引用计数的含义是跟踪记录每个值被引用的次数。当声明了一个变量并将一个引用类型赋值给该变量时,则这个值的引用次数就是1。相反,如果包含对这个值引用的变量又取得了另外一个值,则这个值的引用次数就减1。当这个引用次数变成0时,则说明没有办法再访问这个值了,因而就可以将其所占的内存空间给收回来。这样,垃圾收集器下次再运行时,它就会释放那些引用次数为0的值所占的内存。
但是用这种方法存在着一个问题,下面来看看代码:
function problem() {
var objA = new Object();
var objB = new Object();
objA.someOtherObject = objB;
objB.anotherObject = objA;
}
在这个例子中,objA和objB通过各自的属性相互引用;也就是说这两个对象的引用次数都是2。在采用引用计数的策略中,由于函数执行之后,这两个对象都离开了作用域,函数执行完成之后,objA和objB还将会继续存在,因为他们的引用次数永远不会是0。这样的相互引用如果说很大量的存在就会导致大量的内存泄露。
我们知道,IE中有一部分对象并不是原生JavaScript对象。例如,其BOM和DOM中的对象就是使用C++以COM(Component Object Model,组件对象)对象的形式实现的,而COM对象的垃圾回收器就是采用的引用计数的策略。因此,即使IE的Javascript引擎使用标记清除的策略来实现的,但JavaScript访问的COM对象依然是基于引用计数的策略的。说白了,只要IE中涉及COM对象,就会存在循环引用的问题。看看下面的这个简单的例子:
var element = document.getElementById("some_element");
var myObj =new Object();
myObj.element = element;
element.someObject = myObj;
上面这个例子中,在一个DOM元素(element)与一个原生JavaScript对象(myObj)之间建立了循环引用。其中,变量myObj有一个名为element的属性指向element;而变量element有一个名为someObject的属性回指到myObj。由于循环引用,即使将例子中的DOM从页面中移除,内存也永远不会回收。
不过上面的问题也不是不能解决,我们可以手动切断他们的循环引用。
myObj.element = null;
element.someObject =null;
这样写代码的话就可以解决循环引用的问题了,也就防止了内存泄露的问题。
By admin
read more