当前位置: 首页 > 编程日记 > 正文

关于Javascript的内存泄漏问题的整理稿

常规循环引用内存泄漏和Closure内存泄漏

要了解javascript的内存泄漏问题,首先要了解的就是javascript的GC原理。

我记得原来在犀牛书《JavaScript: The Definitive Guide》中看到过,IE使用的GC算法是计数器,因此只碰到循环 引用就会造成memory leakage。后来一直觉得和观察到的现象很不一致,直到看到Eric的文章,才明白犀牛书的说法没有说得很明确,估计该书成文后IE升级过算法吧。在IE 6中,对于javascript object内部,jscript使用的是mark-and-sweep算法,而对于javascript object与外部object(包括native object和vbscript object等等)的引用时,IE 6使用的才是计数器的算法。

Eric Lippert在http://blogs.msdn.com/ericlippert/archive/2003/09/17/53038.aspx一文中提到IE 6中JScript的GC算法使用的是nongeneration mark-and-sweep。对于javascript对算法的实现缺陷,文章如是说:
"The benefits of this approach are numerous, but the principle benefit is that circular references are not leaked unless the circular reference involves an object not owned by JScript. "
也就是说,IE 6对于纯粹的Script Objects间的Circular References是可以正确处理的,可惜它处理不了的是JScript与Native Object(例如Dom、ActiveX Object)之间的Circular References。
所以,当我们出现Native对象(例如Dom、ActiveX Object)与Javascript对象间的循环引用时,内存泄露的问题就出现了。当然,这个bug在IE 7中已经被修复了http://www.quirksmode.org/blog/archives/2006/04/ie_7_and_javasc.html]。

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/IETechCol/dnwebgen/ie_leak_patterns.asp 中有个示意图和简单的例子体现了这个问题:

< html >
    
< head >
        
< script language = " JScript " >

        
var  myGlobalObject;

        
function  SetupLeak()  // 产生循环引用,因此会造成内存泄露
        {
            
//  First set up the script scope to element reference
            myGlobalObject  =
                document.getElementById(
" LeakedDiv " );

            
//  Next set up the element to script scope reference
            document.getElementById( " LeakedDiv " ).expandoProperty  =
                myGlobalObject;
        }


        
function  BreakLeak()  // 解开循环引用,解决内存泄露问题
        {
            document.getElementById(
" LeakedDiv " ).expandoProperty  =
                
null ;
        }
        
</ script >
    
</ head >

    
< body onload = " SetupLeak() "  onunload = " BreakLeak() " >
        
< div id = " LeakedDiv " ></ div >
    
</ body >
</ html >
上面这个例子,看似很简单就能够解决内存泄露的问题。可惜的是,当我们的代码中的结构复杂了以后,造成循环引用的原因开始变得多样,我们就没法那么容易观察到了,这时候,我们必须对代码进行仔细的检查。

尤其是当碰到Closure,当我们往Native对象(例如Dom对象、ActiveX Object)上绑定事件响应代码时,一个不小心,我们就会制造出Closure Memory Leak。其关键原因,其实和前者是一样的,也是一个跨javascript object和native object的循环引用。只是代码更为隐蔽,这个隐蔽性,是由于javascript的语言特性造成的。但在使用类似内嵌函数的时候,内嵌的函数有拥有一个reference指向外部函数的scope,包括外部函数的参数,因此也就很容易造成一个很隐蔽的循环引用,例如:
DOM_Node.onevent ->function_object.[ [ scope ] ] ->scope_chain ->Activation_object.nodeRef ->DOM_Node。

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/IETechCol/dnwebgen/ie_leak_patterns.asp]有个例子极深刻地显示了该隐蔽性:

< html >
    
< head >
        
< script language = " JScript " >

        
function  AttachEvents(element)
        {
            
//  This structure causes element to ref ClickEventHandler  //element有个引用指向函数ClickEventHandler()
            element.attachEvent( " onclick " , ClickEventHandler);

            
function  ClickEventHandler()
            {
                
//  This closure refs element  //该函数有个引用指向AttachEvents(element)调用Scope,也就是执行了参数element。
                
            }
        }

        
function  SetupLeak()
        {
            
//  The leak happens all at once
            AttachEvents(document.getElementById( " LeakedDiv " ));
        }

        
</ script >
    
</ head >

    
< body onload = " SetupLeak() "  onunload = " BreakLeak() " >
        
< div id = " LeakedDiv " ></ div >
    
</ body >
</ html >

还有这个例子在IE 6中同样原因会引起泄露



function  leakmaybe() {
var  elm  =  document.createElement( " DIV " );
  elm.onclick 
=   function () {
return   2   +   2 ;
  }
}

for  ( var  i  =   0 ; i   10000 ; i ++ ) {
  leakmaybe();
}


btw:
关于Closure的知识,大家可以看看http://jibbering.com/faq/faq_notes/closures.html这篇文章,习惯中文也可以看看zkjbeyond的blog,他对Closure这篇文章进行了简要的翻译:http://www.blogjava.net/zkjbeyond/archive/2006/05/19/47025.html。之所以会有这一系列的问题,关键就在于javascript是种函数式脚本解析语言,因此javascript中“函数中的变量的作用域是定义作用域,而不是动态作用域”,这点在犀牛书《JavaScript: The Definitive Guide》中的“Funtion”一章中有所讨论。
http://support.microsoft.com/default.aspx?scid=KB;EN-US;830555中也对这个问题举了很详细的例子。


一些 简单的解决方案

目前大多数ajax前端的javascript framework都利用对事件的管理,解决了该问题。

如果你需要自己解决这个问题,可以参考以下的一些方法:

  • http://outofhanwell.com/ieleak/index.php?title=Main_Page:有个不错的检测工具
  • http://youngpup.net/2005/0221010713 中提到:可以利用递归Dom树,解除event绑定,从而解除循环引用:

    														
    if (window.attachEvent) {
    var clearElementProps = [
    'data',
    'onmouseover',
    'onmouseout',
    'onmousedown',
    'onmouseup',
    'ondblclick',
    'onclick',
    'onselectstart',
    'oncontextmenu'
    ];

    window.attachEvent("onunload", function() {
    var el;
    for(var d = document.all.length;d--;){
    el = document.all[d];
    for(var c = clearElementProps.length;c--;){
    el[clearElementProps[c]] = null;
    }
    }
    });
    }
  • http://novemberborn.net/javascript/event-cache一文中则通过增加EventCache,从而给出一个相对结构化的解决方案

    /*     EventCache Version 1.0
        Copyright 2005 Mark Wubben

        Provides a way for automagically removing events from nodes and thus preventing memory leakage.
        See <http://novemberborn.net/javascript/event-cache> for more information.
        
        This software is licensed under the CC-GNU LGPL <http://creativecommons.org/licenses/LGPL/2.1/>
    */

    /*     Implement array.push for browsers which don't support it natively.
        Please remove this if it's already in other code 
    */
    if (Array.prototype.push  ==   null ){
        Array.prototype.push 
    =   function (){
            
    for ( var  i  =   0 ; i  <  arguments.length; i ++ ){
                
    this [ this .length]  =  arguments[i];
            };
            
    return   this .length;
        };
    };

    /*     Event Cache uses an anonymous function to create a hidden scope chain.
        This is to prevent scoping issues. 
    */
    var  EventCache  =   function (){
        
    var  listEvents  =  [];
        
        
    return  {
            listEvents : listEvents,
        
            add : 
    function (node, sEventName, fHandler, bCapture){
                listEvents.push(arguments);
            },
        
            flush : 
    function (){
                
    var  i, item;
                
    for (i  =  listEvents.length  -   1 ; i  >=   0 ; i  =  i  -   1 ){
                    item 
    =  listEvents[i];
                    
                    
    if (item[ 0 ].removeEventListener){
                        item[
    0 ].removeEventListener(item[ 1 ], item[ 2 ], item[ 3 ]);
                    };
                    
                    
    /*  From this point on we need the event names to be prefixed with 'on"  */
                    
    if (item[ 1 ].substring( 0 2 !=   " on " ){
                        item[
    1 =   " on "   +  item[ 1 ];
                    };
                    
                    
    if (item[ 0 ].detachEvent){
                        item[
    0 ].detachEvent(item[ 1 ], item[ 2 ]);
                    };
                    
                    item[
    0 ][item[ 1 ]]  =   null ;
                };
            }
        };
    }();

  • 使用方法也很简单:

    												
    <script type="text/javascript">
    function addEvent(oEventTarget, sEventType, fDest){
    if(oEventTarget.attachEvent){
    oEventTarget.attachEvent("on" + sEventType, fDest);
    } elseif(oEventTarget.addEventListener){
    oEventTarget.addEventListener(sEventType, fDest, true);
    } elseif(typeof oEventTarget[sEventType] == "function"){
    var fOld = oEventTarget[sEventType];
    oEventTarget[sEventType] = function(e){ fOld(e); fDest(e); };
    } else {
    oEventTarget[sEventType] = fDest;
    };

    /* Implementing EventCache for all event systems */
    EventCache.add(oEventTarget, sEventType, fDest, true);
    };


    function createLeak(){
    var body = document.body;

    function someHandler(){
                   return body;
    };

    addEvent(body, "click", someHandler);
    };

    window.onload = function(){
    var i = 500;
    while(i > 0){
    createLeak();
    i = i - 1;
    }
    };

    window.onunload = EventCache.flush;
    </script>
  • http://talideon.com/weblog/2005/03/js-memory-leaks.cfm 一文中的方法类似:

    /*
     * EventManager.js
     * by Keith Gaughan
     *
     * This allows event handlers to be registered unobtrusively, and cleans
     * them up on unload to prevent memory leaks.
     *
     * Copyright (c) Keith Gaughan, 2005.
     *
     * All rights reserved. This program and the accompanying materials
     * are made available under the terms of the Common Public License v1.0
     * (CPL) which accompanies this distribution, and is available at
     * http://www.opensource.org/licenses/cpl.php
     *
     * This software is covered by a modified version of the Common Public License
     * (CPL), where Keith Gaughan is the Agreement Steward, and the licensing
     * agreement is covered by the laws of the Republic of Ireland.
     
    */

    //  For implementations that don't include the push() methods for arrays.
    if  ( ! Array.prototype.push) {
        Array.prototype.push 
    =   function (elem) {
            
    this [ this .length]  =  elem;
        }
    }

    var  EventManager  =  {
        _registry: 
    null ,

        Initialise: 
    function () {
            
    if  ( this ._registry  ==   null ) {
                
    this ._registry  =  [];

                
    //  Register the cleanup handler on page unload.
                EventManager.Add(window,  " unload " this .CleanUp);
            }
        },

        
    /* *
         * Registers an event and handler with the manager.
         *
         * @param  obj         Object handler will be attached to.
         * @param  type        Name of event handler responds to.
         * @param  fn          Handler function.
         * @param  useCapture  Use event capture. False by default.
         *                     If you don't understand this, ignore it.
         *
         * @return True if handler registered, else false.
         
    */
        Add: 
    function (obj, type, fn, useCapture) {
            
    this .Initialise();

            
    //  If a string was passed in, it's an id.
             if  ( typeof  obj  ==   " string " ) {
                obj 
    =  document.getElementById(obj);
            }
            
    if  (obj  ==   null   ||  fn  ==   null ) {
                
    return   false ;
            }

            
    //  Mozilla/W3C listeners?
             if  (obj.addEventListener) {
                obj.addEventListener(type, fn, useCapture);
                
    this ._registry.push({obj: obj, type: type, fn: fn, useCapture: useCapture});
                
    return   true ;
            }

            
    //  IE-style listeners?
             if  (obj.attachEvent  &&  obj.attachEvent( " on "   +  type, fn)) {
                
    this ._registry.push({obj: obj, type: type, fn: fn, useCapture:  false });
                
    return   true ;
            }

            
    return   false ;
        },

        
    /* *
         * Cleans up all the registered event handlers.
         
    */
        CleanUp: 
    function () {
            
    for  ( var  i  =   0 ; i  <  EventManager._registry.length; i ++ ) {
                
    with  (EventManager._registry[i]) {
                    
    //  Mozilla/W3C listeners?
                     if  (obj.removeEventListener) {
                        obj.removeEventListener(type, fn, useCapture);
                    }
                    
    //  IE-style listeners?
                     else   if  (obj.detachEvent) {
                        obj.detachEvent(
    " on "   +  type, fn);
                    }
                }
            }

            
    //  Kill off the registry itself to get rid of the last remaining
             //  references.
            EventManager._registry  =   null ;
        }
    };

    使用起来也很简单

    												
    <html>
    <head>
    <script type=text/javascript src=EventManager.js></script>
    <script type=text/javascript>
    function onLoad() {

    EventManager.Add(document.getElementById(testCase),click,hit );
    returntrue;
    }

    function hit(evt) {
    alert(click);
    }
    </script>
    </head>

    <body οnlοad='javascript: onLoad();'>

    <div id='testCase' style='width:100%; height: 100%; background-color: yellow;'>
    <h1>Click me!</h1>
    </div>

    </body>
    </html>
  • google map api同样提供了一个类似的函数用在页面的unload事件中,解决Closure带来的内存泄露问题。
  • 当然,如果你不嫌麻烦,你也可以为每个和native object有关的就阿vascript object编写一个destoryMemory函数,用来手动调用,从而手动解除Dom对象的事件绑定。

  • 还有一种就是不要那么OO,抛弃Dom的一些特性,用innerHTML代替appendChild,避开循环引用。详细见http://birdshome.cnblogs.com/archive/2005/02/16/104967.html中的讨论贴。

Cross-Page Leaks

Cross-Page Leaks和下一节提到的Pseudo-Leaks在我看来,就是IE的bug, 虽然MS死皮赖脸不承认:)

大家可以看看这段例子代码:

< html >
    
< head >
        
< script language = " JScript " >

        
function  LeakMemory()  // 这个函数会引发Cross-Page Leaks
        {
            
var  hostElement  =  document.getElementById( " hostElement " );

            
//  Do it a lot, look at Task Manager for memory response

            
for (i  =   0 ; i  <   5000 ; i ++ )
            {
                
var  parentDiv  =
                    document.createElement(
" <div onClick='foo()'> " );
                
var  childDiv  =
                    document.createElement(
" <div onClick='foo()'> " );

                
//  This will leak a temporary object
                parentDiv.appendChild(childDiv);
                hostElement.appendChild(parentDiv);
                hostElement.removeChild(parentDiv);
                parentDiv.removeChild(childDiv);
                parentDiv 
=   null ;
                childDiv 
=   null ;
            }
            hostElement 
=   null ;
        }


        
function  CleanMemory()  // 而这个函数不会引发Cross-Page Leaks
        {
            
var  hostElement  =  document.getElementById( " hostElement " );

            
//  Do it a lot, look at Task Manager for memory response

            
for (i  =   0 ; i  <   5000 ; i ++ )
            {
                
var  parentDiv  =   document.createElement( " <div onClick='foo()'> " );
                
var  childDiv  =   document.createElement( " <div onClick='foo()'> " );

                
//  Changing the order is important, this won't leak
                hostElement.appendChild(parentDiv);
                parentDiv.appendChild(childDiv);
                hostElement.removeChild(parentDiv);
                parentDiv.removeChild(childDiv);
                parentDiv 
=   null ;
                childDiv 
=   null ;
            }
            hostElement 
=   null ;
        }
        
</ script >
    
</ head >

    
< body >
        
< button onclick = " LeakMemory() " > Memory Leaking Insert </ button >
        
< button onclick = " CleanMemory() " > Clean Insert </ button >
        
< div id = " hostElement " ></ div >
    
</ body >
</ html >

LeakMemory和CleanMemory这两段函数的唯一区别就在于他们的代码的循序,从代码上看,两段代码的逻辑都没有错。

但LeakMemory却会造成泄露。原因是LeakMemory()会先建立起parentDiv和childDiv之间的连接,这时候,为了让 childDiv能够获知parentDiv的信息,因此IE需要先建立一个临时的scope对象。而后parentDiv建立了和 hostElement对象的联系,parentDiv和childDiv直接使用页面document的scope。可惜的是,IE不会释放刚才那个临时的scope对象的内存空间,直到我们跳转页面,这块空间才能被释放。而CleanMemory函数不同,他先把parentDiv和 hostElement建立联系,而后再把childDiv和parentDiv建立联系,这个过程不需要单独建立临时的scope,只要直接使用页面 document的scope就可以了, 所以也就不会造成内存泄露了

详细原因,大家可以看看http://msdn.microsoft.com/library/default.asp?url=/library/en-us/IETechCol/dnwebgen/ie_leak_patterns.asp这篇文章。

btw:
IE 6中垃圾回收算法,就是从那些直接"in scope"的对象开始进行mark清除的:
Every variable which is "in scope" is called a "scavenger". A scavenger may refer to a number, an object, a string, whatever. We maintain a list of scavengers – variables are moved on to the scav list when they come into scope and off the scav list when they go out of scope.

Pseudo-Leaks

这个被称为“秀逗泄露”真是恰当啊:)
看看这个例子:

< html >
    
< head >
        
< script language = " JScript " >

        
function  LeakMemory()
        {
            
//  Do it a lot, look at Task Manager for memory response

            
for (i  =   0 ; i  <   5000 ; i ++ )
            {
                hostElement.text 
=   " function foo() { } " ;//看内存会不断增加
            }
        }
        
</ script >
    
</ head >

    
< body >
        
< button onclick = " LeakMemory() " > Memory Leaking Insert </ button >
        
< script id = " hostElement " > function  foo() { } </ script >
    
</ body >
</ html >

MS是这么解释的,这不是内存泄漏。如果您创建了许多无法获得也无法释放的对象,那才是内存泄漏。在这里,您将创建许多元素,Internet Explorer 需要保存它们以正确呈现页面。Internet Explorer 并不知道您以后不会运行操纵您刚刚创建的所有这些对象的脚本。当页面消失时(当您浏览完,离开浏览器时)会释放内存。它不会泄漏。当销毁页面时,会中断循环引用。

唉~~~

详细原因,大家可以看看http://msdn.microsoft.com/library/default.asp?url=/library/en-us/IETechCol/dnwebgen/ie_leak_patterns.asp这篇文章。

其它一些琐碎的注意点

变量定义一定要用var,否则隐式声明出来的变量都是全局变量,不是局部变量;
全局变量没用时记得要置null;
注意正确使用delete,删除没用的一些函数属性;
注意正确使用try...cache,确保去处无效引用的代码能被正确执行;
open出来的窗口即使close了,它的window对象还是存在的,要记得删除引用;
frame和iframe的情况和窗口的情况类似。

相关文章:

C#计算两个日期的相隔天数

DateTime start Convert.ToDateTime(dateStart.ToShortDateString()); DateTime end Convert.ToDateTime(dateEnd.ToShortDateString()); TimeSpan sp end.Subtract(start); int days sp.Days;转载于:https://www.cnblogs.com/weimingxin/p/8109234.html

.NET 端口监听

1.直接调用微软socket对象处理 static void Main(string[] args){try{IPAddress ip new IPAddress(new byte[] { 127, 0, 0, 1 });//在3721端口新建一个TcpListener对象TcpListener listener new TcpListener(ip, 3721); listener.Start();Console.WriteLine("started l…

微信小程序导航栏设置透明

使用的时Mpvue 在app.json 文件中设置 "window": {"navigationStyle": "custom"},

epub 电子书软件代码销售

epub 电子书软件代码销售本套代码用来读取epub 格式电子书。主要面向&#xff1a;有一定开发能力的人员&#xff0c;和有一定制作水平的朋友们。用途&#xff1a;自己开发学习&#xff0c;钻研&#xff0c;出appstore 应用&#xff0c;卖钱&#xff0c;加广告赚钱等。&#xff…

重新编译iptables

重新编译iptables一&#xff0e;重新编译后的内核版本为&#xff1a;<?xml:namespace prefix st1 ns "urn:schemas-microsoft-com:office:smarttags" />2.6.28.10重新编译后的iptables的版本为&#xff1a;1.4.4&#xff0c;新添加了layer7的模块&#xff0…

爬虫之Xpath详解

爬虫之Xpath详解 XPath介绍 XPath 是一门在 XML 文档中查找信息的语言。XPath 可用来在 XML 文档中对元素和属性进行遍历。 XPath 是 W3C XSLT 标准的主要元素&#xff0c;并且 XQuery 和 XPointer 都构建于 XPath 表达之上。 因此&#xff0c;对 XPath 的理解是很多高级 XML 应…

非常认同的《SEO优化大全》

1、每个网页标题简洁&#xff0c;不超过30字。  2、每个网页核心关键词不超过3个。如果可以&#xff0c;你要学会放弃。  3、最重要的关键词放在标题首位&#xff0c;依次类推。  4、网站的描述&#xff0c;简洁&#xff0c;明了&#xff0c;最开始和结束部分自然出现关键…

python中tornado的第一个例子

python中tornado的第一个例子 1 先安装tornado pip install tornado 2 新建tor.py 记住不能建立 tornado.py 这样的名字 不然会报错 ImportError: No module named tornado.ioloop; tornado is not a package import tornado.ioloop import tornado.webclass MainHandler(tor…

docker 安装和使用

目录 1、安装docker的官方网站 配置镜像加速器 查看docker安装的版本 重启docker 启动 docker 查看启动的状态 下载测试镜像 并且启动该容器 2、操作docker 镜像的常用命令 搜索镜像 下载镜像 列出镜像 删除本地镜像 保存镜像到本地 加载镜像到docker仓库 构…

不编译内核加载connlimit模块

转载于:https://blog.51cto.com/sookk8/280372

记录一下g++的编译选项

假设main.cpp,hello.h,hello.cpp,其中main.cpp调用了hello类中的方法 1 生成hello.so g -shared hello.cpp -olibhello.so 2 编译main.cpp,并链接,并指定运行时libhello.so的位置 g main.cpp -lhello -L./ -Wl,-rpath./ -o main 值得一提的是,如果采用带版本号的库,例如libhell…

JSP中是EL表达式与JSTL

EL语法&#xff1a;${ } EL取值来自于作用域对象 1.如何从指定作用域取值(默认从最小作用域取值)   pageScope、requestScope、sessionScope、applicationScope   ${pageScope.xxx }--- ${requestScope.xxx} --- ${sessionScope.xxx } 2.用EL取出请求参数中的数据   EL表…

数据库连接无法释放

问题已解决,发现是数据库连接无法释放,不知道是什么原因,同样的代码在本地就是好的,在服务器端就有问题,最后在连接串里加入以下语句解决问题. Poolingtrue; MAX Pool Size512;Min Pool Size50;Connection Lifetime30 转载于:https://www.cnblogs.com/tianciliangen/p/8110625.…

mpvue 引入自己创建的js 文件 到其他的文件中

1、mpvue 引入外部js 文件 中的方法 如果需要调用外部的js文件中的方法 需要按照以下的格式进行写 创建方法&#xff0c;将方法抛出 /** * 七牛上传文件 工具方法 **/ function getToken() {console.info("进来了"); } export {getToken }在其他的文件中使用 im…

DirectShow camera demo

我在编译SDK自带的Cameracapture的例子时&#xff0c;出现 生成: 0 已成功, 1 已失败, 0 最新, 0 已跳过 1> ------ 已启动生成: 项目: CameraCapture, 配置: Release Windows Mobile 5.0 Pocket PC SDK (ARMV4I) ------ 1> 正在链接... 1> graphmanager.obj : …

Uva 11400 - Lighting System Design (DP)

题目链接 https://cn.vjudge.net/problem/UVA-11400【题意】你的任务是设计一个照明系统&#xff0c;一共有n&#xff08;n<1000&#xff09;个灯泡可以选择&#xff0c;不同种类的灯必须使用不同的电源&#xff0c;但同种灯泡可以共用一个电源&#xff0c;每种灯泡有4个属性…

删除表中多余的重复记录,重复记录是根据单个字段(peopleId)来判断,只留有rowid最小的记录...

delete from people where rowid in (select min(rowid) from people group by peopleId having count(peopleId )>1)转载于:https://www.cnblogs.com/macT/p/10865224.html

微信表白墙 微信小程序 吐槽墙 表白墙 java 开发

目录 1 小程序展示 2 后台展示 3 技术栈 4 代码目录 5 第一版微信表白墙链接 1 小程序展示 2 后台展示 3 技术栈 java:Springboot mybatis mysql mpvue bootstrap dataTable echars 4 代码目录 5 第一版微信表白墙链接 https://blog.csdn.net/huyande123/article/det…

Sql存储过程加密和解密

可用于加密SQL存储过程或者触发器&#xff08;这是SQL Server本身提供的&#xff0c;也就是说这是微软的加密算法&#xff09; http://www.mscto.com 使用 WITH ENCRYPTION 选项 WITH ENCRYPTION 子句对用户隐藏存储过程的文本。下例创建加密过程&#xff0c;使用 sp_helptext …

C++向量类模板(支持实数向量与复数向量的各种运算)

2019独角兽企业重金招聘Python工程师标准>>> 头文件&#xff1a; /** Copyright (c) 2008-2011 Zhang Ming (M. Zhang), zmjerry163.com** This program is free software; you can redistribute it and/or modify it* under the terms of the GNU General Public L…

C# 篇基础知识11——泛型和集合

.NET提供了一级功能强大的集合类&#xff0c;实现了多种不同类型的集合&#xff0c;可以根据实际用途选择恰当的集合类型。 除了数组 Array 类定义在System 命名空间中外&#xff0c;其他的集合类都定义在System.Collections 命名空间中。为了方便、快捷地操纵集合元素&#xf…

React和vue的差异和相似地方

React 单向绑定&#xff08;加插件后&#xff0c;还是可以双向绑定&#xff09; Vue 双向绑定 组件化 1、 React&#xff0c;需要编写render函数&#xff0c; 2、 当React状态的状态state改变是render就会重新被调用&#xff0c; 重新计算全dom&#xff0c;然后对旧的dom就行对…

正则表达式相关方法

1 判断字符串中是否包含字母 /** * 使用正则表达式来判断字符串中是否包含字母 * param str 待检验的字符串 * return 返回是否包含 * true: 包含字母 ;false 不包含字母*/ public boolean judgeContainsStr(String str) { String regex".*[a-zA-Z].*"; Match…

Ajax Upload多文件上传插件翻译及中文演示

http://www.zhangxinxu.com/wordpress/?p342转载于:https://www.cnblogs.com/qiantuwuliang/archive/2010/03/19/1689800.html

[每日一讲] Python系列:Python概述

Python 序章 概述 Python 是弱类型动态解释型的面向对象高级语言&#xff0c;其具备面向对象的三大特点&#xff1a;封装、继承、多态。Python 代码运行时&#xff0c;其有一个编译过程&#xff0c;通过编译器生成 .pyc 字节码 文件&#xff08;为二进制文件&#xff09;&#…

微信公众号开发 微信消息回复开发 文本消息 图片消息开发

开发语言&#xff1a;java 实现功能&#xff1a;发送文字回复文字&#xff0c;发送图片回复图片、token验证、获取access_token等相关功能。 如图&#xff1a; 微信后台接口配置 &#xff0c;此为测试账号&#xff0c;正式设置也是一样的 项目地址&#xff1a;https://github…

[置顶]2010年东北大学ACM程序设计竞赛冬季校赛题解

8题只做出4题比较easy的题&#xff0c;而且做得挺麻烦&#xff0c;看来还要多练练。 AC的题如下 NEUOJ 1112 I Love Apple DescriptionSo many people love apple and there is a problem about apple.An Apple Word is a word that consists of only the letters A, P, L, an…

生成唯一序列号

写一个存储过程来实现&#xff1a; 转载于:https://www.cnblogs.com/hwgok/p/8136750.html

如何改变一个地图的Zoom单位

mapControl1.Map.Zoom new MapInfo.Geometry.Distance(mapControl1.Map.Zoom.value,MapInfo.Geometry.DistanceUnit.Kilometer);也可以分开写成如下格式&#xff1a;MapInfo.Geometry.Distance d new MapInfo.Geometry.Distance(1000, DistanceUnit.Kilometer);mapControl1.M…

canvas上的像素操作(图像复制,细调)

canvas上的像素操作(图像复制&#xff0c;细调) 总结 1、操作对象&#xff1a;ImageData 对象&#xff0c;其实是canvas的像素点集合 2、主要操作&#xff1a; var objctx.getImageData(0,0,100,100); ctx.putImageData(obj,110,0) 3、操作图片要放在站点才能正常操作&#xf…