3

我在 github 上发现了一个有趣的项目,它处理浏览器中的pdf 渲染

我试图阅读代码,因为我对这个主题很感兴趣,但我意识到我的 javascript 知识很差(不足)。

有如下结构:

var Obj = (function() {
    function constructor(type, value) {
    this.type = type;
    this.value = value;
    }

    constructor.prototype = {
    };

    var types = [
    "Bool", "Int", "Real", "String", "Name", "Null",
    "Array", "Dict", "Stream", "Ref",
    "Cmd", "Error", "EOF", "None"
    ];

    for (var i = 0; i < types.length; ++i) {
    var typeName = types[i];
    constructor[typeName] = i;
    constructor.prototype["is" + typeName] =
    (function (value) {
     return this.type == i &&
     (typeof value == "undefined" || value == this.value);
     });
    }

    constructor.prototype.lookup = function(key) {
      function lookup(key) {
        if (!(this.value.contains(key)))
          return Obj.nullObj;
        return this.value.get(key);
      }
    }

    Object.freeze(constructor.trueObj = new constructor(constructor.Bool, true));
    Object.freeze(constructor.falseObj = new constructor(constructor.Bool, false));
    Object.freeze(constructor.nullObj = new constructor(constructor.Null));
    Object.freeze(constructor.errorObj = new constructor(constructor.Error));
    Object.freeze(constructor.prototype);
    Object.freeze(constructor);

    return constructor;
})();

您可以在上面的链接中看到更多。

您能否告诉我一些可以学习的资源,以便能够轻松理解项目中的代码,甚至更好地为以后的项目做出贡献?

4

5 回答 5

6

在外面工作,这里的第一个大概念是匿名函数。

var Obj = (function() { /* do work */})();

简单地说,我们正在创建一个匿名函数,然后立即执行它,并将匿名函数的返回值分配给一个名为 Obj 的变量。

为什么会有人想做?

在这种情况下,它用于创建私有范围。javascript 中的局部变量的作用域是定义它们的函数。例如:

function test() {
    var a = 10;
}

// a is not defined here.

在最后一个例子中,a真的只存在于定义它的函数的范围内。Javascript 在这方面有点棘手,因为通过省略var 关键字,您可以定义一个全局变量。

因此,在您给出的示例中,他们使用此匿名函数为将要使用的某些变量构建范围,但最终希望在函数完成执行后立即被丢弃。

下一个:

var Obj = (function() {
    function constructor(type, value) {
        this.type = type;
        this.value = value;
    }

    // SNIP
})();

这将创建一个名为 的新函数constructor。重要的是要注意 javascript 函数是一等对象,这意味着它们的工作方式与任何其他对象非常相似,并且可以分配给变量。此函数的作用域是匿名函数。因此,试图constructor超出其功能范围是行不通的。例如

var Obj = (function() {
    function constructor(type, value) {
        this.type = type;
        this.value = value;
    }

    // SNIP
})();

typeof(constructor) // <= undefined

到目前为止,如果您要执行到目前为止的代码片段,那么Obj将是未定义的。现在让我们略过一点结束,看看返回。

var Obj = (function() {
    function constructor(type, value) {
        this.type = type;
        this.value = value;
    }

    // SNIP

    return constructor;
})();

因此,当调用匿名函数时,它会返回构造函数。这个被传回的函数被分配给Obj. 这会将构造函数交回函数的本地范围之外,并分配给变量。然后你就可以调用它了

var Obj = (function() {
    function constructor(type, value) {
        this.type = type;
        this.value = value;
    }

    // SNIP

    return constructor;
})();

var o1 = new Obj("t", "v");
o1.type // <= "t"
o1.value // <= "v"

接下来我们有一条有趣的线

var Obj = (function() {
    function constructor(type, value) {
    this.type = type;
    this.value = value;
    }

    constructor.prototype = { };

    // SNIP

    return constructor;
})();       

这会将构造函数的原型设置为空对象。解释原型的细节是本文的范围,但过于简单的是原型定义了可用于由构造函数创建的对象的实例方法。单个“原型”在之间共享,并将用于定义可用于通过调用构造的对象的方法new Obj()

接下来我们有一个本地定义的数组

var types = [
    "Bool", "Int", "Real", "String", "Name", "Null",
    "Array", "Dict", "Stream", "Ref",
    "Cmd", "Error", "EOF", "None"
];

请记住,因为我们在函数内部,所以这个变量绑定在外部匿名函数的范围内。

接下来我们遍历那个数组,并设置一些东西。

for (var i = 0; i < types.length; ++i) {
    var typeName = types[i];
    constructor[typeName] = i;
    constructor.prototype["is" + typeName] =
        (function (value) {
            return this.type == i &&
            (typeof value == "undefined" || value == this.value);
        });
}

这里发生了两件有趣的事情。首先,它设置 'static' 属性constructor,然后在构造函数的原型上创建一个新函数。这个函数被称为"is" + typeName。所以我们应该生成一堆实例方法,命名为:“isBool”、“isInt”、“isReal”等。

constructor.prototype.lookup = function(key) {
  function lookup(key) {
    if (!(this.value.contains(key)))
      return Obj.nullObj;
    return this.value.get(key);
  }
}

接下来我们定义另一个实例方法lookup,并做一些工作。

最后,我们从构造函数中创建一些静态属性,并将它们冻结(因此它们不能被更改或扩展)

一旦一切都说完了,Obj, 应该指向一个构造函数,我们应该可以这样说:

var myType = new Obj("MyType",undefined);
myType.isBool(undefined) //instance method
Obj.Bool  // static property

无论如何,我希望这有助于解释一些正在使用的概念。最大的收获应该是 afunction可以用来控制范围,并且函数是一等函数,并且可以像变量一样被传递。您还可以使用点表示法 ( obj.property) 或括号表示法 ( obj["property"]) 引用对象的属性。

还有很多东西要学,所有的书建议在这个线程中都是可靠的。如果没有提到,我也会推荐Haverbeke 的 Eloquent JavaSript

于 2011-08-23T18:58:11.933 回答
2

Douglas Crockford 的书JavaScript: The Good Parts是一个很好的地方,可以让您了解 JavaScript 的强大功能,同时让您远离丑陋(或完全危险)的部分。 他的网站还收集了有关该语言的有趣文章。我推荐两者。

于 2011-08-23T18:16:49.087 回答
1

我可以参考一些链接

我可以命名一个javascript函数并立即执行它吗?

http://devlicio.us/blogs/sergio_pereira/archive/2009/02/09/javascript-5-ways-to-call-a-function.aspx

我希望你能和他们一起学习

于 2011-08-23T18:18:51.307 回答
1

我发现 Douglas Crockford ( http://www.crockford.com/ )、John Resig ( http://ejohn.org/blog/ ) 的博客对中高级概念很有用。查看其他人的代码(就像您正在做的一样)也会有所帮助。归根结底,虽然没有什么比实际尝试这个概念更好,但值得信赖的 Firebug 控制台仍然是最好的。

于 2011-08-23T18:22:58.347 回答