原文地址

——这篇文章有点意思,可以扩展你对作用域和闭包的认识。

本文内容

  • 背景
  • 作用域
  • 闭包
    • 臭名昭著的循环问题
    • 自调用函数(匿名函数)
  • 其他

我认为,尝试向别人解释 JavaScript 作用域和闭包是很纠结的事情。

背景


有很多文章和博客都在试图解释的作用域(scope)和关闭(closure),但总体来说,我认为大多数都不是很清楚。此外,一些人想当然地认为,之前,每个人都已经大概用15种其他语言开发,而我的经验是,很多这样编写 JavaScript 代码的人都具有 HTML 和 CSS 背景,而不是 C 和 Java。

因此,本文的目标是,让每个人掌握什么是作用域和闭包,他们如何工作,特别是你如何可以从中受益。在阅读本文前,你需要理解变量和函数这些基本概念。

 

作用域(Scope)


作用域是指变量和函数可访问性在哪里,以及执行环境是什么。最基本的是,一个变量或函数可以定义在全局或局部作用域。变量具有所谓的函数作用域,函数跟变量具有相同的作用域。

全局(Global)作用域

当是全局的时候,意味着,在你的代码中,可以从任何地方访问。如下代码所示:

        var monkey = "Gorilla";
 
        function greetVisitor() {
            return alert("Hello dear blog reader!");
        }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

如果该代码执行在 Web 浏览器中,那么,函数的作用域是 window,因此,对运行在 Web 浏览器窗口中所有东西,该函数都是可用的。

局部(Local)作用域

与全局作用域相反,局部作用域只是在你某部分的代码中定义并访问,如一个函数。代码如下所示:

        function talkDirty() {
            var saying = "Oh, you little VB lover, you";
            return alert(saying);
        }
        alert(saying); // Throws an error

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

上面代码,变量 saying 只在 talkDirty 函数内可用。而在外边,更本没有定义。注意:如果声明 saying 前边没有 var 关键字,那么该变量将自动变成一个全局变量。

这也意味着,如果你有嵌套(nested)函数,那么,这个嵌套函数将可以访问包含其函数内的变量和函数:

        function saveName(firstName) {
            function capitalizeName() {
                return firstName.toUpperCase();
            }
            var capitalized = capitalizeName();
            return capitalized;
        }
        alert(saveName("Robert")); // Returns "ROBERT"

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

正如上面看到的,嵌套函数 capitalizeName 不需要任何参数传递,就可以完全访问它外边的 saveName 函数的参数 firstName。清楚起见,让我们看下面的例子:

        function siblings() {
            var siblings = ["John", "Liza", "Peter"];
            function siblingCount() {
                var siblingsLength = siblings.length;
                return siblingsLength;
            }
            function joinSiblingNames() {
                return "I have " + siblingCount() + " siblings:\n\n" + siblings.join("\n");
            }
            return joinSiblingNames();
        }
        alert(siblings()); // Outputs "I have 3 siblings: John Liza Peter"

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

上面代码,那两个嵌套函数都可以访问包含其函数内的 siblings 数组,并且,每个嵌套函数都可以同等地访问另一个嵌套函数(在这种情况下,joinSiblingNames 可以访问 siblingCount)。但是, siblingCount 函数中的变量 siblingsLength 只在它所在的函数可用,也就是作用域。

 

闭包(Closures)


现在,当你希望获得更好地掌握作用域是什么时,让我们向组合添加闭包。闭包是表达式,通常是函数,再一个某个上下文环境内进行变量设置。或者,为了尝试并使其更容易,涉及局部变量的内部函数创建闭包。例如:

        function add(x) {
            return function (y) {
                return x + y;
            };
        }
        var add5 = add(5);
        var no8 = add5(3);
        alert(no8); // Returns 8

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

发生了什么?

  1. add 函数被调用时,它返回了一个函数。
  2. 这个返回的函数关闭上下文环境,记住参数 x 在那个时候是什么(例如,上面代码的 5)。
  3. 当调用 add 函数的返回结果被分配给变量 add5 时,add5 函数总是知道 x 是什么,当 add5 被初始化创建时。
  4. add5 变量引用一个函数,它总是把传给它的参数加 5
  5. 这意味着,当用 3 调用 add5 时,它应该返回 3 加 5,等于 8。

因此,在 JavaScript 世界里,事实上,add5 函数实际像如下所示:

        function add5(y) {
            return 5 + y;
        }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

臭名昭著的循环问题

有多少次你创建一个循环,想以某种方式分配 i 的值,例如:给一个元素,有没有发现它只是返回的最后一个 i 的值?

  • 错误的引用

让我们看下错误的代码,它创建五个链接元素,每个元素的文本值为 i,并且每个元素的单击事件为弹出内容为 i 的 alert。把这五个元素追加到 document body:

        function addLinks() {
            for (var i = 0, link; i < 5; i++) {
                link = document.createElement("a");
                link.innerHTML = "Link " + i;
                link.onclick = function () {
                    alert(i);
                };
                document.body.appendChild(link);
            }
        }
        window.onload = addLinks;

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

每个元素都获得了正确的文本,例如“Link 0”、“Link 1”等等,但是你单击的每个链接,alert 中的值都是 5,这显然不对,为什么?原因在于,变量 i 以 1 递增,可 onclick 事件没有被执行,仅仅是应用到了元素,i 再增加 1。

因此,循环继续直到等于 5,这是 i 的最后一个值,此时,函数 addLinks 退出。之后,当 onclick 事件实际被触发时,只得到 i 的最后一个值。

  • 正确的引用

你所需要做的就是创建一个闭包,这样,当你把 i 值应用到元素的 onclick 事件时,就会在触发那个时刻得到 i 的准确值。如下所示:

        function addLinks() {
            for (var i = 0, link; i < 5; i++) {
                link = document.createElement("a");
                link.innerHTML = "Link " + i;
                link.onclick = function (num) {
                    return function () {
                        alert(num);
                    };
                } (i);
                document.body.appendChild(link);
            }
        }
        window.onload = addLinks;

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

上面代码就没有问题了。单击第一个创建的链接元素,alter 为 0;第二个为 1 等等。该解决方案是,应用到 onclick 事件的内部函数创建了一个闭包,在那里引用参数 num,也就是 i 的值。

自调用函数(Self-Invoking Functions)

自调用函数是那些自动执行的函数(匿名函数),并且创建它们自己的闭包,如下代码所示:

        (function () {
            var dog = "German Shepherd";
            alert(dog);
        })();
        alert(dog); // Returns undefined

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

dog 变量只在其作用域内可用。它可以解决我们上面的循环问题,而且这也是 Yahoo JavaScript Module Pattern 的基础。

Yahoo JavaScript Module Pattern

Yahoo JavaScript 模块模式的要点是,它使用了一个自调用函数来创建一个封闭,因此,使具有私有和公共的属性和方法成为可能。一个简单的例子,如下所示:

        var person = function () {
            // Private
            var name = "Robert";
            return {
                getName: function () {
                    return name;
                },
                setName: function (newName) {
                    name = newName;
                }
            };
        } ();
        alert(person.name); // Undefined
        alert(person.getName()); // "Robert"
        person.setName("Robert Nyman");
        alert(person.getName()); // "Robert Nyman"

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

这个代码就很优雅了。现在,你可以自己决定公开什么,隐藏什么了。变量 name 就是对外部隐藏的(在外部引用为 undefined),但可以通过 getNamesetName 函数访问,因为,它们创建了闭包,在里边引用了 name 变量。

 

其他


 

下载 Demo

JavaScript 作用域和闭包——另一个角度:扩展你对作用域和闭包的认识【翻译+整理】的更多相关文章

  1. javascript回调函数,闭包作用域,call,apply函数解决this的作用域问题

    在JavaScrip中,function是内置的类对象,也就是说它是一种类型的对象,可以和其它String.Array.Number.Object类的对象一样用于内置对象的管理.因为function实 ...

  2. JavaScript中函数作为另一个函数的参数的时候它存在于哪个作用域

    一直对函数作为参数被传递进另外一个函数理解的不是很清除.先看下这段代码吧: function test(fn){ var bar = 1; fn(); } var bar = 99; test(fun ...

  3. JavaScript 上下文环境和作用域,以及 call、apply 和 bind【转载+翻译+整理】

    --看到这篇文章,翻译国外的,虽说写得有点矫情,但总体来看,还是相当不错的- 本文内容 我在哪儿?你又是谁 ? this? 用 apply 和 call 掌控上下文环境 bind 之美 本文将说明上下 ...

  4. python基础----函数的定义和调用、return语句、变量作用域、传参、函数嵌套、函数对象、闭包、递归函数

    1.函数的定义: 函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段. 函数能提高应用的模块性,和代码的重复利用率.你已经知道Python提供了许多内建函数,比如print().但你也可 ...

  5. ASP.NET MVC WebApi 返回数据类型序列化控制(json,xml) 用javascript在客户端删除某一个cookie键值对 input点击链接另一个页面,各种操作。 C# 往线程里传参数的方法总结 TCP/IP 协议 用C#+Selenium+ChromeDriver 生成我的咕咚跑步路线地图 (转)值得学习百度开源70+项目

    ASP.NET MVC WebApi 返回数据类型序列化控制(json,xml)   我们都知道在使用WebApi的时候Controller会自动将Action的返回值自动进行各种序列化处理(序列化为 ...

  6. 我的第一个chrome扩展(1)——读样例,实现时钟

    学习chrome扩展开发: 与网页类似,需要的知识:html,javascript chrome扩展程序的构成: manifest.json:对扩展程序的整体描述文件 { "manifest ...

  7. 运用JavaScript构建你的第一个Metro式应用程序(onWindows 8)(二)

    原文 http://blog.csdn.net/zhangxin09/article/details/6793330 先前的学习中,我们已经了解了 Metro式的 JavaScript 应用程序大致如 ...

  8. 如何用原生js开发一个Chrome扩展程序

    原文地址:How to Build a Simple Chrome Extension in Vanilla JavaScript 开发一个Chrome扩展程序非常简单,只需要使用原生的js就可以完成 ...

  9. 《JavaScript 高级程序设计》第四章:变量、作用域和内存问题

    目录 变量的引用 执行环境及作用域 作用域链延长 块级作用域 垃圾回收机制 变量的引用 当一个变量保存了基本数据类型时,此时对于变量的操作(赋值,运算)就是操作这个基本数据的本身,就算是赋值操作,赋值 ...

随机推荐

  1. deeplearningbook-chinese

    https://exacity.github.io/deeplearningbook-chinese/

  2. ASP.NET Web API接受AngualrJS的QueryString的两种方式

    ASP.NET Web API如何接受来自AngualrJS的QueryString呢?本篇体验两种方式. 第一种方式:http://localhost:49705/api/products?sear ...

  3. 有关Delphi RTTI的一些文章

    Delphi RTTI 资料 Delphi 的RTTI机制浅探 Delphi XE的RTTI增强,动态Hook某些内部事件

  4. android 模拟器报 no CPU/ABI system image for target

    搭建完成Android开发环境后,在创建安卓模拟器的时候遇到了问题.这个问题就是图片中显示的no CPU/ABI system image available for this target还有no ...

  5. 格林第一季/全集Grimm迅雷下载

    本季Grimm Season 1 (2011) 第一季看点:该剧由<天使调查团>的一对制片组合Jim Kouf.David Greenwalt打造. 该剧根据<格林童话>中的原 ...

  6. 好汉两个半第一季/全集Two And A Half Men迅雷下载

    第一季 Two and a Half Men Season 1 (2003)看点:Charlie是一个潇洒自由的单身汉,但正面临离婚危机的兄弟Alan带着儿子Jake的突然来访完全打乱了Charlie ...

  7. MongoDB索引,性能分析

    索引的限制: 索引名称不能超过128个字符 每个集合不能超过64个索引 复合索引不能超过31列 MongoDB 索引语法 db.collection.createIndex({ <field&g ...

  8. 7z文件格式及其源码linux/windows编译

    7z文件格式及其源码的分析(二) 一. 准备工作: 1. 源码下载: 可以从官方中文主页下载:http://sparanoid.com/lab/7z/. 为了方便, 这里直接给出下载链接: http: ...

  9. mysqldump参数详细说明

    Mysqldump参数大全(参数来源于mysql5.5.19源码)   参数 参数说明 --all-databases  , -A 导出全部数据库. mysqldump  -uroot -p --al ...

  10. vmware桥接模式

    vmware桥接模式 桥接网络是指本地物理网卡和虚拟网卡通过VMnet0虚拟交换机进行桥接,物理网卡和虚拟网卡在拓扑图上处于同等地位,那么物理网卡和虚拟网卡就相当于处于同一个网段,虚拟交换机就相当于一 ...