Javascript 中的高级构造

发布于 2024-12-01 07:24:50 字数 1562 浏览 1 评论 0原文

我在 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;
})();

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

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

I found one interesting project on github which deals with pdf rendering in the browser.

I tried to read the code because I'm interested in this topic but I realized that my javascript knowledge is poor (insuficient).

There are constructs like:

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;
})();

You can see more of them in the link above.

Could you please advise me some resources which to study to be able to understand the code in the project with ease and even better to contribute later to the project?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

揽清风入怀 2024-12-08 07:24:50

从外到内工作,这里的第一个大概念是匿名函数。

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);
        });
}

这里发生了两件有趣的事情。首先,它在构造函数中设置一个“静态”属性,然后
在构造函数的原型上创建一个新函数。该函数称为“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

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

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

Working outside in, the first big concept here are anonymous funcitons.

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

Simply, put, we are making an anonymous function, and then immediately execturing it,
and assigning the return from the anonymous function to an variable named Obj.

Why would anyone want to do it?

In this case, it is used to create a private scope. Local variables in javascript are
scoped to the function where they are defined. For example:

function test() {
    var a = 10;
}

// a is not defined here.

In the last example, a really only exists inside the scope of the function that
defined it. Javascript is a little tricky this regard because by omitting the var
keyword, you can define a global variable.

So in the example you've given, they are using this anonymous function to build a
scope for some variables that will be used, but will ultimately want to be thrown
away as soon as the function is finished executing.

Next:

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

    // SNIP
})();

This creates a new function called constructor. Its important to note that javascript functions
are first-class objects, which means they work a lot like any other object, and can be assigned
to a variable. This function is scoped to the anonymous function. So trying to get constructor out
side of the scope of its function, doesn't work. For example

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

    // SNIP
})();

typeof(constructor) // <= undefined

So far, if you were to execute the snippits so far, then Obj would have been undefined. Now
let's skip ahead a bit to end, and look at the return.

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

    // SNIP

    return constructor;
})();

So when the anonymous function gets invoked, it returns the constructor. This function that gets
passed back is assigned to Obj. This hands back the constructor, out of the local scope of the
function, and assigns to the variable. You would then be able to invoke it

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"

Next we've got an interesting line

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

    constructor.prototype = { };

    // SNIP

    return constructor;
})();       

This sets the prototype for the constructor to an empty object. Explaining the details of prototypes is
a bit of the scope of this post, but an over-simplication is that a prototype defines the instance methods
that are available to an object that is created by a constructor. A single 'prototype' is shared between
and will be used to define the methods that will be available to the objects that are constructed by
calling new Obj().

Next we have a locally defined array

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

Remember because we are inside of a function, this variable is bound within the outer anonymous function's scope.

Next we loop through that array, and set up some stuff.

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);
        });
}

Two things interesting happen here. First, it sets a 'static' property off of the constructor, and then
creates a new function on the constructor's prototype. This function is called "is" + typeName. So we should
generate a bunch of instance methods named stuff like: "isBool", "isInt", "isReal", and so on.

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

Next we define another instance method called lookup and does some work.

Lastly we create some static properties off of our constructor, and freeze them (so they can't be changed or extended)

Once its all said and done, Obj, should point to a constructor function, and we should be able to say things like:

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

Anyway, I hope that helped a little bit explaining a few of the concepts that were being used. The big take-away should
be that a function can be used to control scope, and that functions are First-class functions, and can be handed around
like variables. You can also reference a property off a object using dot notation (obj.property) or bracket notation
(obj["property"]).

There are a bunch of more things to learn, and all of the book suggestions are solid in this thread. If it hasn't been mentioned I
would also recommend Eloquent JavaSript by Haverbeke.

混浊又暗下来 2024-12-08 07:24:50

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

Douglas Crockford's book JavaScript: The Good Parts is a great place to gain an appreciation of the power in JavaScript, while steering you away from the ugly (or downright dangerous) parts. His website also has a collection of interesting articles about the language. I recommend both.

寂寞陪衬 2024-12-08 07:24:50

我找到了 Douglas Crockford(http://www.crockford.com/)、John Resig(< a href="http://ejohn.org/blog/" rel="nofollow">http://ejohn.org/blog/) 对于中级到高级概念很有用。查看其他人的代码(就像您正在做的一样)也会有所帮助。归根结底,没有什么比实际尝试这个概念更好的了,为此值得信赖的 Firebug 控制台仍然是最好的。

I find the blogs by Douglas Crockford(http://www.crockford.com/), John Resig(http://ejohn.org/blog/) useful for intermediate to advanced concepts. Looking at other people's code(just like what you are doing) can also be helpful. At the end of the day though nothing beats actually trying out the concept and for that the trusty Firebug console is still the best.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文